From 72d45e2806ca715a956deb66c76fc2d9c0cb1569 Mon Sep 17 00:00:00 2001
From: fangq <fangq@786e58fb-9377-0410-9ff7-e4ac0ac0635c>
Date: Sun, 16 Oct 2011 04:10:44 +0000
Subject: [PATCH] use real file instead of link

git-svn-id: http://svn.code.sf.net/p/iso2mesh/code/trunk/jsonlab@313 786e58fb-9377-0410-9ff7-e4ac0ac0635c
---
 loadjson.m | 402 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 savejson.m | 277 ++++++++++++++++++++++++++++++++++++
 2 files changed, 679 insertions(+)
 create mode 100644 loadjson.m
 create mode 100644 savejson.m

diff --git a/loadjson.m b/loadjson.m
new file mode 100644
index 0000000..7a6bd96
--- /dev/null
+++ b/loadjson.m
@@ -0,0 +1,402 @@
+function data = loadjson(fname)
+%
+% data=loadjson(fname)
+%
+% parse a JSON (JavaScript Object Notation) file or string
+%
+% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
+%            date: 2011/09/09
+%         Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
+%            date: 2009/11/02
+%         François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
+%            date: 2009/03/22
+%         Joel Feenstra: http://www.mathworks.com/matlabcentral/fileexchange/20565
+%            date: 2008/07/03
+%
+% input:
+%      fname: input file name, if fname contains "{}" or "[]", fname
+%      will be interpreted as a JSON string
+%
+% output:
+%      dat: a cell array, where {...} blocks are converted into cell arrays,
+%           and [...] are converted to arrays
+%
+% license:
+%     BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details 
+%
+% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
+%
+
+global pos inStr len  esc index_esc len_esc isoct arraytoken
+
+if(regexp(fname,'[\{\}\]\[]','once'))
+   string=fname;
+elseif(exist(fname,'file'))
+   fid = fopen(fname,'rt');
+   string = fscanf(fid,'%c');
+   fclose(fid);
+else
+   error('input file does not exist');
+end
+
+pos = 1; len = length(string); inStr = string;
+isoct=exist('OCTAVE_VERSION');
+arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
+
+% String delimiters and escape chars identified to improve speed:
+esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]');
+index_esc = 1; len_esc = length(esc);
+
+if pos <= len
+    switch(next_char)
+        case '{'
+            data = parse_object;
+        case '['
+            data = parse_array;
+        otherwise
+            error_pos('Outer level structure must be an object or an array');
+    end
+end % if
+
+len=length(data);
+if(len==1 && isstruct(data))
+    data=jstruct2array(data);
+else
+    for i=1:len
+        if(isstruct(data(i)))
+            data(i)=jstruct2array(data(i));
+        end
+    end
+end
+
+%%-------------------------------------------------------------------------
+function newdata=jstruct2array(data)
+fn=fieldnames(data);
+newdata=data;
+for i=1:length(fn) % depth-first
+    if(isstruct(getfield(data,fn{i})))
+        newdata=setfield(newdata,fn{i},jstruct2array(getfield(data,fn{i})));
+    end
+end
+if(~isempty(strmatch('x_ArrayType_',fn)) && ~isempty(strmatch('x_ArrayData_',fn)))
+    newdata=cast(data.x_ArrayData_,data.x_ArrayType_);
+    iscpx=0;
+    if(~isempty(strmatch('x_ArrayIsComplex_',fn)))
+        if(data.x_ArrayIsComplex_)
+           iscpx=1;
+        end
+    end
+    if(~isempty(strmatch('x_ArrayIsSparse_',fn)))
+        if(data.x_ArrayIsSparse_)
+            if(iscpx && size(newdata,2)==4)
+                newdata(:,3)=complex(newdata(:,3),newdata(:,4));
+            end
+            if(~isempty(strmatch('x_ArraySize_',fn)))
+                dim=data.x_ArraySize_;
+                newdata=sparse(newdata(:,1),newdata(:,2),newdata(:,3),dim(1),prod(dim(2:end)));
+            else
+                newdata=sparse(newdata(:,1),newdata(:,2),newdata(:,3));
+            end
+        end
+    elseif(~isempty(strmatch('x_ArraySize_',fn)))
+        if(iscpx && size(newdata,2)==2)
+             newdata=complex(newdata(:,1),newdata(:,2));
+        end
+        newdata=reshape(newdata(:),data.x_ArraySize_);
+    end
+end
+
+%%-------------------------------------------------------------------------
+function object = parse_object
+    parse_char('{');
+    object = [];
+    if next_char ~= '}'
+        while 1
+            str = parseStr;
+            if isempty(str)
+                error_pos('Name of value at position %d cannot be empty');
+            end
+            parse_char(':');
+            val = parse_value;
+            eval( sprintf( 'object.%s  = val;', valid_field(str) ) );
+            if next_char == '}'
+                break;
+            end
+            parse_char(',');
+        end
+    end
+    parse_char('}');
+
+%%-------------------------------------------------------------------------
+
+function object = parse_array % JSON array is written in row-major order
+global pos inStr 
+    parse_char('[');
+    object = cell(0, 1);
+    if next_char ~= ']'
+        endpos=matching_bracket(inStr,pos);
+        arraystr=['[' inStr(pos:endpos)];
+        arraystr(find(arraystr==sprintf('\n')))=[];
+        arraystr(find(arraystr==sprintf('\r')))=[];
+        arraystr=regexprep(arraystr,'\]\s*,','];');
+        arraystr=regexprep(arraystr,'"_NaN_"','NaN');
+        arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf');
+        try
+           if(isoct && regexp(arraystr,'"','once'))
+                error('Octave eval can produce empty cells for JSON-like input');
+           end
+           object=eval(arraystr);
+           pos=endpos;
+        catch
+         while 1
+            val = parse_value;
+            object{end+1} = val;
+            if next_char == ']'
+                break;
+            end
+            parse_char(',');
+         end
+        end
+    end
+    try
+        object=cell2mat(object')';
+        if(size(object,1)>1 && ndims(object)==2)
+            object=object';
+        end
+    catch
+    end
+    parse_char(']');
+
+%%-------------------------------------------------------------------------
+
+function parse_char(c)
+    global pos inStr len
+    skip_whitespace;
+    if pos > len || inStr(pos) ~= c
+        error_pos(sprintf('Expected %c at position %%d', c));
+    else
+        pos = pos + 1;
+        skip_whitespace;
+    end
+
+%%-------------------------------------------------------------------------
+
+function c = next_char
+    global pos inStr len
+    skip_whitespace;
+    if pos > len
+        c = [];
+    else
+        c = inStr(pos);
+    end
+
+%%-------------------------------------------------------------------------
+
+function skip_whitespace
+    global pos inStr len
+    while pos <= len && isspace(inStr(pos))
+        pos = pos + 1;
+    end
+
+%%-------------------------------------------------------------------------
+function str = parseStr
+    global pos inStr len  esc index_esc len_esc
+ % len, ns = length(inStr), keyboard
+    if inStr(pos) ~= '"'
+        error_pos('String starting with " expected at position %d');
+    else
+        pos = pos + 1;
+    end
+    str = '';
+    while pos <= len
+        while index_esc <= len_esc && esc(index_esc) < pos
+            index_esc = index_esc + 1;
+        end
+        if index_esc > len_esc
+            str = [str inStr(pos:len)];
+            pos = len + 1;
+            break;
+        else
+            str = [str inStr(pos:esc(index_esc)-1)];
+            pos = esc(index_esc);
+        end
+        nstr = length(str); switch inStr(pos)
+            case '"'
+                pos = pos + 1;
+                if(~isempty(str))
+                    if(strcmp(str,'_Inf_'))
+                        str=Inf;
+                    elseif(strcmp(str,'-_Inf_'))
+                        str=-Inf;
+                    elseif(strcmp(str,'_NaN_'))
+                        str=NaN;
+                    end
+                end
+                return;
+            case '\'
+                if pos+1 > len
+                    error_pos('End of file reached right after escape character');
+                end
+                pos = pos + 1;
+                switch inStr(pos)
+                    case {'"' '\' '/'}
+                        str(nstr+1) = inStr(pos);
+                        pos = pos + 1;
+                    case {'b' 'f' 'n' 'r' 't'}
+                        str(nstr+1) = sprintf(['\' inStr(pos)]);
+                        pos = pos + 1;
+                    case 'u'
+                        if pos+4 > len
+                            error_pos('End of file reached in escaped unicode character');
+                        end
+                        str(nstr+(1:6)) = inStr(pos-1:pos+4);
+                        pos = pos + 5;
+                end
+            otherwise % should never happen
+                str(nstr+1) = inStr(pos), keyboard
+                pos = pos + 1;
+        end
+    end
+    error_pos('End of file while expecting end of inStr');
+
+%%-------------------------------------------------------------------------
+
+function num = parse_number
+    global pos inStr len isoct
+    currstr=inStr(pos:end);
+    numstr=0;
+    if(isoct~=0)
+        numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end');
+        [num, one] = sscanf(currstr, '%f', 1);
+        delta=numstr+1;
+    else
+        [num, one, err, delta] = sscanf(currstr, '%f', 1);
+        if ~isempty(err)
+            error_pos('Error reading number at position %d');
+        end
+    end
+    pos = pos + delta-1;
+
+%%-------------------------------------------------------------------------
+
+function val = parse_value
+    global pos inStr len
+    true = 1; false = 0;
+
+    switch(inStr(pos))
+        case '"'
+            val = parseStr;
+            return;
+        case '['
+            val = parse_array;
+            return;
+        case '{'
+            val = parse_object;
+            return;
+        case {'-','0','1','2','3','4','5','6','7','8','9'}
+            val = parse_number;
+            return;
+        case 't'
+            if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true')
+                val = true;
+                pos = pos + 4;
+                return;
+            end
+        case 'f'
+            if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false')
+                val = false;
+                pos = pos + 5;
+                return;
+            end
+        case 'n'
+            if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null')
+                val = [];
+                pos = pos + 4;
+                return;
+            end
+    end
+    error_pos('Value expected at position %d');
+%%-------------------------------------------------------------------------
+
+function error_pos(msg)
+    global pos inStr len
+    poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
+    if poShow(3) == poShow(2)
+        poShow(3:4) = poShow(2)+[0 -1];  % display nothing after
+    end
+    msg = [sprintf(msg, pos) ': ' ...
+    inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
+    error( ['JSONparser:invalidFormat: ' msg] );
+
+%%-------------------------------------------------------------------------
+
+function str = valid_field(str)
+global isoct
+% From MATLAB doc: field names must begin with a letter, which may be
+% followed by any combination of letters, digits, and underscores.
+% Invalid characters will be converted to underscores, and the prefix
+% "x_" will be added if first character is not a letter.
+    if ~isletter(str(1)) || str(1)>'z'
+        str = ['x' str];
+    end
+    if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return;  end
+    if(~isoct)
+        str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
+    else
+        pos=regexp(str,'[^0-9A-Za-z_]');
+        if(isempty(pos)) return; end
+        str0=str;
+        pos0=[0 pos(:)' length(str)];
+        str='';
+        for i=1:length(pos)
+            str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
+        end
+        if(pos(end)~=length(str))
+            str=[str str0(pos0(end-1)+1:pos0(end))];
+        end
+    end
+    %str(~isletter(str) & ~('0' <= str & str <= '9')) = '_';
+
+%%-------------------------------------------------------------------------
+function endpos = matching_quote(str,pos)
+len=length(str);
+while(pos<len)
+    if(str(pos)=='"')
+        if(~(pos>1 && str(pos-1)=='\'))
+            endpos=pos;
+            return;
+        end        
+    end
+    pos=pos+1;
+end
+
+%%-------------------------------------------------------------------------
+function endpos = matching_bracket(str,pos)
+global arraytoken
+level=1;
+endpos=0;
+bpos=arraytoken(arraytoken>=pos);
+tokens=str(bpos);
+len=length(tokens);
+pos=1;
+while(pos<=len)
+    c=tokens(pos);
+    if(c==']')
+        level=level-1;
+        if(level==0)
+            endpos=bpos(pos);
+            return
+        end
+    end
+    if(c=='[')
+        level=level+1;
+    end
+    if(c=='"')
+        pos=matching_quote(tokens,pos+1);
+    end
+    pos=pos+1;
+end
+if(endpos==0) 
+    error('unmatched "]"');
+end
+
diff --git a/savejson.m b/savejson.m
new file mode 100644
index 0000000..d967286
--- /dev/null
+++ b/savejson.m
@@ -0,0 +1,277 @@
+function json=savejson(rootname,obj,varargin)
+%
+% json=savejson(rootname,obj,opt)
+%
+% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
+% Object Notation) string
+%
+% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
+%            date: 2011/09/09
+%
+% input:
+%      rootname: name of the root-object, if set to '', will use variable name
+%      obj: a MATLAB object (array, cell, cell array, struct, struct array)
+%      opt: a struct for additional options, use [] if all use default
+%        opt can have the following fields (first in [.|.] is the default)
+%        opt.FloatFormat ['%.10g'|string]: format to show each numeric element
+%                         of a 1D/2D array;
+%        opt.ArrayIndent [1|0]: if 1, output explicit data array with
+%                         precedent indentation; if 0, no indentation
+%        opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
+%                         array in JSON array format; if sets to 1, an
+%                         array will be shown as a struct with fields
+%                         "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
+%                         sparse arrays, the non-zero elements will be
+%                         saved to _ArrayData_ field in triplet-format i.e.
+%                         (ix,iy,val) and "_ArrayIsSparse_" will be added
+%                         with a value of 1; for a complex array, the 
+%                         _ArrayData_ array will include two columns 
+%                         (4 for sparse) to record the real and imaginary 
+%                         parts, and also "_ArrayIsComplex_":1 is added. 
+%        opt.ParseLogical [0|1]: if this is set to 1, logical array elem
+%                         will use true/false rather than 1/0.
+%
+% output:
+%      json: a string in the JSON format (see http://json.org)
+%
+% examples:
+%      a=struct('node',[1  9  10; 2 1 1.2], 'elem',[9 1;1 2;2 3],...
+%           'face',[9 01 2; 1 2 3; NaN,Inf,-Inf], 'author','FangQ');
+%      savejson('mesh',a)
+%      savejson('',a,struct('ArrayIndent',0,'FloatFormat','\t%.5g'))
+%
+% license:
+%     BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
+%
+% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
+%
+
+varname=inputname(2);
+if(~isempty(rootname))
+   varname=rootname;
+end
+rootisarray=0;
+rootlevel=1;
+if((isnumeric(obj) || islogical(obj) || ischar(obj)) && isempty(rootname))
+    rootisarray=1;
+    rootlevel=0;
+    varname='';
+end
+json=obj2json(varname,obj,rootlevel,varargin{:});
+if(rootisarray)
+    json=sprintf('%s\n',json);
+else
+    json=sprintf('{\n%s\n}\n',json);
+end
+
+%%-------------------------------------------------------------------------
+function txt=obj2json(name,item,level,varargin)
+
+cname=class(item);
+
+if(iscell(item))
+    txt=cell2json(name,item,level,varargin{:});
+elseif(isstruct(item))
+    txt=struct2json(name,item,level,varargin{:});
+elseif(ischar(item))
+    txt=str2json(name,item,level,varargin{:});
+else
+    txt=mat2json(name,item,level,varargin{:});
+end
+
+%%-------------------------------------------------------------------------
+function txt=cell2json(name,item,level,varargin)
+txt='';
+if(~iscell(item))
+        error('input is not a cell');
+end
+
+dim=size(item);
+len=numel(item); % let's handle 1D cell first
+padding1=repmat(sprintf('\t'),1,level-1);
+padding0=repmat(sprintf('\t'),1,level);
+if(len>1) txt=sprintf('%s"%s": [\n',padding0, name); name=''; end
+for i=1:len
+    txt=sprintf('%s%s%s',txt,padding1,obj2json(name,item{i},level+(len>1),varargin{:}));
+    if(i<len) txt=sprintf('%s%s',txt,sprintf(',\n')); end
+end
+if(len>1) txt=sprintf('%s\n%s]',txt,padding0); end
+
+%%-------------------------------------------------------------------------
+function txt=struct2json(name,item,level,varargin)
+txt='';
+if(~isstruct(item))
+	error('input is not a struct');
+end
+len=numel(item);
+padding1=repmat(sprintf('\t'),1,level);
+padding0=repmat(sprintf('\t'),1,level+1);
+sep=',';
+
+if(~isempty(name)) 
+    if(len>1) txt=sprintf('%s"%s": [\n',padding1,name); end
+else
+    if(len>1) txt=sprintf('%s[\n',padding1); end
+end
+for e=1:len
+  names = fieldnames(item(e));
+  if(~isempty(name) && len==1)
+        txt=sprintf('%s%s"%s": {\n',txt,padding1, name); 
+  else
+        txt=sprintf('%s%s{\n',txt,repmat(sprintf('\t'),1,level+(len>1))); 
+  end
+  if(~isempty(names))
+    for i=1:length(names)
+	    txt=sprintf('%s%s',txt,obj2json(names{i},getfield(item(e),...
+             names{i}),level+1+(len>1),varargin{:}));
+        if(i<length(names)) txt=sprintf('%s%s',txt,','); end
+        txt=sprintf('%s%s',txt,sprintf('\n'));
+    end
+  end
+  txt=sprintf('%s%s}',txt,repmat(sprintf('\t'),1,level+(len>1)));
+  if(e==len) sep=''; end
+  if(e<len) txt=sprintf('%s%s',txt,sprintf(',\n')); end
+end
+if(len>1) txt=sprintf('%s\n%s]',txt,padding1); end
+
+%%-------------------------------------------------------------------------
+function txt=str2json(name,item,level,varargin)
+global isoct
+txt='';
+if(~ischar(item))
+        error('input is not a string');
+end
+len=size(item,1);
+sep=sprintf(',\n');
+
+padding1=repmat(sprintf('\t'),1,level);
+padding0=repmat(sprintf('\t'),1,level+1);
+
+if(~isempty(name)) 
+    if(len>1) txt=sprintf('%s"%s": [\n',padding1,name); end
+else
+    if(len>1) txt=sprintf('%s[\n',padding1); end
+end
+for e=1:len
+    if(isoct)
+        val=regexprep(item(e,:),'\\','\\');
+        val=regexprep(val,'"','\"');
+        val=regexprep(val,'^"','\"');
+    else
+        val=regexprep(item(e,:),'\\','\\\\');
+        val=regexprep(val,'"','\\"');
+        val=regexprep(val,'^"','\\"');
+    end
+    if(len==1)
+        obj=['"' name '": ' '"',val,'"'];
+	if(isempty(name)) obj=['"',val,'"']; end
+        txt=sprintf('%s%s%s%s',txt,repmat(sprintf('\t'),1,level),obj);
+    else
+        txt=sprintf('%s%s%s%s',txt,repmat(sprintf('\t'),1,level+1),['"',val,'"']);
+    end
+    if(e==len) sep=''; end
+    txt=sprintf('%s%s',txt,sep);
+end
+if(len>1) txt=sprintf('%s\n%s%s',txt,padding1,']'); end
+
+%%-------------------------------------------------------------------------
+function txt=mat2json(name,item,level,varargin)
+if(~isnumeric(item) && ~islogical(item))
+        error('input is not an array');
+end
+
+padding1=repmat(sprintf('\t'),1,level);
+padding0=repmat(sprintf('\t'),1,level+1);
+
+if(length(size(item))>2 || issparse(item) || ~isreal(item) || jsonopt('ArrayToStruct',0,varargin{:}))
+    if(isempty(name))
+    	txt=sprintf('%s{\n%s"_ArrayType_": "%s",\n%s"_ArraySize_": %s,\n',...
+              padding1,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') );
+    else
+    	txt=sprintf('%s"%s": {\n%s"_ArrayType_": "%s",\n%s"_ArraySize_": %s,\n',...
+              padding1,name,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') );
+    end
+else
+    if(isempty(name))
+    	txt=sprintf('%s%s',padding1,matdata2json(item,level+1,varargin{:}));
+    else
+    	txt=sprintf('%s"%s": %s',padding1,name,matdata2json(item,level+1,varargin{:}));
+    end
+    return;
+end
+dataformat='%s%s%s%s%s';
+
+if(issparse(item))
+    [ix,iy]=find(item);
+    data=full(item(find(item)));
+    if(~isreal(item))
+       data=[real(data(:)),imag(data(:))];
+       txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sprintf(',\n'));
+    end
+    txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sprintf(',\n'));
+    if(find(size(item)==1))
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
+           matdata2json([ix,data],level+2,varargin{:}), sprintf('\n'));
+    else
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
+           matdata2json([ix,iy,data],level+2,varargin{:}), sprintf('\n'));
+    end
+else
+    if(isreal(item))
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
+            matdata2json(item(:)',level+2,varargin{:}), sprintf('\n'));
+    else
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sprintf(',\n'));
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
+            matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), sprintf('\n'));
+    end
+end
+txt=sprintf('%s%s%s',txt,padding1,'}');
+
+%%-------------------------------------------------------------------------
+function txt=matdata2json(mat,level,varargin)
+if(size(mat,1)==1)
+    pre='';
+    post='';
+    level=level-1;
+else
+    pre=sprintf('[\n');
+    post=sprintf('\n%s]',repmat(sprintf('\t'),1,level-1));
+end
+if(isempty(mat))
+    txt='null';
+    return;
+end
+floatformat=jsonopt('FloatFormat','%.10g',varargin{:});
+formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],\n')]];
+
+if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1)
+    formatstr=[repmat(sprintf('\t'),1,level) formatstr];
+end
+txt=sprintf(formatstr,mat');
+txt(end-1:end)=[];
+if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1)
+   txt=regexprep(txt,'1','true');
+   txt=regexprep(txt,'0','false');
+end
+%txt=regexprep(mat2str(mat),'\s+',',');
+%txt=regexprep(txt,';',sprintf('],\n['));
+% if(nargin>=2 && size(mat,1)>1)
+%     txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']);
+% end
+txt=[pre txt post];
+if(any(isinf(mat(:))))
+    txt=regexprep(txt,'([-+]*)Inf','"$1_Inf_"');
+end
+if(any(isnan(mat(:))))
+    txt=regexprep(txt,'NaN','"_NaN_"');
+end
+
+%%-------------------------------------------------------------------------
+function val=jsonopt(key,default,varargin)
+val=default;
+if(nargin<=2) return; end
+opt=varargin{1};
+if(isstruct(opt) && isfield(opt,key))
+    val=getfield(opt,key);
+end
-- 
GitLab