📄 tffio.m
字号:
srdata = lower(sprule.datatype);
srcond = sprule.cond;
srexpr = sprule.varname;
srform = sprule.format;
% double check type and field
if ~strcmpi(srtype, 'flist') || ...
~strcmpi(srfldn, fieldname)
error( ...
'BVQXtools:BadTFFSpec', ...
'Field type or name don''t match FLIST spec.' ...
);
end
% depending on what data
switch (lower(srdata))
% built-in
case { ...
'char', 'int8', 'int16', 'int32', ...
'uint8', 'uint16', 'uint32', ...
'single', 'double', 'logical'}
% first to double then to value
try
eval(['tffcont.' srexpr '=' ...
lower(srdata) '(str2num(fieldval));']);
catch
error( ...
'BVQXtools:EvaluationError', ...
'Could not store %s field in %s.', ...
srdata, srexpr ...
);
end
% handle strings specifically
case {'cstring', 'string'}
% format with delimiter, remove it then
if ~isempty(srform) && ...
length(fieldval) > 1 && ...
srform(1) == srform(end) && ...
fieldval(1) == srform(1) && ...
fieldval(end) == srform(1)
fieldval = fieldval(2:end - 1);
end
% simply copy content
try
eval(['tffcont.' srexpr '=fieldval;']);
catch
error( ...
'BVQXtools:EvaluationError', ...
'Could not store string field in %s.', ...
rexpr ...
);
end
% special
otherwise
% try custom conversion (only once)
try
eval(['tffcont.' srexpr ...
'=string2' srdata '(fieldval);']);
catch
error( ...
'BVQXtools:ConversionError', ...
'Could not convert string=>%s field for %s.', ...
srdata, srexpr ...
);
end
end
% increase line counter and check
linec = linec + 1;
if linec > linecount
break;
end
% get next content to check and perform check
fieldline = deblank(linecont{linec});
[flinea{1:3}] = ...
regexpi(fieldline, fieldmlist);
flinet = flinea{3};
end
% skip N rules
case {'skipn'}
% extra check dim field
if isempty(regexpi(prule.dim, '^\d+$'))
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid SKIPN dim (N) given.' ...
);
end
% conditional skip
if ~isempty(rcond)
performskip = false;
try
eval(['if ' rcond ',performskip=true;end']);
catch
error( ...
'BVQXtools:EvaluationError', ...
'Error evaluating SKIPN condition: ''%s''.', ...
rcond ...
);
end
% if not skip, continue with next rule
if ~performskip
rulec = rulec + 1;
continue;
end
end
% get dim
try
eval(['nskipdim = [' prule.dim '];']);
catch
error( ...
'BVQXtools:ConversionError', ...
'Error converting dimensions.' ...
);
end
nskiptgt = rulec + nskipdim;
nskiplst = nskiptgt - 1;
% skip too high ?
if nskiplst > rules
error( ...
'BVQXtools:BadTFFSpec', ...
'Can''t skip %d rules at rule %d/%d.', ...
nskipdim, rulec, rules ...
);
end
% correctly leave any loops on our way
for trulec = rulec:nskiplst
% get shortcut for rule
tstruct = rule(trulec);
% eloop
if strcmpi(tstruct.type, 'eloop')
% matching with last entered loop
if ~strcmp(tstruct.varname, loopx{end})
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid LOOP (ELOOP) nesting found: ''%s''.', ...
tstruct.varname ...
);
end
% pop loop
loopi(end) = [];
loopx(end) = [];
loopc = loopc - 1;
end
end
% set new rulec
rulec = nskiptgt;
% write a line
case {'wrtln'}
% check condition first
if ~isempty(rcond)
try
eval(['dowrtln=false;if ' rcond ',dowrtln=true;end']);
catch
error( ...
'BVQXtools:EvaluationError', ...
'Error evaluating SKIPN condition: ''%s''.', ...
rcond ...
);
end
% if not skip, continue with next rule
if ~dowrtln
rulec = rulec + 1;
continue;
end
end
% reading
if ~writemode
% empty line & skip empty lines, do nothing
if ldc && ...
isempty(rexpr)
rulec = rulec + 1;
continue;
end
% simply skip next line
linec = linec + 1;
% writing
else
% evaluate line?
if ~isempty(rexpr) && ...
rexpr(1) == '%' && ...
rexpr(end) == '%'
rexpr = eval(rexpr(2:end-1), '''''');
if isempty(rexpr)
rexpr = strrep(lasterr, char(10), ' ');
end
end
% write line
linecont{end + 1} = rexpr;
linecount = linecount + 1;
end
% exit of a loop
case {'xloop'}
% check name of ENTERED loops
if ~any(strcmp(rexpr, loopx))
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid XLOOP token found: ''%s''.', ...
rexpr ...
);
end
% check cond, whether loop has to be left
try
if isempty(rcond)
leaveloop = true;
else
eval([ ...
'leaveloop=false;if ' rcond ',leaveloop=true;end']);
end
catch
error( ...
'BVQXtools:EvaluationFailed', ...
'Error evaluating XLOOP condition: ''%s''.', ...
rcond ...
);
end
% if we're leaving loop
if leaveloop
% find loop to leave
leaveloop = find(strcmp(rexpr, loopx));
% set rulec to lastloop of this loop
rulec = loopi(leaveloop).lastrule;
% clear loopi and loopx, set loopc
loopi(leaveloop:end) = [];
loopx(leaveloop:end) = [];
loopc = leaveloop - 1;
end
% otherwise bail out
otherwise
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid rule type ''%s''.', ...
rtype ...
);
end
% increase next rule counter
rulec = rulec + 1;
end
% remaining input in read mode
if ~writemode && ...
linec <= linecount
tffcont.REMAININGLINES = linecont(linec:end);
% remaining content in write mode
elseif writemode && ...
isfield(tffcont, 'REMAININGLINES') && ...
iscell(tffcont.REMAININGLINES) && ...
~isempty(tffcont.REMAININGLINES) && ...
ischar(tffcont.REMAININGLINES{1})
linecont(end + 1:end + numel(tffcont.REMAININGLINES)) = ...
tffcont.REMAININGLINES(:);
end
% forcemode catch
catch % catch forcemode
if forcemode
% only warning
warning( ...
'BVQXtools:ForcedOverride', ...
'Forceing error override: ''%s''.', ...
lasterr ...
);
% otherwise
else
% simply don't allow this
rethrow(lasterror);
end
end % of try forcemode
% writing file
if writemode
try
binwrite(filename, gluetostring(linecont, lds, true));
catch
error( ...
'BVQXtools:ErrorWritingFile', ...
'Could not write output file, %s: ''%s''.', ...
filename, lasterr ...
);
end
end
% print in verbosemode
if ~writemode && ...
verbosemode
disp(tffcont);
end
% give correct output
if ~writemode
varargout{1} = tffcont;
else
if nargout > 0
varargout = cell(1, nargout);
varargout{1} = tffcont;
end
end
% %%%% sub function
function parsed = tff_parsecode(parsed)
% shortcut
if isempty(parsed) || ...
~any(parsed == '$' | parsed == '@')
return;
end
% find first occurance
pattern = '(\$|\@)([a-z][a-z_0-9]*)';
[pcm{1:3}] = regexpi(parsed, pattern);
pcm = pcm{3};
% loop until tokens are gone
while ~isempty(pcm)
% what kind of token
switch (parsed(pcm{1}(1, 1)))
% replace $var
case {'$'}
parsed = [ ...
parsed(1:pcm{1}(1, 1) - 1) 'namevars.' ...
parsed(pcm{1}(2, 1):end)];
% @var
case {'@'}
parsed = [ ...
parsed(1:pcm{1}(1, 1) - 1) 'tffcont.' ...
parsed(pcm{1}(2, 1):end)];
end
% rematch
[pcm{1:3}] = regexpi(parsed, pattern);
pcm = pcm{3};
end
% any occurance of $$/@@
parsed = strrep(strrep(parsed, '@@', 'tffcont'), '$$', 'namevars');
% end of function parsedcode = tff_parsecode(unparsed, nv, cnt)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -