From 398539d109a2299fce02ba02403e7f67a4cc820f Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Wed, 23 Oct 2019 20:12:40 -0400 Subject: [PATCH] reoptimize for speed --- decodevarname.m | 12 ++++-- encodevarname.m | 2 +- jdatadecode.m | 43 +++++++++++--------- jsonopt.m | 7 ++-- loadjson.m | 8 ++-- loadubjson.m | 7 ++-- mergestruct.m | 4 +- savejson.m | 105 ++++++++++++++++++++++++++---------------------- 8 files changed, 105 insertions(+), 83 deletions(-) diff --git a/decodevarname.m b/decodevarname.m index 4a4e3fa..20c8753 100644 --- a/decodevarname.m +++ b/decodevarname.m @@ -30,12 +30,18 @@ % 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 b336f2d..5534f8a 100644 --- a/encodevarname.m +++ b/encodevarname.m @@ -37,7 +37,7 @@ % 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 641096d..99cc062 100644 --- a/jdatadecode.m +++ b/jdatadecode.m @@ -54,7 +54,12 @@ % 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 8e1a9d3..bd7ef68 100644 --- a/jsonopt.m +++ b/jsonopt.m @@ -25,11 +25,12 @@ 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 a7964aa..ae74e93 100644 --- a/loadjson.m +++ b/loadjson.m @@ -130,6 +130,10 @@ 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 @@ 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 14d4d42..06472a4 100644 --- a/loadubjson.m +++ b/loadubjson.m @@ -92,6 +92,10 @@ 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 @@ 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 befbc4d..3c52083 100644 --- a/mergestruct.m +++ b/mergestruct.m @@ -27,7 +27,7 @@ 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 3872454..19583d5 100644 --- a/savejson.m +++ b/savejson.m @@ -132,13 +132,25 @@ 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 @@ 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 @@ nl=whitespaces.newline; json=obj2json(rootname,obj,rootlevel,opt); + if(rootisarray) json=sprintf('%s%s',json,nl); else @@ -254,7 +267,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ %%------------------------------------------------------------------------- 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 @@ 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 @@ 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