ucftools/matlab/@ini/ini.m

241 lines
7.8 KiB
Matlab

classdef ini < handle
% Low-level utilities for INI files.
properties (Access = public)
File % file name
IOMode % file opened in read-only or read-write mode?
FileSize % file size
NumSection % maximum number of datasets in this file (over all time steps)
Verbosity % verbose output?
end
%%
properties (Access = private)
% File info
fileID
fileBeg
fileEnd
ioflag
tarflag
content
end
%% ------------------------------------------------------------------------%%
%% CONSTRUCORS/DESTRUCTORS %%
%% ------------------------------------------------------------------------%%
methods (Access = public)
function obj = ini(varargin)
% [obj] = ini(varargin)
% Default contructor
% Input
% ? verbosity verbose output? (default: no)
par = inputParser;
addOptional(par,'verbosity',0,@isnumeric);
parse(par,varargin{:});
obj.resetPublicProperties();
obj.resetPrivateProperties();
obj.setVerbosity(par.Results.verbosity);
end
function delete(obj)
% obj.delete()
% Object destructor
obj.close();
end
end
%% ------------------------------------------------------------------------%%
%% INITIALIZATION METHODS %%
%% ------------------------------------------------------------------------%%
methods(Access=public)
function open(obj,fname)
% obj.open()
% Opens an INI file.
% Input
% fname file name
obj.File = fname;
obj.IOMode = 'read';
obj.ioflag = 'r';
obj.tarflag = false;
obj.fileID = fopen(obj.File,obj.ioflag);
obj.fileBeg = 0;
fseek(obj.fileID,0,'eof');
obj.fileEnd = ftell(obj.fileID);
obj.FileSize = obj.fileEnd-obj.fileBeg;
obj.parse();
end
function opentar(obj,ptr)
% obj.opentar(ptr)
% Opens a subfile from tar in read-only mode.
% Input
% ptr pointer: [fid,first byte,number of bytes]
obj.File = 'tar-mode'; % Set generic file name
obj.IOMode = 'read'; % abstract IO mode
obj.ioflag = 'r'; % internal IO mode
obj.tarflag = true; % reading from tar archive?
% Set file ID to tar file ID
obj.fileID = ptr(1);
if obj.fileID<0
error('Unable to access file: %s',obj.File);
end
obj.fileBeg = ptr(2);
obj.fileEnd = ptr(2)+ptr(3);
obj.FileSize = ptr(3);
obj.parse();
end
end
methods(Access=public)
function close(obj)
% obj.close()
% Closes a file.
tarmode = obj.tarflag;
obj.resetPublicProperties();
obj.resetPrivateProperties();
if obj.fileID<0 || tarmode
return;
end
status = fclose(obj.fileID);
if status<0
warning('Error while closing: %d',status);
return;
end
obj.fileID = -1;
end
function setVerbosity(obj,flag)
% obj.setVerbosity(flag)
% Sets verbosity
% Input
% flag '1' -> verbose output
obj.Verbosity = flag;
end
function [data] = getContent(obj)
% [data] = obj.getContent()
% Get the entire content of the INI file.
% Output
% data entire content of file as structure
data = obj.content;
end
function [data] = getSection(obj,section)
% [data] = obj.getSection(section)
% Get the content of a single section of the INI file.
% Input
% section name of the requested section
% Output
% data content of one section of file as structure
if isfield(obj.content,section)
data = obj.content.(section);
else
error('Section not found: %s',name);
end
end
function [data] = getEntry(obj,section,entry)
% [data] = obj.getEntry(section,entry)
% Get the value of a single entry within the INI file.
% Input
% section name of the requested section
% entry name of the entry within requested section
% Output
% data value of the requested entry
if ~isfield(obj.content,section)
error('Section not found: %s',section);
elseif ~isfield(obj.content.(section),entry)
error('Entry not found: %s',entry);
else
data = obj.content.(section).(entry);
end
end
function [data] = listSections(obj)
% [data] = obj.listSections()
% Get a list of section names.
% Output
% data cell array with section names
data = fieldnames(obj.content);
end
function [data] = listEntries(obj,section)
% [data] = obj.listEntries(section)
% Get a list of entry names within a section..
% Input
% section name of the requested section
% Output
% data cell array with section names
data = fieldnames(obj.content.(section));
end
end
%% ------------------------------------------------------------------------%%
%% PRIVATE STATIC METHODS %%
%% ------------------------------------------------------------------------%%
methods(Access=private)
function parse(obj)
fseek(obj.fileID,obj.fileBeg,'bof');
% Construct a struct with content of file
obj.content = [];
curSection = '';
while ftell(obj.fileID)<obj.fileEnd
str = strtrim(fgetl(obj.fileID));
% Check for empty lines and comments (; or #)
if isempty(str)
continue;
end
if (str(1)==';')
continue;
end
if (str(1)=='#')
continue;
end
% Check for section
if (str(1)=='[') && (str(end)==']')
% This is a section: create a structure
curSection = ini.getUniqueVarname(str(2:end-1));
obj.content.(curSection) = [];
else
% This is not a section: create structure entry
[curMember,curValue] = strtok(str,'=');
curValue = ini.trimValue(curValue);
curMember = ini.getUniqueVarname(curMember);
% We now have the field name and the corresponding value as strings.
% Convert the value to a numeric value if possible.
[tmp,flag] = str2num(curValue);
if flag
curValue = tmp;
end
% Add this structure to the current section
if ~isempty(curSection)
obj.content.(curSection).(curMember) = curValue;
else
obj.content.(curMember) = curValue;
end
end
end
obj.NumSection = numel(fieldnames(obj.content));
end
function resetPublicProperties(obj)
obj.File = [];
obj.FileSize = [];
obj.IOMode = [];
obj.NumSection = [];
obj.Verbosity = [];
end
function resetPrivateProperties(obj)
obj.fileBeg = [];
obj.fileEnd = [];
obj.ioflag = [];
obj.tarflag = [];
obj.content = [];
end
end
%% ------------------------------------------------------------------------%%
%% PRIVATE STATIC METHODS %%
%% ------------------------------------------------------------------------%%
methods(Access=private,Static)
function str = trimValue(str)
str = strtrim(str);
if strcmpi(str(1),'=')
str(1)=[];
end
str = strtrim(str);
end
function varname = getUniqueVarname(varname)
%tmp = matlab.lang.makeValidName(varname);
%varname = matlab.lang.makeUniqueStrings(tmp,who,namelengthmax);
varname = strrep(varname,'-','_');
varname = genvarname(varname);
end
end
end