diff --git a/decodevarname.m b/decodevarname.m index 4a4e3fa5af351016c3c90ec285d63993598f963a..20c87536146ec5ffce7293ed83a87c982046024c 100644 --- a/decodevarname.m +++ b/decodevarname.m @@ -30,12 +30,18 @@ function newname = decodevarname(name,varargin) % License: GPLv3 or 3-clause BSD license, see https://github.com/fangq/easyh5 for details % -isunpack=jsonopt('UnpackHex',1,varargin{:}); newname=name; -if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) - return +isunpack=1; +if(nargin==2 && ~isstruct(varargin{1})) + isunpack=varargin{1}; +elseif(nargin>1) + isunpack=jsonopt('UnpackHex',1,varargin{:}); end + if(isunpack) + if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) + return + end if(exist('native2unicode','builtin')) h2u=@hex2unicode; newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${h2u($2)}'); diff --git a/encodevarname.m b/encodevarname.m index b336f2dd3d19f0a27e4d9f2c4cdb8127cec40dad..5534f8a7ba182c5130a36370aeeb3743904e6c65 100644 --- a/encodevarname.m +++ b/encodevarname.m @@ -37,7 +37,7 @@ function str = encodevarname(str,varargin) % License: GPLv3 or 3-clause BSD license, see https://github.com/fangq/easyh5 for details % - if(~isempty(regexp(str,'^[^A-Za-z]','once'))) + if(~isvarname(str(1))) if(exist('unicode2native','builtin')) str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); else diff --git a/jdatadecode.m b/jdatadecode.m index 641096dd395e28983ca8dbc9b1cf12e2af00a693..99cc0629db4a4c5454a03c909674192d812bd7f9 100644 --- a/jdatadecode.m +++ b/jdatadecode.m @@ -54,7 +54,12 @@ function newdata=jdatadecode(data,varargin) % newdata=data; - opt=varargin2struct(varargin{:}); + opt=struct; + if(nargin==2) + opt=varargin{1}; + elseif(nargin>2) + opt=varargin2struct(varargin{:}); + end %% process non-structure inputs if(~isstruct(data)) @@ -75,8 +80,8 @@ function newdata=jdatadecode(data,varargin) len=length(data); needbase64=jsonopt('Base64',0,opt); format=jsonopt('FormatVersion',2,opt); - prefix=jsonopt('Prefix',sprintf('x0x%X','_'+0),opt); - if(~any(ismember(N_('_ArrayType_'),fn)) && any(ismember('x_ArrayType_',fn))) + prefix=jsonopt('Prefix','x0x5F',opt); + if(~isfield(data,N_('_ArrayType_')) && isfield(data,'x_ArrayType_')) prefix='x'; opt.prefix='x'; end @@ -95,15 +100,15 @@ function newdata=jdatadecode(data,varargin) end %% handle array data - if(any(ismember(N_('_ArrayType_'),fn)) && (any(ismember(N_('_ArrayData_'),fn)) || any(ismember(N_('_ArrayZipData_'),fn)))) + if(isfield(data,N_('_ArrayType_')) && (isfield(data,N_('_ArrayData_')) || isfield(data,N_('_ArrayZipData_')))) newdata=cell(len,1); for j=1:len - if(any(ismember(N_('_ArrayZipSize_'),fn)) && any(ismember(N_('_ArrayZipData_'),fn))) + if(isfield(data,N_('_ArrayZipSize_')) && isfield(data,N_('_ArrayZipData_'))) zipmethod='zip'; - if(any(ismember(N_('_ArrayZipType_'),fn))) + if(isfield(data,N_('_ArrayZipType_'))) zipmethod=data(j).(N_('_ArrayZipType_')); end - if(any(ismember(zipmethod,{'zlib','gzip','lzma','lzip','lz4','lz4hc'}))) + if(~isempty(strmatch(zipmethod,{'zlib','gzip','lzma','lzip','lz4','lz4hc'}))) decompfun=str2func([zipmethod 'decode']); if(needbase64) ndata=reshape(typecast(decompfun(base64decode(data(j).(N_('_ArrayZipData_')))),data(j).(N_('_ArrayType_'))),data(j).(N_('_ArrayZipSize_'))(:)'); @@ -119,18 +124,18 @@ function newdata=jdatadecode(data,varargin) end ndata=cast(data(j).(N_('_ArrayData_')),char(data(j).(N_('_ArrayType_')))); end - if(any(ismember(N_('_ArrayZipSize_'),fn))) + if(isfield(data,N_('_ArrayZipSize_'))) ndata=reshape(ndata(:),fliplr(data(j).(N_('_ArrayZipSize_'))(:)')); ndata=permute(ndata,ndims(ndata):-1:1); end iscpx=0; - if(any(ismember(N_('_ArrayIsComplex_'),fn))) + if(isfield(data,N_('_ArrayIsComplex_'))) if(data(j).(N_('_ArrayIsComplex_'))) iscpx=1; end end - if(any(ismember(N_('_ArrayIsSparse_'),fn)) && data(j).(N_('_ArrayIsSparse_'))) - if(any(ismember(N_('_ArraySize_'),fn))) + if(isfield(data,N_('_ArrayIsSparse_')) && data(j).(N_('_ArrayIsSparse_'))) + if(isfield(data,N_('_ArraySize_'))) dim=double(data(j).(N_('_ArraySize_'))(:)'); if(iscpx) ndata(end-1,:)=complex(ndata(end-1,:),ndata(end,:)); @@ -154,7 +159,7 @@ function newdata=jdatadecode(data,varargin) end ndata=sparse(ndata(1,:),ndata(2,:),ndata(3,:)); end - elseif(any(ismember(N_('_ArraySize_'),fn))) + elseif(isfield(data,N_('_ArraySize_'))) if(iscpx) ndata=complex(ndata(1,:),ndata(2,:)); end @@ -175,7 +180,7 @@ function newdata=jdatadecode(data,varargin) end %% handle table data - if(any(ismember(N_('_TableRecords_'),fn))) + if(isfield(data,N_('_TableRecords_'))) newdata=cell(len,1); for j=1:len ndata=data(j).(N_('_TableRecords_')); @@ -205,7 +210,7 @@ function newdata=jdatadecode(data,varargin) end %% handle map data - if(any(ismember(N_('_MapData_'),fn))) + if(isfield(data,N_('_MapData_'))) newdata=cell(len,1); for j=1:len key=cell(1,length(data(j).(N_('_MapData_')))); @@ -223,7 +228,7 @@ function newdata=jdatadecode(data,varargin) end %% handle graph data - if(any(ismember(N_('_GraphNodes_'),fn)) && exist('graph','file') && exist('digraph','file')) + if(isfield(data,N_('_GraphNodes_')) && exist('graph','file') && exist('digraph','file')) newdata=cell(len,1); isdirected=1; for j=1:len @@ -241,12 +246,12 @@ function newdata=jdatadecode(data,varargin) nodetable=table; end - if(any(ismember(N_('_GraphEdges_'),fn))) + if(isfield(data,N_('_GraphEdges_'))) edgedata=data(j).(N_('_GraphEdges_')); - elseif(any(ismember(N_('_GraphEdges0_'),fn))) + elseif(isfield(data,N_('_GraphEdges0_'))) edgedata=data(j).(N_('_GraphEdges0_')); isdirected=0; - elseif(any(ismember(N_('_GraphMatrix_'),fn))) + elseif(isfield(data,N_('_GraphMatrix_'))) edgedata=jdatadecode(data(j).(N_('_GraphMatrix_')),varargin{:}); end @@ -273,7 +278,7 @@ function newdata=jdatadecode(data,varargin) end %% handle bytestream and arbitrary matlab objects - if(sum(ismember({N_('_ByteStream_'),N_('_DataInfo_')},fn))==2) + if(isfield(data,N_('_ByteStream_')) && isfield(data,N_('_DataInfo_'))==2) newdata=cell(len,1); for j=1:len if(isfield(data(j).(N_('_DataInfo_')),'MATLABObjectClass')) diff --git a/jsonopt.m b/jsonopt.m index 8e1a9d3efc67f59f44eb2ffb547157630fd87ef4..bd7ef6816813af09222f5c5f26a7c3be0d70f9df 100644 --- a/jsonopt.m +++ b/jsonopt.m @@ -25,11 +25,12 @@ val=default; if(nargin<=2) return; end +key0=lower(key); opt=varargin{1}; if(isstruct(opt)) - if(isfield(opt,key)) + if(isfield(opt,key0)) + val=opt.(key0); + elseif(isfield(opt,key)) val=opt.(key); - elseif(isfield(opt,lower(key))) - val=opt.(lower(key)); end end diff --git a/loadjson.m b/loadjson.m index a7964aad94db18babb6637302eae8a6e77103183..ae74e932c2ceb0ce8120cd1962908159229fa18d 100644 --- a/loadjson.m +++ b/loadjson.m @@ -130,6 +130,10 @@ function data = loadjson(fname,varargin) data=data{1}; end + if(jsonopt('JDataDecode',1,varargin{:})==1) + data=jdatadecode(data,'Base64',1,'Recursive',1,varargin{:}); + end + if(isfield(opt,'progressbar_')) close(opt.progressbar_); end @@ -425,10 +429,6 @@ function [object, pos, index_esc] = parse_object(inputstr, pos, esc, index_esc, end end pos=parse_char(inputstr, pos, '}'); - if(jsonopt('JDataDecode',1,varargin{:})==1) - varargin{:}.Recursive=0; - object=jdatadecode(object,'Base64',1,varargin{:}); - end end %%------------------------------------------------------------------------- diff --git a/loadubjson.m b/loadubjson.m index 14d4d42e939d918ace8079ff22c751d43f0ece48..06472a4d3dafea9315d685abd434f50acb5b4e0c 100644 --- a/loadubjson.m +++ b/loadubjson.m @@ -92,6 +92,10 @@ function data = loadubjson(fname,varargin) if(jsoncount==1 && iscell(data)) data=data{1}; end + + if(jsonopt('JDataDecode',1,varargin{:})==1) + data=jdatadecode(data,'Base64',0,'Recursive',1,varargin{:}); + end end %%------------------------------------------------------------------------- @@ -338,9 +342,6 @@ function [object, pos] = parse_object(inputstr, pos, varargin) if(count==-1) pos=parse_char(inputstr, pos, '}'); end - if(isstruct(object)) - object=jdatadecode(object,'Recursive',0, 'Base64',0,varargin{:}); - end end %%------------------------------------------------------------------------- diff --git a/mergestruct.m b/mergestruct.m index befbc4d4d58669b4c4d5dcafa2520703b8c61f55..3c52083906ca5f697976219b72cf46b52f16ea24 100644 --- a/mergestruct.m +++ b/mergestruct.m @@ -27,7 +27,7 @@ if(length(s1)>1 || length(s2)>1) end fn=fieldnames(s2); s=s1; -for i=1:length(fn) - s=setfield(s,fn{i},getfield(s2,fn{i})); +for i=1:length(fn) + s.(fn{i})=s2.(fn{i}); end diff --git a/savejson.m b/savejson.m index 387245437c327570e2cf4acc13bfc02f647e5c3e..19583d562a811769a5d89fab7b756edd4e23ad58 100644 --- a/savejson.m +++ b/savejson.m @@ -132,13 +132,25 @@ if(length(varargin)==1 && ischar(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',2,opt); +opt.compressarraysize=jsonopt('CompressArraySize',100,opt); +opt.intformat=jsonopt('IntFormat','%d',opt); +opt.floatformat=jsonopt('FloatFormat','%.10g',opt); +opt.unpackhex=jsonopt('UnpackHex',1,opt); + if(jsonopt('PreEncode',1,opt)) obj=jdataencode(obj,'Base64',1,'UseArrayZipSize',0,opt); end -dozip=jsonopt('Compression','',opt); +dozip=opt.compression; if(~isempty(dozip)) if(isempty(strmatch(dozip,{'zlib','gzip','lzma','lzip','lz4','lz4hc'}))) error('compression method "%s" is not supported',dozip); @@ -178,7 +190,7 @@ if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot) end whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); -if(jsonopt('Compact',0,opt)==1) +if(opt.compact==1) whitespaces=struct('tab','','newline','','sep',','); end if(~isfield(opt,'whitespaces_')) @@ -188,6 +200,7 @@ end nl=whitespaces.newline; json=obj2json(rootname,obj,rootlevel,opt); + if(rootisarray) json=sprintf('%s%s',json,nl); else @@ -254,7 +267,7 @@ isnum2cell=jsonopt('num2cell_',0,varargin{:}); if(isnum2cell) item=squeeze(item); else - format=jsonopt('FormatVersion',2,varargin{:}); + format=varargin{1}.formatversion; if(format>1.9 && ~isvector(item)) item=permute(item,ndims(item):-1:1); end @@ -266,20 +279,20 @@ if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now dim=size(item); end len=numel(item); -ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:}); +ws=varargin{1}.whitespaces_; padding0=repmat(ws.tab,1,level); padding2=repmat(ws.tab,1,level+1); nl=ws.newline; -bracketlevel=~jsonopt('SingletCell',1,varargin{:}); +bracketlevel=~varargin{1}.singletcell; if(len>bracketlevel) if(~isempty(name)) - txt={padding0, '"', decodevarname(name,varargin{:}),'": [', nl}; name=''; + txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'": [', nl}; name=''; else txt={padding0, '[', nl}; end elseif(len==0) if(~isempty(name)) - txt={padding0, '"' decodevarname(name,varargin{:}) '": []'}; name=''; + txt={padding0, '"' decodevarname(name,varargin{1}.unpackhex) '": []'}; name=''; else txt={padding0, '[]'}; end @@ -319,9 +332,8 @@ if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now dim=size(item); end len=numel(item); -forcearray= (len>1 || (jsonopt('SingletArray',0,varargin{:})==1 && level>0)); -ws=struct('tab',sprintf('\t'),'newline',sprintf('\n')); -ws=jsonopt('whitespaces_',ws,varargin{:}); +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); @@ -329,7 +341,7 @@ nl=ws.newline; if(isempty(item)) if(~isempty(name)) - txt={padding0, '"', decodevarname(name,varargin{:}),'": []'}; + txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'": []'}; else txt={padding0, '[]'}; end @@ -338,7 +350,7 @@ if(isempty(item)) end if(~isempty(name)) if(forcearray) - txt={padding0, '"', decodevarname(name,varargin{:}),'": [', nl}; + txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'": [', nl}; end else if(forcearray) @@ -352,7 +364,7 @@ for j=1:dim(2) 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{:}),'": {', nl}; + txt(end+1:end+5)={padding1, '"', decodevarname(name,varargin{1}.unpackhex),'": {', nl}; else txt(end+1:end+3)={padding1, '{', nl}; end @@ -409,15 +421,14 @@ if(~strcmp(item.KeyType,'char')) end len=prod(dim); -forcearray= (len>1 || (jsonopt('SingletArray',0,varargin{:})==1 && level>0)); -ws=struct('tab',sprintf('\t'),'newline',sprintf('\n')); -ws=jsonopt('whitespaces_',ws,varargin{:}); +forcearray= (len>1 || (varargin{1}.singletarray==1 && level>0)); +ws=varargin{1}.whitespaces_; padding0=repmat(ws.tab,1,level); nl=ws.newline; if(isempty(item)) if(~isempty(name)) - txt={padding0, '"', decodevarname(name,varargin{:}),'": []'}; + txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'": []'}; else txt={padding0, '[]'}; end @@ -426,7 +437,7 @@ if(isempty(item)) end if(~isempty(name)) if(forcearray) - txt={padding0, '"', decodevarname(name,varargin{:}),'": {', nl}; + txt={padding0, '"', decodevarname(name,varargin{1}.unpackhex),'": {', nl}; end else if(forcearray) @@ -459,8 +470,7 @@ if(~ischar(item)) end item=reshape(item, max(size(item),[1 0])); len=size(item,1); -ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); -ws=jsonopt('whitespaces_',ws,varargin{:}); +ws=varargin{1}.whitespaces_; padding1=repmat(ws.tab,1,level); padding0=repmat(ws.tab,1,level+1); nl=ws.newline; @@ -468,7 +478,7 @@ sep=ws.sep; if(~isempty(name)) if(len>1) - txt={padding1, '"', decodevarname(name,varargin{:}),'": [', nl}; + txt={padding1, '"', decodevarname(name,varargin{1}.unpackhex),'": [', nl}; end else if(len>1) @@ -478,7 +488,7 @@ end for e=1:len val=escapejsonstring(item(e,:)); if(len==1) - obj=['"' decodevarname(name,varargin{:}) '": ' '"',val,'"']; + obj=['"' decodevarname(name,varargin{1}.unpackhex) '": ' '"',val,'"']; if(isempty(name)) obj=['"',val,'"']; end @@ -501,39 +511,35 @@ function txt=mat2json(name,item,level,varargin) if(~isnumeric(item) && ~islogical(item)) error('input is not an array'); end -ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); -ws=jsonopt('whitespaces_',ws,varargin{:}); +ws=varargin{1}.whitespaces_; padding1=repmat(ws.tab,1,level); padding0=repmat(ws.tab,1,level+1); nl=ws.newline; sep=ws.sep; -dozip=jsonopt('Compression','',varargin{:}); -zipsize=jsonopt('CompressArraySize',100,varargin{:}); -format=jsonopt('FormatVersion',2,varargin{:}); +dozip=varargin{1}.compression; +zipsize=varargin{1}.compressarraysize; +format=varargin{1}.formatversion; +isnest=varargin{1}.nestarray; -if(((jsonopt('NestArray',0,varargin{:})==0) && length(size(item))>2) || issparse(item) || ~isreal(item) || ... +if(((isnest==0) && length(size(item))>2) || issparse(item) || ~isreal(item) || ... (isempty(item) && any(size(item))) ||jsonopt('ArrayToStruct',0,varargin{:}) || (~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{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); + padding1,decodevarname(name,varargin{1}.unpackhex),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl); end else - if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0 && level>0) - numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']$',''); - else - numtxt=matdata2json(item,level+1,varargin{:}); - end + numtxt=matdata2json(item,level+1,varargin{:}); if(isempty(name)) txt=sprintf('%s%s',padding1,numtxt); else - if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0) - txt=sprintf('%s"%s": %s',padding1,decodevarname(name,varargin{:}),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{:}),numtxt); + txt=sprintf('%s"%s": %s',padding1,decodevarname(name,varargin{1}.unpackhex),numtxt); end end return; @@ -651,12 +657,11 @@ end %%------------------------------------------------------------------------- function txt=matdata2json(mat,level,varargin) -ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')); -ws=jsonopt('whitespaces_',ws,varargin{:}); +ws=varargin{1}.whitespaces_; tab=ws.tab; nl=ws.newline; -isnest=jsonopt('NestArray',0,varargin{:}); -format=jsonopt('FormatVersion',2,varargin{:}); +isnest=varargin{1}.nestarray; +format=varargin{1}.formatversion; isnum2cell=jsonopt('num2cell_',0,varargin{:}); if(~isvector(mat) && isnest==1) @@ -688,12 +693,15 @@ if(isempty(mat)) return; end if(isinteger(mat)) - floatformat=jsonopt('FloatFormat','%d',varargin{:}); + floatformat=varargin{1}.intformat; else - floatformat=jsonopt('FloatFormat','%.10g',varargin{:}); + 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)]]; +else + formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; end -formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]]; - if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1) formatstr=[repmat(tab,1,level) formatstr]; end @@ -739,14 +747,15 @@ if(isoct) end if(isoct) escapechars={'\\','\"','\/','\a','\f','\n','\r','\t','\v'}; - for i=1:length(escapechars); + 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'}; - for i=1:length(escapechars); - newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\')); + 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