📄 tffparse.m
字号:
function tffspec = tffparse(tffcont)
% tffparse - parse TFF text file format description
%
% FORMAT: tffspec = tffparse(tffcont)
%
% Input fields:
%
% tffcont 1xN char: TFF specification file name or content
%
% Output fields:
%
% tffspec 1x1 struct with TFF specification
%
% See also tffdocu, tffio
% Version: v0.7a
% Build: 7072014
% Date: Jul-20 2007, 2:05 PM CEST
% Author: Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools
tffversion = 'v0.7a';
% argument check
if ...
nargin < 1 || ...
~ischar(tffcont) || ...
isempty(tffcont)
error( ...
'BVQXtools:BadArgument', ...
'Invalid TFF specification argument given.' ...
);
end
% check for line feeds and try to read file
if numel(tffcont) ~= length(tffcont) || ...
~any(tffcont == char(10))
if exist(tffcont, 'file') ~= 2
error( ...
'BVQXtools:FileNotFound', ...
'Either invalid content or file not found.' ...
);
end
% read tffspec
try
tffcont = asciiread(tffcont);
catch
rethrow(lasterror);
end
end
% check content
if isempty(strfind(tffcont, 'TextFileFormat'))
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid TFF specification file/content given.' ...
);
end
% split into lines
tfflines = splittocell(tffcont(:)', char([10, 13]), 1, 1);
% remove empty ones and comments
for lc = length(tfflines):-1:1
% deblank lines
tffline = deblank(tfflines{lc});
% remove comment
tffcomm = find(tffline == '#');
if ~isempty(tffcomm)
tffline(tffcomm(1):end) = [];
tfflines{lc} = tffline;
end
% if is empty, remove line
if isempty(tffline)
tfflines(lc) = [];
continue;
end
end
% initialize content
tffspec = struct;
tffspec.FFTYPE = 'TFF';
tffspec.TFFVERSION = tffversion;
tffspec.AfterReadCode = '';
tffspec.ArrayFormat = '%-12s';
tffspec.BeforeWriteCode = '';
tffspec.CustomDelimiters = {};
tffspec.Description = 'All files';
tffspec.Extensions = {};
tffspec.FieldDelimCollapse = true;
tffspec.FieldDelimiters = {char(9)};
tffspec.Filetype = 'Custom TFF file';
tffspec.FilenameMatch = {};
tffspec.LineDelimiters = {char([13,10]), char(10)};
tffspec.ListOfFields = cell2struct(cell(0,0,0), {}, 3);
tffspec.Loops = struct;
tffspec.Magic = cell2struct(cell(0,0,0), {}, 3);
tffspec.NewFileCode = '';
tffspec.ParagraphArrays = true;
tffspec.SkipEmptyLines = true;
tffspec.Variables = struct;
% parse content
lc = 1;
llc = length(tfflines);
while (lc <= llc)
% regexpi line matches '<TOKEN>:<VALUE>' ?
tffline = tfflines{lc};
[tlmatcht{1:3}] = regexpi( ...
tffline, '^([a-z][a-z_0-9]*)\:\s*(.*)\s*$');
tlmatcht = tlmatcht{3};
% continue with next line if no match
lc = lc + 1;
if isempty(tlmatcht)
continue;
end
% handle those sections/keywords:
tffkey = tffline(tlmatcht{1}(1, 1):tlmatcht{1}(1, 2));
tffval = tffline(tlmatcht{1}(2, 1):tlmatcht{1}(2, 2));
switch (lower(tffkey))
% after read code snippet
case {'afterreadcode'}
% find "EndAfterReadCode"
endline = llc + 1;
for slc = lc:llc
if ~isempty(regexpi(tfflines{slc}, '^endafterreadcode'))
endline = slc - 1;
break;
end
end
% check endline
if endline > llc
error( ...
'BVQXtools:BadTFFSpec', ...
'Unclosed AfterReadCode section in TFF spec.' ...
);
end
% generate and check code snippet
codesnip = gluetostring(tfflines(lc:endline), char(10), 1);
tcodesnip = codesnip;
tcodesnip(tcodesnip == '$' | tcodesnip == '@') = [];
try
eval(['if 1==0,' tcodesnip ';end']);
catch
error( ...
'BVQXtools:BadTFFSpec', ...
'Syntax error detected in AfterReadCode: ''%s''.', ...
lasterr ...
);
end
% store code
tffspec.AfterReadCode = codesnip;
% array element format (sprintf)
case {'arrayformat'}
% check format
testformat = sprintf(tffval, sprintf('%.3f', pi));
if isempty(regexp(testformat, '3\.14', 'once'))
error( ...
'BVQXtools:BadTFFSpec', ...
'Bad ArrayFormat specified: ''%s''.', ...
tffval ...
);
end
% set format
tffspec.ArrayFormat = tffval;
% before write code snippet
case {'beforewritecode'}
% find "EndBeforeWriteCode"
endline = llc + 1;
for slc = lc:llc
if ~isempty(regexpi(tfflines{slc}, '^endbeforewritecode'))
endline = slc - 1;
break;
end
end
% check endline
if endline > llc
error( ...
'BVQXtools:BadTFFSpec', ...
'Unclosed BeforeWriteCode section in TFF spec.' ...
);
end
% generate and check code snippet
codesnip = gluetostring(tfflines(lc:endline), char(10), 1);
tcodesnip = codesnip;
tcodesnip(tcodesnip == '$' | tcodesnip == '@') = [];
try
eval(['if 1==0,' tcodesnip ';end']);
catch
error( ...
'BVQXtools:BadTFFSpec', ...
'Syntax error detected in BeforeWriteCode: ''%s''.', ...
lasterr ...
);
end
% store code
tffspec.BeforeWriteCode = codesnip;
% custom delimiters
case {'customdelimiters'}
try
% evaluate list
eval(['tffspec.CustomDelimiters=' tffval ';']);
% check list syntax
if isempty(tffspec.CustomDelimiters) || ...
~iscell(tffspec.CustomDelimiters)
tffspec.CustomDelimiters = {};
warning( ...
'BVQXtools:BadTFFSpec', ...
'Empty or malformed CustomDelimiters: ''%s''.', ...
tffval ...
);
end
% check list content
delimlst = tffspec.CustomDelimiters(:)';
for clcc = 1:length(delimlst)
if ~ischar(delimlst{clcc})
delimlst{clcc} = char(delimlst{clcc}(:)');
end
end
% put back to struct
tffspec.CustomDelimiters = delimlst;
% on error
catch
% bail out
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid CustomDelimiters list: ''%s''.', ...
tffval ...
);
end
% file open description
case {'description'}
tffspec.Description = splittocell(tffval, ';,', 1, 1);
% valid extensions list
case {'extensions'}
tffspec.Extensions = splittocell(tffval, ';,. ', 1, 1);
% collapse field delimiters
case {'fielddelimcollapse'}
try
tffspec.FieldDelimCollapse = logical(eval(tffval));
catch
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid FieldDelimCollapse value given: ''%s''.', ...
tffval ...
);
end
% field delimiters
case {'fielddelimiters'}
try
% evaluate list
eval(['tffspec.FieldDelimiters=' tffval ';']);
% check list syntax
if isempty(tffspec.FieldDelimiters) || ...
~iscell(tffspec.FieldDelimiters)
tffspec.FieldDelimiters = {char(9)};
warning( ...
'BVQXtools:BadTFFSpec', ...
'Empty or malformed FieldDelimiters: ''%s''.', ...
tffval ...
);
end
% check list content
delimlst = tffspec.FieldDelimiters(:)';
for clcc = 1:length(delimlst)
if ~ischar(delimlst{clcc})
delimlst{clcc} = char(delimlst{clcc}(:)');
end
end
% put back to struct
tffspec.FieldDelimiters = delimlst;
% on error
catch
% bail out
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid FieldDelimiters list: ''%s''.', ...
tffval ...
);
end
% valid extensions list
case {'filenamematch'}
tffspec.FilenameMatch = splittocell(tffval, ';, ', 1, 1);
% line delimiters
case {'linedelimiters'}
try
% evaluate list
eval(['tffspec.LineDelimiters=' tffval ';']);
% check list syntax
if isempty(tffspec.LineDelimiters) || ...
~iscell(tffspec.LineDelimiters)
tffspec.LineDelimiters = {char([13, 10]),char(9)};
warning( ...
'BVQXtools:BadTFFSpec', ...
'Empty or malformed LineDelimiters: ''%s''.', ...
tffval ...
);
end
% check list content
delimlst = tffspec.LineDelimiters(:)';
for clcc = 1:length(delimlst)
if ~ischar(delimlst{clcc})
delimlst{clcc} = char(delimlst{clcc}(:)');
end
end
% put back to struct
tffspec.LineDelimiters = delimlst;
% on error
catch
% bail out
error( ...
'BVQXtools:BadTFFSpec', ...
'Invalid LineDelimiters list: ''%s''.', ...
tffval ...
);
end
% list of fields
case {'listoffields'}
% find "EndListOfFields" line
endline = llc + 1;
for slc = (lc + 1):llc
if ~isempty(regexpi(tfflines{slc}, '^endlistoffields'))
endline = slc - 1;
break;
end
end
blc = lc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -