0001 function data = loadubjson(fname,varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian
0053
0054 if(regexp(fname,'[\{\}\]\[]','once'))
0055 string=fname;
0056 elseif(exist(fname,'file'))
0057 fid = fopen(fname,'rb');
0058 string = fread(fid,inf,'uint8=>char')';
0059 fclose(fid);
0060 else
0061 error('input file does not exist');
0062 end
0063
0064 pos = 1; len = length(string); inStr = string;
0065 isoct=exist('OCTAVE_VERSION','builtin');
0066 arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
0067 jstr=regexprep(inStr,'\\\\',' ');
0068 escquote=regexp(jstr,'\\"');
0069 arraytoken=sort([arraytoken escquote]);
0070
0071
0072 esc = find(inStr=='"' | inStr=='\' );
0073 index_esc = 1; len_esc = length(esc);
0074
0075 opt=varargin2struct(varargin{:});
0076 fileendian=upper(jsonopt('IntEndian','B',opt));
0077 [os,maxelem,systemendian]=computer;
0078
0079 jsoncount=1;
0080 while pos <= len
0081 switch(next_char)
0082 case '{'
0083 data{jsoncount} = parse_object(opt);
0084 case '['
0085 data{jsoncount} = parse_array(opt);
0086 otherwise
0087 error_pos('Outer level structure must be an object or an array');
0088 end
0089 jsoncount=jsoncount+1;
0090 end
0091
0092 jsoncount=length(data);
0093 if(jsoncount==1 && iscell(data))
0094 data=data{1};
0095 end
0096
0097
0098 function object = parse_object(varargin)
0099 parse_char('{');
0100 object = [];
0101 type='';
0102 count=-1;
0103 if(next_char == '$')
0104 type=inStr(pos+1);
0105 pos=pos+2;
0106 end
0107 if(next_char == '#')
0108 pos=pos+1;
0109 count=double(parse_number());
0110 end
0111 if next_char ~= '}'
0112 num=0;
0113 while 1
0114 if(jsonopt('NameIsString',0,varargin{:}))
0115 str = parseStr(varargin{:});
0116 else
0117 str = parse_name(varargin{:});
0118 end
0119 if isempty(str)
0120 error_pos('Name of value at position %d cannot be empty');
0121 end
0122
0123 val = parse_value(varargin{:});
0124 num=num+1;
0125 object.(valid_field(str))=val;
0126 if next_char == '}' || (count>=0 && num>=count)
0127 break;
0128 end
0129
0130 end
0131 end
0132 if(count==-1)
0133 parse_char('}');
0134 end
0135 if(isstruct(object))
0136 object=struct2jdata(object);
0137 end
0138
0139
0140 function [cid,len]=elem_info(type)
0141 id=strfind('iUIlLdD',type);
0142 dataclass={'int8','uint8','int16','int32','int64','single','double'};
0143 bytelen=[1,1,2,4,8,4,8];
0144 if(id>0)
0145 cid=dataclass{id};
0146 len=bytelen(id);
0147 else
0148 error_pos('unsupported type at position %d');
0149 end
0150
0151
0152
0153 function [data, adv]=parse_block(type,count,varargin)
0154 global pos inStr isoct fileendian systemendian
0155 [cid,len]=elem_info(type);
0156 datastr=inStr(pos:pos+len*count-1);
0157 newdata=uint8(datastr);
0158 id=strfind('iUIlLdD',type);
0159 if(fileendian~=systemendian)
0160 newdata=swapbytes(typecast(newdata,cid));
0161 end
0162 data=typecast(newdata,cid);
0163 adv=double(len*count);
0164
0165
0166
0167
0168 function object = parse_array(varargin)
0169 global pos inStr
0170 parse_char('[');
0171 object = cell(0, 1);
0172 dim=[];
0173 type='';
0174 count=-1;
0175 if(next_char == '$')
0176 type=inStr(pos+1);
0177 pos=pos+2;
0178 end
0179 if(next_char == '#')
0180 pos=pos+1;
0181 if(next_char=='[')
0182 dim=parse_array(varargin{:});
0183 count=prod(double(dim));
0184 else
0185 count=double(parse_number());
0186 end
0187 end
0188 if(~isempty(type))
0189 if(count>=0)
0190 [object, adv]=parse_block(type,count,varargin{:});
0191 if(~isempty(dim))
0192 object=reshape(object,dim);
0193 end
0194 pos=pos+adv;
0195 return;
0196 else
0197 endpos=matching_bracket(inStr,pos);
0198 [cid,len]=elem_info(type);
0199 count=(endpos-pos)/len;
0200 [object, adv]=parse_block(type,count,varargin{:});
0201 pos=pos+adv;
0202 parse_char(']');
0203 return;
0204 end
0205 end
0206 if next_char ~= ']'
0207 while 1
0208 val = parse_value(varargin{:});
0209 object{end+1} = val;
0210 if next_char == ']'
0211 break;
0212 end
0213
0214 end
0215 end
0216 if(jsonopt('SimplifyCell',0,varargin{:})==1)
0217 try
0218 oldobj=object;
0219 object=cell2mat(object')';
0220 if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
0221 object=oldobj;
0222 elseif(size(object,1)>1 && ismatrix(object))
0223 object=object';
0224 end
0225 catch
0226 end
0227 end
0228 if(count==-1)
0229 parse_char(']');
0230 end
0231
0232
0233
0234 function parse_char(c)
0235 global pos inStr len
0236 skip_whitespace;
0237 if pos > len || inStr(pos) ~= c
0238 error_pos(sprintf('Expected %c at position %%d', c));
0239 else
0240 pos = pos + 1;
0241 skip_whitespace;
0242 end
0243
0244
0245
0246 function c = next_char
0247 global pos inStr len
0248 skip_whitespace;
0249 if pos > len
0250 c = [];
0251 else
0252 c = inStr(pos);
0253 end
0254
0255
0256
0257 function skip_whitespace
0258 global pos inStr len
0259 while pos <= len && isspace(inStr(pos))
0260 pos = pos + 1;
0261 end
0262
0263
0264 function str = parse_name(varargin)
0265 global pos inStr
0266 bytelen=double(parse_number());
0267 if(length(inStr)>=pos+bytelen-1)
0268 str=inStr(pos:pos+bytelen-1);
0269 pos=pos+bytelen;
0270 else
0271 error_pos('End of file while expecting end of name');
0272 end
0273
0274
0275 function str = parseStr(varargin)
0276 global pos inStr
0277
0278 type=inStr(pos);
0279 if type ~= 'S' && type ~= 'C' && type ~= 'H'
0280 error_pos('String starting with S expected at position %d');
0281 else
0282 pos = pos + 1;
0283 end
0284 if(type == 'C')
0285 str=inStr(pos);
0286 pos=pos+1;
0287 return;
0288 end
0289 bytelen=double(parse_number());
0290 if(length(inStr)>=pos+bytelen-1)
0291 str=inStr(pos:pos+bytelen-1);
0292 pos=pos+bytelen;
0293 else
0294 error_pos('End of file while expecting end of inStr');
0295 end
0296
0297
0298
0299 function num = parse_number(varargin)
0300 global pos inStr isoct fileendian systemendian
0301 id=strfind('iUIlLdD',inStr(pos));
0302 if(isempty(id))
0303 error_pos('expecting a number at position %d');
0304 end
0305 type={'int8','uint8','int16','int32','int64','single','double'};
0306 bytelen=[1,1,2,4,8,4,8];
0307 datastr=inStr(pos+1:pos+bytelen(id));
0308 newdata=uint8(datastr);
0309 if(fileendian~=systemendian)
0310 newdata=swapbytes(typecast(newdata,type{id}));
0311 end
0312 num=typecast(newdata,type{id});
0313 pos = pos + bytelen(id)+1;
0314
0315
0316
0317 function val = parse_value(varargin)
0318 global pos inStr
0319
0320 switch(inStr(pos))
0321 case {'S','C','H'}
0322 val = parseStr(varargin{:});
0323 return;
0324 case '['
0325 val = parse_array(varargin{:});
0326 return;
0327 case '{'
0328 val = parse_object(varargin{:});
0329 return;
0330 case {'i','U','I','l','L','d','D'}
0331 val = parse_number(varargin{:});
0332 return;
0333 case 'T'
0334 val = true;
0335 pos = pos + 1;
0336 return;
0337 case 'F'
0338 val = false;
0339 pos = pos + 1;
0340 return;
0341 case {'Z','N'}
0342 val = [];
0343 pos = pos + 1;
0344 return;
0345 end
0346 error_pos('Value expected at position %d');
0347
0348
0349 function error_pos(msg)
0350 global pos inStr len
0351 poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
0352 if poShow(3) == poShow(2)
0353 poShow(3:4) = poShow(2)+[0 -1];
0354 end
0355 msg = [sprintf(msg, pos) ': ' ...
0356 inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
0357 error( ['JSONparser:invalidFormat: ' msg] );
0358
0359
0360
0361 function str = valid_field(str)
0362 global isoct
0363
0364
0365
0366
0367 pos=regexp(str,'^[^A-Za-z]','once');
0368 if(~isempty(pos))
0369 if(~isoct)
0370 str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
0371 else
0372 str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
0373 end
0374 end
0375 if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' )))
0376 return;
0377 end
0378 if(~isoct)
0379 str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
0380 else
0381 pos=regexp(str,'[^0-9A-Za-z_]');
0382 if(isempty(pos))
0383 return;
0384 end
0385 str0=str;
0386 pos0=[0 pos(:)' length(str)];
0387 str='';
0388 for i=1:length(pos)
0389 str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
0390 end
0391 if(pos(end)~=length(str))
0392 str=[str str0(pos0(end-1)+1:pos0(end))];
0393 end
0394 end
0395
0396
0397
0398 function endpos = matching_quote(str,pos)
0399 len=length(str);
0400 while(pos<len)
0401 if(str(pos)=='"')
0402 if(~(pos>1 && str(pos-1)=='\'))
0403 endpos=pos;
0404 return;
0405 end
0406 end
0407 pos=pos+1;
0408 end
0409 error('unmatched quotation mark');
0410
0411 function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos)
0412 global arraytoken
0413 level=1;
0414 maxlevel=level;
0415 endpos=0;
0416 bpos=arraytoken(arraytoken>=pos);
0417 tokens=str(bpos);
0418 len=length(tokens);
0419 pos=1;
0420 e1l=[];
0421 e1r=[];
0422 while(pos<=len)
0423 c=tokens(pos);
0424 if(c==']')
0425 level=level-1;
0426 if(isempty(e1r))
0427 e1r=bpos(pos);
0428 end
0429 if(level==0)
0430 endpos=bpos(pos);
0431 return
0432 end
0433 end
0434 if(c=='[')
0435 if(isempty(e1l))
0436 e1l=bpos(pos);
0437 end
0438 level=level+1;
0439 maxlevel=max(maxlevel,level);
0440 end
0441 if(c=='"')
0442 pos=matching_quote(tokens,pos+1);
0443 end
0444 pos=pos+1;
0445 end
0446 if(endpos==0)
0447 error('unmatched "]"');
0448 end
0449