From cf573262eb12c1d1dc3668913c1f902e3452f566 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Mon, 5 Jun 2023 09:04:47 -0400 Subject: [PATCH] support blosc2 meta compressors --- blosc2decode.m | 50 +++ blosc2encode.m | 43 ++ jdatadecode.m | 14 +- jdataencode.m | 8 +- savebj.m | 2 +- savejson.m | 1016 +++++++++++++++++++++++---------------------- varargin2struct.m | 29 +- 7 files changed, 634 insertions(+), 528 deletions(-) create mode 100644 blosc2decode.m create mode 100644 blosc2encode.m diff --git a/blosc2decode.m b/blosc2decode.m new file mode 100644 index 0000000..b2ca7aa --- /dev/null +++ b/blosc2decode.m @@ -0,0 +1,50 @@ +function varargout = blosc2decode(varargin) +% +% output = blosc2decode(input,codec) +% output = blosc2decode(input) +% or +% output = blosc2decode(input,info) +% +% Decompressing an blosc2-compressed byte-stream to recover the original data +% This function depends on the ZMat toolbox (http://github.com/fangq/zmat) +% +% authors:Qianqian Fang (q.fang neu.edu) +% +% input: +% input: a string, int8/uint8 vector or numerical array to store blosc2-compressed data +% codec: if the 2nd input is a string, it is treated as a compression method that +% blosc2 supports, it can be one of: +% 'blosc2blosclz', 'blosc2lz4', 'blosc2lz4hc', 'blosc2zlib' and 'blosc2zstd' +% if no codec is specified, 'blosc2blosclz' method is assumed +% info (optional): a struct produced by the zmat/blosc2encode function during +% compression; if not given, the inputs/outputs will be treated as a +% 1-D vector +% +% output: +% output: the decompressed byte stream stored in a uint8 vector; if info is +% given, output will restore the original data's type and dimensions +% +% examples: +% [bytes, info]=blosc2encode(eye(10)); +% orig=blosc2decode(bytes,info); +% +% 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) +% + +if (nargin == 0) + error('you must provide at least 1 input'); +end +if (exist('zmat', 'file') == 2 || exist('zmat', 'file') == 3) + if (nargin >= 2 && ischar(varargin{2})) + [varargout{1:nargout}] = zmat(varargin{1}, 0, varargin{2:end}); + elseif (nargin > 1) + [varargout{1:nargout}] = zmat(varargin{1}, varargin{2:end}); + else + [varargout{1:nargout}] = zmat(varargin{1}, 0, 'blosc2blosclz', varargin{2:end}); + end +else + error('you must install ZMat toolbox to use this feature: http://github.com/NeuroJSON/zmat'); +end diff --git a/blosc2encode.m b/blosc2encode.m new file mode 100644 index 0000000..4733267 --- /dev/null +++ b/blosc2encode.m @@ -0,0 +1,43 @@ +function varargout = blosc2encode(varargin) +% +% output = blosc2encode(input) +% or +% [output, info] = blosc2encode(input) +% +% Compress a string or a numerical array using LZ4-compression +% +% This function depends on the ZMat toolbox (http://github.com/fangq/zmat) +% +% authors:Qianqian Fang (q.fang neu.edu) +% +% input: +% input: the original data, can be a string, a numerical vector or array +% +% output: +% output: the compressed byte stream stored in a uint8 vector +% info: (optional) a struct storing the metadata of the input, see "help zmat" for details +% +% examples: +% [bytes, info]=blosc2encode(eye(10)); +% orig=blosc2decode(bytes,info); +% +% 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) +% + +if (nargin == 0) + error('you must provide at least 1 input'); +end + +if (exist('zmat', 'file') == 2 || exist('zmat', 'file') == 3) + if (nargin > 1 && ischar(varargin{2})) + [varargout{1:nargout}] = zmat(varargin{1}, 1, varargin{2:end}); + else + [varargout{1:nargout}] = zmat(varargin{1}, 1, 'blosc2blosclz', varargin{2:end}); + end + return +else + error('you must install ZMat toolbox to use this feature: http://github.com/NeuroJSON/zmat'); +end diff --git a/jdatadecode.m b/jdatadecode.m index 6511b05..ba8a466 100644 --- a/jdatadecode.m +++ b/jdatadecode.m @@ -126,8 +126,14 @@ if(isfield(data,N_('_ArrayZipType_'))) zipmethod=data(j).(N_('_ArrayZipType_')); end - if(ismember(zipmethod,{'zlib','gzip','lzma','lzip','lz4','lz4hc','base64'})) - decompfun=str2func([zipmethod 'decode']); + if(ismember(zipmethod,{'zlib','gzip','lzma','lzip','lz4','lz4hc','base64'}) || ~isempty(regexp(zipmethod,'^blosc2', 'once'))) + decodeparam={}; + if(~isempty(regexp(zipmethod,'^blosc2', 'once'))) + decompfun=@blosc2decode; + decodeparam={zipmethod}; + else + decompfun=str2func([zipmethod 'decode']); + end arraytype=data(j).(N_('_ArrayType_')); chartype=0; if(strcmp(arraytype,'char') || strcmp(arraytype,'logical')) @@ -135,9 +141,9 @@ arraytype='uint8'; end if(needbase64 && strcmp(zipmethod,'base64')==0) - ndata=reshape(typecast(decompfun(base64decode(data(j).(N_('_ArrayZipData_')))),arraytype),dims); + ndata=reshape(typecast(decompfun(base64decode(data(j).(N_('_ArrayZipData_'))),decodeparam{:}),arraytype),dims); else - ndata=reshape(typecast(decompfun(data(j).(N_('_ArrayZipData_'))),arraytype),dims); + ndata=reshape(typecast(decompfun(data(j).(N_('_ArrayZipData_')),decodeparam{:}),arraytype),dims); end if(chartype) ndata=char(ndata); diff --git a/jdataencode.m b/jdataencode.m index 43d5af3..691d445 100644 --- a/jdataencode.m +++ b/jdataencode.m @@ -314,12 +314,16 @@ end if(~isempty(zipmethod) && numel(item)>minsize) - compfun=str2func([zipmethod 'encode']); + compfun=str2func([regexprep(zipmethod,'blosc2[a-z0-9]+','blosc2') 'encode']); newitem.(N('_ArrayZipType_'))=lower(zipmethod); if(~isfield(newitem,N('_ArrayZipSize_'))) newitem.(N('_ArrayZipSize_'))=size(newitem.(N('_ArrayData_'))); end - newitem.(N('_ArrayZipData_'))=compfun(typecast(newitem.(N('_ArrayData_'))(:).','uint8')); + if(strcmp(zipmethod,'blosc2')) + newitem.(N('_ArrayZipData_'))=compfun(typecast(newitem.(N('_ArrayData_'))(:).','uint8'), zipmethod); + else + newitem.(N('_ArrayZipData_'))=compfun(typecast(newitem.(N('_ArrayData_'))(:).','uint8')); + end newitem=rmfield(newitem,N('_ArrayData_')); if(varargin{1}.base64) newitem.(N('_ArrayZipData_'))=char(base64encode(newitem.(N('_ArrayZipData_')))); diff --git a/savebj.m b/savebj.m index 51770f4..d0a1f5f 100644 --- a/savebj.m +++ b/savebj.m @@ -192,7 +192,7 @@ dozip=opt.compression; if(~isempty(dozip)) - if(~ismember(dozip,{'zlib','gzip','lzma','lzip','lz4','lz4hc'})) + if (~ismember(dozip, {'zlib', 'gzip', 'lzma', 'lzip', 'lz4', 'lz4hc'}) && isempty(regexp(dozip,'^blosc2', 'once'))) error('compression method "%s" is not supported',dozip); end if(exist('zmat','file')~=2 && exist('zmat','file')~=3) diff --git a/savejson.m b/savejson.m index e48db7c..8d9a772 100644 --- a/savejson.m +++ b/savejson.m @@ -1,4 +1,4 @@ -function output=savejson(rootname,obj,varargin) +function output = savejson(rootname, obj, varargin) % % json=savejson(obj) % or @@ -36,10 +36,10 @@ % 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. +% 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. % NestArray [0|1]: If set to 1, use nested array constructs % to store N-dimensional arrays; if set to 0, % use the annotated array format defined in the @@ -50,14 +50,14 @@ % numerical element will be shown without a square % bracket, unless it is the root object; if 0, square % brackets are forced for any numerical arrays. -% SingletCell [1|0]: if 1, always enclose a cell with "[]" +% SingletCell [1|0]: if 1, always enclose a cell with "[]" % even it has only one element; if 0, brackets % are ignored when a cell has only 1 element. % ForceRootName [0|1]: when set to 1 and rootname is empty, savejson -% will use the name of the passed obj variable as the -% root object name; if obj is an expression and -% does not have a name, 'root' will be used; if this -% is set to 0 and rootname is empty, the root level +% will use the name of the passed obj variable as the +% root object name; if obj is an expression and +% does not have a name, 'root' will be used; if this +% is set to 0 and rootname is empty, the root level % will be merged down to the lower level. % Inf ['"$1_Inf_"'|string]: a customized regular expression pattern % to represent +/-Inf. The matched pattern is '([-+]*)Inf' @@ -68,27 +68,27 @@ % JSONP [''|string]: to generate a JSONP output (JSON with padding), % for example, if opt.JSONP='foo', the JSON data is % wrapped inside a function call as 'foo(...);' -% UnpackHex [1|0]: convert the 0x[hex code] output by loadjson +% UnpackHex [1|0]: convert the 0x[hex code] output by loadjson % back to the string form % SaveBinary [1|0]: 1 - save the JSON file in binary mode; 0 - text mode. % Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs) -% Compression 'zlib', 'gzip', 'lzma', 'lzip', 'lz4' or 'lz4hc': specify array +% Compression 'zlib', 'gzip', 'lzma', 'lzip', 'lz4' or 'lz4hc': specify array % compression method; currently only supports 6 methods. The -% data compression only applicable to numerical arrays +% data compression only applicable to numerical arrays % in 3D or higher dimensions, or when ArrayToStruct % is 1 for 1D or 2D arrays. If one wants to % compress a long string, one must convert % it to uint8 or int8 array first. The compressed % array uses three extra fields -% "_ArrayZipType_": the opt.Compression value. +% "_ArrayZipType_": the opt.Compression value. % "_ArrayZipSize_": a 1D integer array to % store the pre-compressed (but post-processed) -% array dimensions, and +% array dimensions, and % "_ArrayZipData_": the "base64" encoded -% compressed binary array data. -% CompressArraySize [100|int]: only to compress an array if the total +% compressed binary array data. +% CompressArraySize [100|int]: only to compress an array if the total % element count is larger than this number. -% CompressStringSize [400|int]: only to compress a string if the total +% CompressStringSize [400|int]: only to compress a string if the total % element count is larger than this number. % FormatVersion [3|float]: set the JSONLab output version; since % v2.0, JSONLab uses JData specification Draft 1 @@ -98,22 +98,22 @@ % Encoding ['']: json file encoding. Support all encodings of % fopen() function % Append [0|1]: if set to 1, append a new object at the end of the file. -% Endian ['n'|'b','l']: Endianness of the output file ('n': native, +% Endian ['n'|'b','l']: Endianness of the output file ('n': native, % 'b': big endian, 'l': little-endian) % PreEncode [1|0]: if set to 1, call jdataencode first to preprocess % the input data before saving % BuiltinJSON [0|1]: if set to 1, this function attempts to call % jsonencode, if presents (MATLAB R2016b or Octave -% 6) first. If jsonencode does not exist or failed, +% 6) first. If jsonencode does not exist or failed, % this function falls back to the jsonlab savejson % -% opt can be replaced by a list of ('param',value) pairs. The param +% opt can be replaced by a list of ('param',value) pairs. The param % string is equivallent to a field in opt and is case sensitive. % output: % json: a string in the JSON format (see http://json.org) % % examples: -% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... +% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],... % 'MeshElem',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],... % 'MeshSurf',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;... % 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],... @@ -128,687 +128,689 @@ % -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab) % -if(nargin==1) - varname=inputname(1); - obj=rootname; - rootname=varname; +if (nargin == 1) + varname = inputname(1); + obj = rootname; + rootname = varname; else - varname=inputname(2); + varname = inputname(2); end -if(length(varargin)==1 && (ischar(varargin{1}) || isa(varargin{1}, 'string'))) - opt=struct('filename',varargin{1}); +if (length(varargin) == 1 && (ischar(varargin{1}) || isa(varargin{1}, 'string'))) + opt = struct('filename', varargin{1}); else - opt=varargin2struct(varargin{:}); -end - -opt.isoctave=isoctavemesh; - -opt.compression=jsonopt('Compression','',opt); -opt.nestarray=jsonopt('NestArray',0,opt); -opt.compact=jsonopt('Compact',0,opt); -opt.singletcell=jsonopt('SingletCell',1,opt); -opt.singletarray=jsonopt('SingletArray',0,opt); -opt.formatversion=jsonopt('FormatVersion',3,opt); -opt.compressarraysize=jsonopt('CompressArraySize',100,opt); -opt.compressstringsize=jsonopt('CompressStringSize',opt.compressarraysize*4,opt); -opt.intformat=jsonopt('IntFormat','%.0f',opt); -opt.floatformat=jsonopt('FloatFormat','%.16g',opt); -opt.unpackhex=jsonopt('UnpackHex',1,opt); -opt.arraytostruct=jsonopt('ArrayToStruct',0,opt); -opt.parselogical=jsonopt('ParseLogical',0,opt); -opt.arrayindent=jsonopt('ArrayIndent',1,opt); -opt.inf=jsonopt('Inf','"$1_Inf_"',opt); -opt.nan=jsonopt('NaN','"_NaN_"',opt); -opt.num2cell_=0; -opt.nosubstruct_=0; - -if(jsonopt('BuiltinJSON',0,opt) && exist('jsonencode','builtin')) + opt = varargin2struct(varargin{:}); +end + +opt.isoctave = isoctavemesh; + +opt.compression = jsonopt('Compression', '', opt); +opt.nestarray = jsonopt('NestArray', 0, opt); +opt.compact = jsonopt('Compact', 0, opt); +opt.singletcell = jsonopt('SingletCell', 1, opt); +opt.singletarray = jsonopt('SingletArray', 0, opt); +opt.formatversion = jsonopt('FormatVersion', 3, opt); +opt.compressarraysize = jsonopt('CompressArraySize', 100, opt); +opt.compressstringsize = jsonopt('CompressStringSize', opt.compressarraysize * 4, opt); +opt.intformat = jsonopt('IntFormat', '%.0f', opt); +opt.floatformat = jsonopt('FloatFormat', '%.16g', opt); +opt.unpackhex = jsonopt('UnpackHex', 1, opt); +opt.arraytostruct = jsonopt('ArrayToStruct', 0, opt); +opt.parselogical = jsonopt('ParseLogical', 0, opt); +opt.arrayindent = jsonopt('ArrayIndent', 1, opt); +opt.inf = jsonopt('Inf', '"$1_Inf_"', opt); +opt.nan = jsonopt('NaN', '"_NaN_"', opt); +opt.num2cell_ = 0; +opt.nosubstruct_ = 0; + +if (jsonopt('BuiltinJSON', 0, opt) && exist('jsonencode', 'builtin')) try - obj=jdataencode(obj,'Base64',1,'AnnotateArray',1,'UseArrayZipSize',1,opt); - if(isempty(rootname)) - json=jsonencode(obj); + obj = jdataencode(obj, 'Base64', 1, 'AnnotateArray', 1, 'UseArrayZipSize', 1, opt); + if (isempty(rootname)) + json = jsonencode(obj); else - json=jsonencode(struct(rootname,obj)); + json = jsonencode(struct(rootname, obj)); end - if(isempty(regexp(json,'^[{\[]', 'once'))) - json=['[',json,']']; + if (isempty(regexp(json, '^[{\[]', 'once'))) + json = ['[', json, ']']; end - return; + return catch warning('built-in jsonencode function failed to encode the data, fallback to savejson'); end end -if(jsonopt('PreEncode',1,opt)) - obj=jdataencode(obj,'Base64',1,'UseArrayZipSize',0,opt); +if (jsonopt('PreEncode', 1, opt)) + obj = jdataencode(obj, 'Base64', 1, 'UseArrayZipSize', 0, opt); end -dozip=opt.compression; -if(~isempty(dozip)) - if(~ismember(dozip,{'zlib','gzip','lzma','lzip','lz4','lz4hc'})) - error('compression method "%s" is not supported',dozip); +dozip = opt.compression; +if (~isempty(dozip)) + if (~ismember(dozip, {'zlib', 'gzip', 'lzma', 'lzip', 'lz4', 'lz4hc'}) && isempty(regexp(dozip,'^blosc2', 'once'))) + error('compression method "%s" is not supported', dozip); end - if(exist('zmat','file')~=2 && exist('zmat','file')~=3) + if (exist('zmat', 'file') ~= 2 && exist('zmat', 'file') ~= 3) try error(javachk('jvm')); try - base64decode('test'); + base64decode('test'); catch - matlab.net.base64decode('test'); + matlab.net.base64decode('test'); end catch error('java-based compression is not supported'); end - end - opt.Compression=dozip; + end + opt.Compression = dozip; end -rootisarray=0; -rootlevel=1; -forceroot=jsonopt('ForceRootName',0,opt); -if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || ... - iscell(obj) || isobject(obj) ) && isempty(rootname) && forceroot==0) - rootisarray=1; - rootlevel=0; +rootisarray = 0; +rootlevel = 1; +forceroot = jsonopt('ForceRootName', 0, opt); +if ((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || ... + iscell(obj) || isobject(obj)) && isempty(rootname) && forceroot == 0) + rootisarray = 1; + rootlevel = 0; else - if(isempty(rootname)) - rootname=varname; + if (isempty(rootname)) + rootname = varname; end end -if(isa(obj,'containers.Map') && ~strcmp(obj.KeyType,'char')) - rootisarray=0; +if (isa(obj, 'containers.Map') && ~strcmp(obj.KeyType, 'char')) + rootisarray = 0; end -if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) - rootname='root'; +if ((isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot) + rootname = 'root'; end -whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); -if(opt.compact==1) - whitespaces=struct('tab','','newline','','sep',','); +whitespaces = struct('tab', sprintf('\t'), 'newline', sprintf('\n'), 'sep', sprintf(',\n')); +if (opt.compact == 1) + whitespaces = struct('tab', '', 'newline', '', 'sep', ','); end -if(~isfield(opt,'whitespaces_')) - opt.whitespaces_=whitespaces; +if (~isfield(opt, 'whitespaces_')) + opt.whitespaces_ = whitespaces; end -nl=whitespaces.newline; +nl = whitespaces.newline; -json=obj2json(rootname,obj,rootlevel,opt); +json = obj2json(rootname, obj, rootlevel, opt); -if(rootisarray) - json=sprintf('%s%s',json,nl); +if (rootisarray) + json = sprintf('%s%s', json, nl); else - json=sprintf('{%s%s%s}\n',nl,json,nl); + json = sprintf('{%s%s%s}\n', nl, json, nl); end -jsonp=jsonopt('JSONP','',opt); -if(~isempty(jsonp)) - json=sprintf('%s(%s);%s',jsonp,json,nl); +jsonp = jsonopt('JSONP', '', opt); +if (~isempty(jsonp)) + json = sprintf('%s(%s);%s', jsonp, json, nl); end % save to a file if FileName is set, suggested by Patrick Rapin -filename=jsonopt('FileName','',opt); -if(~isempty(filename)) - encoding = jsonopt('Encoding','',opt); - endian = jsonopt('Endian','n',opt); +filename = jsonopt('FileName', '', opt); +if (~isempty(filename)) + encoding = jsonopt('Encoding', '', opt); + endian = jsonopt('Endian', 'n', opt); mode = 'w'; - if(jsonopt('Append',0,opt)) - mode='a'; + if (jsonopt('Append', 0, opt)) + mode = 'a'; end - if(jsonopt('SaveBinary',1,opt)==1) - if(isempty(encoding)) - fid = fopen(filename, [mode 'b'],endian); + if (jsonopt('SaveBinary', 1, opt) == 1) + if (isempty(encoding)) + fid = fopen(filename, [mode 'b'], endian); else - fid = fopen(filename, [mode 'b'],endian,encoding); + fid = fopen(filename, [mode 'b'], endian, encoding); end - fwrite(fid,json); + fwrite(fid, json); else - if(isempty(encoding)) - fid = fopen(filename,[mode 't'],endian); + if (isempty(encoding)) + fid = fopen(filename, [mode 't'], endian); else - fid = fopen(filename,[mode 't'],endian,encoding); + fid = fopen(filename, [mode 't'], endian, encoding); end - fwrite(fid,json,'char'); + fwrite(fid, json, 'char'); end fclose(fid); end -if(nargout>0 || isempty(filename)) - output=json; +if (nargout > 0 || isempty(filename)) + output = json; end -%%------------------------------------------------------------------------- -function txt=obj2json(name,item,level,varargin) +%% ------------------------------------------------------------------------- +function txt = obj2json(name, item, level, varargin) -if(iscell(item) || isa(item,'string')) - txt=cell2json(name,item,level,varargin{:}); -elseif(isstruct(item)) - txt=struct2json(name,item,level,varargin{:}); -elseif(isnumeric(item) || islogical(item)) - txt=mat2json(name,item,level,varargin{:}); -elseif(ischar(item)) - if(~isempty(varargin{1}.compression) && numel(item)>=varargin{1}.compressstringsize) - txt=mat2json(name,item,level,varargin{:}); +if (iscell(item) || isa(item, 'string')) + txt = cell2json(name, item, level, varargin{:}); +elseif (isstruct(item)) + txt = struct2json(name, item, level, varargin{:}); +elseif (isnumeric(item) || islogical(item)) + txt = mat2json(name, item, level, varargin{:}); +elseif (ischar(item)) + if (~isempty(varargin{1}.compression) && numel(item) >= varargin{1}.compressstringsize) + txt = mat2json(name, item, level, varargin{:}); else - txt=str2json(name,item,level,varargin{:}); - end -elseif(isa(item,'function_handle')) - txt=struct2json(name,functions(item),level,varargin{:}); -elseif(isa(item,'containers.Map')) - txt=map2json(name,item,level,varargin{:}); -elseif(isa(item,'categorical')) - txt=cell2json(name,cellstr(item),level,varargin{:}); -elseif(isa(item,'table')) - txt=matlabtable2json(name,item,level,varargin{:}); -elseif(isa(item,'graph') || isa(item,'digraph')) - txt=struct2json(name,jdataencode(item),level,varargin{:}); -elseif(isobject(item)) - txt=matlabobject2json(name,item,level,varargin{:}); + txt = str2json(name, item, level, varargin{:}); + end +elseif (isa(item, 'function_handle')) + txt = struct2json(name, functions(item), level, varargin{:}); +elseif (isa(item, 'containers.Map')) + txt = map2json(name, item, level, varargin{:}); +elseif (isa(item, 'categorical')) + txt = cell2json(name, cellstr(item), level, varargin{:}); +elseif (isa(item, 'table')) + txt = matlabtable2json(name, item, level, varargin{:}); +elseif (isa(item, 'graph') || isa(item, 'digraph')) + txt = struct2json(name, jdataencode(item), level, varargin{:}); +elseif (isobject(item)) + txt = matlabobject2json(name, item, level, varargin{:}); else - txt=any2json(name,item,level,varargin{:}); + txt = any2json(name, item, level, varargin{:}); end -%%------------------------------------------------------------------------- -function txt=cell2json(name,item,level,varargin) -txt={}; -if(~iscell(item) && ~isa(item,'string')) - error('input is not a cell or string array'); +%% ------------------------------------------------------------------------- +function txt = cell2json(name, item, level, varargin) +txt = {}; +if (~iscell(item) && ~isa(item, 'string')) + error('input is not a cell or string array'); end -if(isa(item,'string')) - level=level-1; +if (isa(item, 'string')) + level = level - 1; end -isnum2cell=varargin{1}.num2cell_; -if(isnum2cell) - item=squeeze(item); - if(~isvector(item)) - item=permute(item,ndims(item):-1:1); +isnum2cell = varargin{1}.num2cell_; +if (isnum2cell) + item = squeeze(item); + if (~isvector(item)) + item = permute(item, ndims(item):-1:1); end end -dim=size(item); +dim = size(item); % if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now % item=reshape(item,dim(1),numel(item)/dim(1)); % dim=size(item); % end -len=numel(item); -ws=varargin{1}.whitespaces_; -padding0=repmat(ws.tab,1,level); -nl=ws.newline; -bracketlevel=~varargin{1}.singletcell; -if(len>bracketlevel) - if(~isempty(name)) - txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'":[', nl}; name=''; +len = numel(item); +ws = varargin{1}.whitespaces_; +padding0 = repmat(ws.tab, 1, level); +nl = ws.newline; +bracketlevel = ~varargin{1}.singletcell; +if (len > bracketlevel) + if (~isempty(name)) + txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl}; + name = ''; else - txt={padding0, '[', nl}; + txt = {padding0, '[', nl}; end -elseif(len==0) - if(~isempty(name)) - txt={padding0, '"' decodevarname(name,varargin{1}.unpackhex) '":[]'}; name=''; +elseif (len == 0) + if (~isempty(name)) + txt = {padding0, '"' decodevarname(name, varargin{1}.unpackhex) '":[]'}; + name = ''; else - txt={padding0, '[]'}; + txt = {padding0, '[]'}; end - txt = sprintf('%s',txt{:}); - return; + txt = sprintf('%s', txt{:}); + return end -if(size(item,1)>1) - item=num2cell(item,2:ndims(item))'; +if (size(item, 1) > 1) + item = num2cell(item, 2:ndims(item))'; end -idx=num2cell(1:length(item)); -sep={[',' nl],''}; -txt=[txt{:},cellfun(@(x,id) [obj2json(name,x,level+(dim(1)>1)+(len>bracketlevel),varargin{:}), sep{(id==length(item))+1}], item, idx, 'UniformOutput',false)]; +idx = num2cell(1:length(item)); +sep = {[',' nl], ''}; +txt = [txt{:}, cellfun(@(x, id) [obj2json(name, x, level + (dim(1) > 1) + (len > bracketlevel), varargin{:}), sep{(id == length(item)) + 1}], item, idx, 'UniformOutput', false)]; -if(len>bracketlevel) - txt(end+1:end+3)={nl,padding0,']'}; +if (len > bracketlevel) + txt(end + 1:end + 3) = {nl, padding0, ']'}; end -txt = sprintf('%s',txt{:}); +txt = sprintf('%s', txt{:}); -%%------------------------------------------------------------------------- -function txt=struct2json(name,item,level,varargin) -txt={}; -if(~isstruct(item)) - error('input is not a struct'); +%% ------------------------------------------------------------------------- +function txt = struct2json(name, item, level, varargin) +txt = {}; +if (~isstruct(item)) + error('input is not a struct'); end -dim=size(item); -if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now - item=reshape(item,dim(1),numel(item)/dim(1)); - dim=size(item); +dim = size(item); +if (ndims(squeeze(item)) > 2) % for 3D or higher dimensions, flatten to 2D for now + item = reshape(item, dim(1), numel(item) / dim(1)); + dim = size(item); end -len=numel(item); -forcearray= (len>1 || (varargin{1}.singletarray==1 && level>0)); -ws=varargin{1}.whitespaces_; -padding0=repmat(ws.tab,1,level); -padding2=repmat(ws.tab,1,level+1); -padding1=repmat(ws.tab,1,level+(dim(1)>1)+forcearray); -nl=ws.newline; -if(isfield(item,encodevarname('_ArrayType_',varargin{1}.unpackhex))) - varargin{1}.nosubstruct_=1; +len = numel(item); +forcearray = (len > 1 || (varargin{1}.singletarray == 1 && level > 0)); +ws = varargin{1}.whitespaces_; +padding0 = repmat(ws.tab, 1, level); +padding2 = repmat(ws.tab, 1, level + 1); +padding1 = repmat(ws.tab, 1, level + (dim(1) > 1) + forcearray); +nl = ws.newline; +if (isfield(item, encodevarname('_ArrayType_', varargin{1}.unpackhex))) + varargin{1}.nosubstruct_ = 1; end -if(isempty(item)) - if(~isempty(name)) - txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'":[]'}; +if (isempty(item)) + if (~isempty(name)) + txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[]'}; else - txt={padding0, '[]'}; + txt = {padding0, '[]'}; end - txt = sprintf('%s',txt{:}); - return; + txt = sprintf('%s', txt{:}); + return end -if(~isempty(name)) - if(forcearray) - txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'":[', nl}; +if (~isempty(name)) + if (forcearray) + txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl}; end else - if(forcearray) - txt={padding0, '[', nl}; - end -end -for j=1:dim(2) - if(dim(1)>1) - txt(end+1:end+3)={padding2,'[',nl}; - end - for i=1:dim(1) - names = fieldnames(item(i,j)); - if(~isempty(name) && len==1 && ~forcearray) - txt(end+1:end+5)={padding1, '"', decodevarname(name,varargin{1}.unpackhex),'":{', nl}; - else - txt(end+1:end+3)={padding1, '{', nl}; - end - if(~isempty(names)) - for e=1:length(names) - if(varargin{1}.nosubstruct_ && ischar(item(i,j).(names{e})) || ... - strcmp(names{e},encodevarname('_ByteStream_'))) - txt{end+1}=str2json(names{e},item(i,j).(names{e}),... - level+(dim(1)>1)+1+forcearray,varargin{:}); + if (forcearray) + txt = {padding0, '[', nl}; + end +end +for j = 1:dim(2) + if (dim(1) > 1) + txt(end + 1:end + 3) = {padding2, '[', nl}; + end + for i = 1:dim(1) + names = fieldnames(item(i, j)); + if (~isempty(name) && len == 1 && ~forcearray) + txt(end + 1:end + 5) = {padding1, '"', decodevarname(name, varargin{1}.unpackhex), '":{', nl}; else - txt{end+1}=obj2json(names{e},item(i,j).(names{e}),... - level+(dim(1)>1)+1+forcearray,varargin{:}); + txt(end + 1:end + 3) = {padding1, '{', nl}; end - if(e 1) + 1 + forcearray, varargin{:}); + else + txt{end + 1} = obj2json(names{e}, item(i, j).(names{e}), ... + level + (dim(1) > 1) + 1 + forcearray, varargin{:}); + end + if (e < length(names)) + txt{end + 1} = ','; + end + txt{end + 1} = nl; + end + end + txt(end + 1:end + 2) = {padding1, '}'}; + if (i < dim(1)) + txt(end + 1:end + 2) = {',' nl}; end - txt{end+1}=nl; - end end - txt(end+1:end+2)={padding1,'}'}; - if(i 1) + txt(end + 1:end + 3) = {nl, padding2, ']'}; + end + if (j < dim(2)) + txt(end + 1:end + 2) = {',' nl}; end - end - if(dim(1)>1) - txt(end+1:end+3)={nl,padding2,']'}; - end - if(j1),varargin{:}); +for i = 1:dim(1) + if (isempty(names{i})) + txt{end + 1} = obj2json('x0x0_', val{i}, level + (dim(1) > 1), varargin{:}); else - txt{end+1}=obj2json(names{i},val{i},level+(dim(1)>1),varargin{:}); + txt{end + 1} = obj2json(names{i}, val{i}, level + (dim(1) > 1), varargin{:}); end - if(i1) - txt={padding1, '"', decodevarname(name,varargin{1}.unpackhex),'":[', nl}; +if (~isempty(name)) + if (len > 1) + txt = {padding1, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl}; end else - if(len>1) - txt={padding1, '[', nl}; + if (len > 1) + txt = {padding1, '[', nl}; end end -for e=1:len - if(strcmp('_ArrayZipData_',decodevarname(name,varargin{1}.unpackhex))==0) - val=escapejsonstring(item(e,:),varargin{:}); +for e = 1:len + if (strcmp('_ArrayZipData_', decodevarname(name, varargin{1}.unpackhex)) == 0) + val = escapejsonstring(item(e, :), varargin{:}); else - val=item(e,:); + val = item(e, :); end - if(len==1) - obj=['"' decodevarname(name,varargin{1}.unpackhex) '":' '"',val,'"']; - if(isempty(name)) - obj=['"',val,'"']; + if (len == 1) + obj = ['"' decodevarname(name, varargin{1}.unpackhex) '":' '"', val, '"']; + if (isempty(name)) + obj = ['"', val, '"']; end - txt(end+1:end+2)={padding1, obj}; + txt(end + 1:end + 2) = {padding1, obj}; else - txt(end+1:end+4)={padding0,'"',val,'"'}; + txt(end + 1:end + 4) = {padding0, '"', val, '"'}; end - if(e==len) - sep=''; + if (e == len) + sep = ''; end - txt{end+1}=sep; + txt{end + 1} = sep; end -if(len>1) - txt(end+1:end+3)={nl,padding1,']'}; +if (len > 1) + txt(end + 1:end + 3) = {nl, padding1, ']'}; end -txt = sprintf('%s',txt{:}); +txt = sprintf('%s', txt{:}); -%%------------------------------------------------------------------------- -function txt=mat2json(name,item,level,varargin) -if(~isnumeric(item) && ~islogical(item) && ~ischar(item)) - error('input is not an array'); +%% ------------------------------------------------------------------------- +function txt = mat2json(name, item, level, varargin) +if (~isnumeric(item) && ~islogical(item) && ~ischar(item)) + error('input is not an array'); end -ws=varargin{1}.whitespaces_; -padding1=repmat(ws.tab,1,level); -padding0=repmat(ws.tab,1,level+1); -nl=ws.newline; -sep=ws.sep; +ws = varargin{1}.whitespaces_; +padding1 = repmat(ws.tab, 1, level); +padding0 = repmat(ws.tab, 1, level + 1); +nl = ws.newline; +sep = ws.sep; -dozip=varargin{1}.compression; -zipsize=varargin{1}.compressarraysize; -format=varargin{1}.formatversion; -isnest=varargin{1}.nestarray; +dozip = varargin{1}.compression; +zipsize = varargin{1}.compressarraysize; +format = varargin{1}.formatversion; +isnest = varargin{1}.nestarray; -if(~varargin{1}.nosubstruct_ && ( ((isnest==0) && length(size(item))>2) || issparse(item) || ~isreal(item) || ... - (isempty(item) && any(size(item))) || varargin{1}.arraytostruct || (~isempty(dozip) && numel(item)>zipsize))) - if(isempty(name)) - txt=sprintf('%s{%s%s"_ArrayType_":"%s",%s%s"_ArraySize_":%s,%s',... - padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); +if (~varargin{1}.nosubstruct_ && (((isnest == 0) && length(size(item)) > 2) || issparse(item) || ~isreal(item) || ... + (isempty(item) && any(size(item))) || varargin{1}.arraytostruct || (~isempty(dozip) && numel(item) > zipsize))) + if (isempty(name)) + txt = sprintf('%s{%s%s"_ArrayType_":"%s",%s%s"_ArraySize_":%s,%s', ... + padding1, nl, padding0, class(item), nl, padding0, regexprep(mat2str(size(item)), '\s+', ','), nl); else - txt=sprintf('%s"%s":{%s%s"_ArrayType_":"%s",%s%s"_ArraySize_":%s,%s',... - padding1,decodevarname(name,varargin{1}.unpackhex),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); + txt = sprintf('%s"%s":{%s%s"_ArrayType_":"%s",%s%s"_ArraySize_":%s,%s', ... + padding1, decodevarname(name, varargin{1}.unpackhex), nl, padding0, class(item), nl, padding0, regexprep(mat2str(size(item)), '\s+', ','), nl); end else - numtxt=matdata2json(item,level+1,varargin{:}); - if(isempty(name)) - txt=sprintf('%s%s',padding1,numtxt); + numtxt = matdata2json(item, level + 1, varargin{:}); + if (isempty(name)) + txt = sprintf('%s%s', padding1, numtxt); else - if(numel(item)==1 && varargin{1}.singletarray==0) - txt=sprintf('%s"%s":%s',padding1,decodevarname(name,varargin{1}.unpackhex),numtxt); + if (numel(item) == 1 && varargin{1}.singletarray == 0) + txt = sprintf('%s"%s":%s', padding1, decodevarname(name, varargin{1}.unpackhex), numtxt); else - txt=sprintf('%s"%s":%s',padding1,decodevarname(name,varargin{1}.unpackhex),numtxt); + txt = sprintf('%s"%s":%s', padding1, decodevarname(name, varargin{1}.unpackhex), numtxt); end end - return; + return end -dataformat='%s%s%s%s%s'; +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(:))]; - if(size(item,1)==1) - % Kludge to have data's 'transposedness' match item's. - % (Necessary for complex row vector handling below.) - data=data'; - end - txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_":','true', sep); +if (issparse(item)) + [ix, iy] = find(item); + data = full(item(find(item))); + if (~isreal(item)) + data = [real(data(:)), imag(data(:))]; + if (size(item, 1) == 1) + % Kludge to have data's 'transposedness' match item's. + % (Necessary for complex row vector handling below.) + data = data'; + end + txt = sprintf(dataformat, txt, padding0, '"_ArrayIsComplex_":', 'true', sep); end - txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_":','true', sep); - if(~isempty(dozip) && numel(data*2)>zipsize) - if(size(item,1)==1) + txt = sprintf(dataformat, txt, padding0, '"_ArrayIsSparse_":', 'true', sep); + if (~isempty(dozip) && numel(data * 2) > zipsize) + if (size(item, 1) == 1) % Row vector, store only column indices. - fulldata=[iy(:),data']; - elseif(size(item,2)==1) + fulldata = [iy(:), data']; + elseif (size(item, 2) == 1) % Column vector, store only row indices. - fulldata=[ix,data]; + fulldata = [ix, data]; else % General case, store row and column indices. - fulldata=[ix,iy,data]; + fulldata = [ix, iy, data]; end - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipSize_":',regexprep(mat2str(size(fulldata)),'\s+',','), sep); - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipType_":"',dozip, ['"' sep]); - compfun=str2func([dozip 'encode']); - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipData_":"',base64encode(compfun(typecast(fulldata(:),'uint8'))),['"' nl]); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipSize_":', regexprep(mat2str(size(fulldata)), '\s+', ','), sep); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, ['"' sep]); + compfun = str2func([dozip 'encode']); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', base64encode(compfun(typecast(fulldata(:), 'uint8'))), ['"' nl]); else - if(size(item,1)==1) + if (size(item, 1) == 1) % Row vector, store only column indices. - fulldata=[iy(:),data']; - elseif(size(item,2)==1) + fulldata = [iy(:), data']; + elseif (size(item, 2) == 1) % Column vector, store only row indices. - fulldata=[ix,data]; + fulldata = [ix, data]; else % General case, store row and column indices. - fulldata=[ix,iy,data]; + fulldata = [ix, iy, data]; end - txt=sprintf(dataformat,txt,padding0,'"_ArrayData_":',... - matdata2json(fulldata',level+2,varargin{:}), nl); + txt = sprintf(dataformat, txt, padding0, '"_ArrayData_":', ... + matdata2json(fulldata', level + 2, varargin{:}), nl); end else - if(format>1.9) - item=permute(item,ndims(item):-1:1); - end - if(~isempty(dozip) && numel(item)>zipsize) - if(isreal(item)) - fulldata=item(:)'; - if(islogical(fulldata) || ischar(fulldata)) - fulldata=uint8(fulldata); + if (format > 1.9) + item = permute(item, ndims(item):-1:1); + end + if (~isempty(dozip) && numel(item) > zipsize) + if (isreal(item)) + fulldata = item(:)'; + if (islogical(fulldata) || ischar(fulldata)) + fulldata = uint8(fulldata); end else - txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_":','true', sep); - fulldata=[real(item(:)) imag(item(:))]'; + txt = sprintf(dataformat, txt, padding0, '"_ArrayIsComplex_":', 'true', sep); + fulldata = [real(item(:)) imag(item(:))]'; end - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipSize_":',regexprep(mat2str(size(fulldata)),'\s+',','), sep); - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipType_":"',dozip, ['"' sep]); - compfun=str2func([dozip 'encode']); - txt=sprintf(dataformat,txt,padding0,'"_ArrayZipData_":"',char(base64encode(compfun(typecast(fulldata(:),'uint8')))),['"' nl]); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipSize_":', regexprep(mat2str(size(fulldata)), '\s+', ','), sep); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, ['"' sep]); + compfun = str2func([dozip 'encode']); + txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', char(base64encode(compfun(typecast(fulldata(:), 'uint8')))), ['"' nl]); else - if(isreal(item)) - txt=sprintf(dataformat,txt,padding0,'"_ArrayData_":',... - matdata2json(item(:)',level+2,varargin{:}), nl); + if (isreal(item)) + txt = sprintf(dataformat, txt, padding0, '"_ArrayData_":', ... + matdata2json(item(:)', level + 2, varargin{:}), nl); else - txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_":','true', sep); - txt=sprintf(dataformat,txt,padding0,'"_ArrayData_":',... - matdata2json([real(item(:)) imag(item(:))]',level+2,varargin{:}), nl); + txt = sprintf(dataformat, txt, padding0, '"_ArrayIsComplex_":', 'true', sep); + txt = sprintf(dataformat, txt, padding0, '"_ArrayData_":', ... + matdata2json([real(item(:)) imag(item(:))]', level + 2, varargin{:}), nl); end end end -txt=sprintf('%s%s%s',txt,padding1,'}'); +txt = sprintf('%s%s%s', txt, padding1, '}'); -%%------------------------------------------------------------------------- -function txt=matlabobject2json(name,item,level,varargin) +%% ------------------------------------------------------------------------- +function txt = matlabobject2json(name, item, level, varargin) try - if numel(item) == 0 %empty object + if numel(item) == 0 % empty object st = struct(); elseif numel(item) == 1 % txt = str2json(name, char(item), level, varargin{:}); return else - propertynames = properties(item); - for p = 1:numel(propertynames) - for o = numel(item):-1:1 % array of objects - st(o).(propertynames{p}) = item(o).(propertynames{p}); - end + propertynames = properties(item); + for p = 1:numel(propertynames) + for o = numel(item):-1:1 % array of objects + st(o).(propertynames{p}) = item(o).(propertynames{p}); end + end end - txt=struct2json(name,st,level,varargin{:}); + txt = struct2json(name, st, level, varargin{:}); catch - txt = any2json(name,item, level, varargin{:}); + txt = any2json(name, item, level, varargin{:}); end -%%------------------------------------------------------------------------- -function txt=matlabtable2json(name,item,level,varargin) -st=containers.Map(); -st('_TableRecords_')=table2cell(item); -st('_TableRows_')=item.Properties.RowNames'; -st('_TableCols_')=item.Properties.VariableNames; -if(isempty(name)) - txt=map2json(name,st,level,varargin{:}); +%% ------------------------------------------------------------------------- +function txt = matlabtable2json(name, item, level, varargin) +st = containers.Map(); +st('_TableRecords_') = table2cell(item); +st('_TableRows_') = item.Properties.RowNames'; +st('_TableCols_') = item.Properties.VariableNames; +if (isempty(name)) + txt = map2json(name, st, level, varargin{:}); else - temp=struct(name,struct()); - temp.(name)=st; - txt=map2json(name,temp.(name),level,varargin{:}); -end - -%%------------------------------------------------------------------------- -function txt=matdata2json(mat,level,varargin) - -ws=varargin{1}.whitespaces_; -tab=ws.tab; -nl=ws.newline; -isnest=varargin{1}.nestarray; -format=varargin{1}.formatversion; -isnum2cell=varargin{1}.num2cell_; - -if(~isvector(mat) && isnest==1) - if(format>1.9 && isnum2cell==0) - mat=permute(mat,ndims(mat):-1:1); - end - varargin{1}.num2cell_=1; - varargin{1}.singletcell=0; - txt=cell2json('',num2cell(mat,1),level-1,varargin{:}); - return; -elseif(isvector(mat) && isnum2cell==1) - mat=mat(:).'; -end - -if(size(mat,1)==1) - pre=''; - post=''; - level=level-1; + temp = struct(name, struct()); + temp.(name) = st; + txt = map2json(name, temp.(name), level, varargin{:}); +end + +%% ------------------------------------------------------------------------- +function txt = matdata2json(mat, level, varargin) + +ws = varargin{1}.whitespaces_; +tab = ws.tab; +nl = ws.newline; +isnest = varargin{1}.nestarray; +format = varargin{1}.formatversion; +isnum2cell = varargin{1}.num2cell_; + +if (~isvector(mat) && isnest == 1) + if (format > 1.9 && isnum2cell == 0) + mat = permute(mat, ndims(mat):-1:1); + end + varargin{1}.num2cell_ = 1; + varargin{1}.singletcell = 0; + txt = cell2json('', num2cell(mat, 1), level - 1, varargin{:}); + return +elseif (isvector(mat) && isnum2cell == 1) + mat = mat(:).'; +end + +if (size(mat, 1) == 1) + pre = ''; + post = ''; + level = level - 1; else - pre=sprintf('[%s',nl); - post=sprintf('%s%s]',nl,repmat(tab,1,level-1)); + pre = sprintf('[%s', nl); + post = sprintf('%s%s]', nl, repmat(tab, 1, level - 1)); end -if(isempty(mat)) - txt='[]'; - return; +if (isempty(mat)) + txt = '[]'; + return end -if(isinteger(mat)) - floatformat=varargin{1}.intformat; +if (isinteger(mat)) + floatformat = varargin{1}.intformat; else - floatformat=varargin{1}.floatformat; + floatformat = varargin{1}.floatformat; end -if(numel(mat)==1 && varargin{1}.singletarray==0 && level>0) - formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',%s',nl)]]; +if (numel(mat) == 1 && varargin{1}.singletarray == 0 && level > 0) + formatstr = [repmat([floatformat ','], 1, size(mat, 2) - 1) [floatformat sprintf(',%s', nl)]]; else - formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; + formatstr = ['[' repmat([floatformat ','], 1, size(mat, 2) - 1) [floatformat sprintf('],%s', nl)]]; end -if(nargin>=2 && size(mat,1)>1 && varargin{1}.arrayindent==1) - formatstr=[repmat(tab,1,level) formatstr]; +if (nargin >= 2 && size(mat, 1) > 1 && varargin{1}.arrayindent == 1) + formatstr = [repmat(tab, 1, level) formatstr]; end -txt=sprintf(formatstr,permute(mat,ndims(mat):-1:1)); -txt(end-length(nl):end)=[]; -if(islogical(mat) && (numel(mat)==1 || varargin{1}.parselogical==1)) - txt=regexprep(txt,'1','true'); - txt=regexprep(txt,'0','false'); +txt = sprintf(formatstr, permute(mat, ndims(mat):-1:1)); +txt(end - length(nl):end) = []; +if (islogical(mat) && (numel(mat) == 1 || varargin{1}.parselogical == 1)) + txt = regexprep(txt, '1', 'true'); + txt = regexprep(txt, '0', 'false'); end -txt=[pre txt post]; -if(any(isinf(mat(:)))) - txt=regexprep(txt,'([-+]*)Inf',varargin{1}.inf); +txt = [pre txt post]; +if (any(isinf(mat(:)))) + txt = regexprep(txt, '([-+]*)Inf', varargin{1}.inf); end -if(any(isnan(mat(:)))) - txt=regexprep(txt,'NaN',varargin{1}.nan); +if (any(isnan(mat(:)))) + txt = regexprep(txt, 'NaN', varargin{1}.nan); end -%%------------------------------------------------------------------------- -function txt=any2json(name,item,level,varargin) -st=containers.Map(); -st('_DataInfo_')=struct('MATLABObjectName',name, 'MATLABObjectClass',class(item),'MATLABObjectSize',size(item)); -st('_ByteStream_')=char(base64encode(getByteStreamFromArray(item))); +%% ------------------------------------------------------------------------- +function txt = any2json(name, item, level, varargin) +st = containers.Map(); +st('_DataInfo_') = struct('MATLABObjectName', name, 'MATLABObjectClass', class(item), 'MATLABObjectSize', size(item)); +st('_ByteStream_') = char(base64encode(getByteStreamFromArray(item))); -if(isempty(name)) - txt=map2json(name,st,level,varargin{:}); +if (isempty(name)) + txt = map2json(name, st, level, varargin{:}); else - temp=struct(name,struct()); - temp.(name)=st; - txt=map2json(name,temp.(name),level,varargin{:}); -end - -%%------------------------------------------------------------------------- -function newstr=escapejsonstring(str,varargin) -newstr=str; -if(isempty(str) || isempty(regexp(str,'\W', 'once'))) - return; -end -isoct=varargin{1}.isoctave; -if(isoct) - vv=sscanf(OCTAVE_VERSION,'%f'); - if(vv(1)>=3.8) - isoct=0; - end -end -if(isoct) - escapechars={'\\','\"','\a','\f','\n','\r','\t','\v'}; - for i=1:length(escapechars) - newstr=regexprep(newstr,escapechars{i},escapechars{i}); - end - newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\$1'); + temp = struct(name, struct()); + temp.(name) = st; + txt = map2json(name, temp.(name), level, varargin{:}); +end + +%% ------------------------------------------------------------------------- +function newstr = escapejsonstring(str, varargin) +newstr = str; +if (isempty(str) || isempty(regexp(str, '\W', 'once'))) + return +end +isoct = varargin{1}.isoctave; +if (isoct) + vv = sscanf(OCTAVE_VERSION, '%f'); + if (vv(1) >= 3.8) + isoct = 0; + end +end +if (isoct) + escapechars = {'\\', '\"', '\a', '\f', '\n', '\r', '\t', '\v'}; + for i = 1:length(escapechars) + newstr = regexprep(newstr, escapechars{i}, escapechars{i}); + end + newstr = regexprep(newstr, '\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)', '\$1'); else - escapechars={'\\','\"','\a','\b','\f','\n','\r','\t','\v'}; - esc={'\\\\','\\"','\\a','\\b','\\f','\\n','\\r','\\t','\\v'}; - for i=1:length(escapechars) - newstr=regexprep(newstr,escapechars{i},esc{i}); - end - newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\\$1'); + escapechars = {'\\', '\"', '\a', '\b', '\f', '\n', '\r', '\t', '\v'}; + esc = {'\\\\', '\\"', '\\a', '\\b', '\\f', '\\n', '\\r', '\\t', '\\v'}; + for i = 1:length(escapechars) + newstr = regexprep(newstr, escapechars{i}, esc{i}); + end + newstr = regexprep(newstr, '\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)', '\\$1'); end diff --git a/varargin2struct.m b/varargin2struct.m index 07952c2..52340ba 100644 --- a/varargin2struct.m +++ b/varargin2struct.m @@ -1,4 +1,4 @@ -function opt=varargin2struct(varargin) +function opt = varargin2struct(varargin) % % opt=varargin2struct('param1',value1,'param2',value2,...) % or @@ -17,24 +17,25 @@ % opt: a struct where opt.param1=value1, opt.param2=value2 ... % % license: -% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details +% 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) % -len=length(varargin); -opt=struct; -if(len==0) return; end -i=1; -while(i<=len) - if(isstruct(varargin{i})) - opt=mergestruct(opt,varargin{i}); - elseif(ischar(varargin{i}) && i