Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/Coursera-Machine-Learning
Path: blob/master/Week 9/Programming Assignment - 8/ex8/lib/jsonlab/loadubjson.m
626 views
1
function data = loadubjson(fname,varargin)
2
%
3
% data=loadubjson(fname,opt)
4
% or
5
% data=loadubjson(fname,'param1',value1,'param2',value2,...)
6
%
7
% parse a JSON (JavaScript Object Notation) file or string
8
%
9
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
10
% created on 2013/08/01
11
%
12
% $Id: loadubjson.m 460 2015-01-03 00:30:45Z fangq $
13
%
14
% input:
15
% fname: input file name, if fname contains "{}" or "[]", fname
16
% will be interpreted as a UBJSON string
17
% opt: a struct to store parsing options, opt can be replaced by
18
% a list of ('param',value) pairs - the param string is equivallent
19
% to a field in opt. opt can have the following
20
% fields (first in [.|.] is the default)
21
%
22
% opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat
23
% for each element of the JSON data, and group
24
% arrays based on the cell2mat rules.
25
% opt.IntEndian [B|L]: specify the endianness of the integer fields
26
% in the UBJSON input data. B - Big-Endian format for
27
% integers (as required in the UBJSON specification);
28
% L - input integer fields are in Little-Endian order.
29
%
30
% output:
31
% dat: a cell array, where {...} blocks are converted into cell arrays,
32
% and [...] are converted to arrays
33
%
34
% examples:
35
% obj=struct('string','value','array',[1 2 3]);
36
% ubjdata=saveubjson('obj',obj);
37
% dat=loadubjson(ubjdata)
38
% dat=loadubjson(['examples' filesep 'example1.ubj'])
39
% dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1)
40
%
41
% license:
42
% BSD, see LICENSE_BSD.txt files for details
43
%
44
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
45
%
46
47
global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian
48
49
if(regexp(fname,'[\{\}\]\[]','once'))
50
string=fname;
51
elseif(exist(fname,'file'))
52
fid = fopen(fname,'rb');
53
string = fread(fid,inf,'uint8=>char')';
54
fclose(fid);
55
else
56
error('input file does not exist');
57
end
58
59
pos = 1; len = length(string); inStr = string;
60
isoct=exist('OCTAVE_VERSION','builtin');
61
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
62
jstr=regexprep(inStr,'\\\\',' ');
63
escquote=regexp(jstr,'\\"');
64
arraytoken=sort([arraytoken escquote]);
65
66
% String delimiters and escape chars identified to improve speed:
67
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]');
68
index_esc = 1; len_esc = length(esc);
69
70
opt=varargin2struct(varargin{:});
71
fileendian=upper(jsonopt('IntEndian','B',opt));
72
[os,maxelem,systemendian]=computer;
73
74
jsoncount=1;
75
while pos <= len
76
switch(next_char)
77
case '{'
78
data{jsoncount} = parse_object(opt);
79
case '['
80
data{jsoncount} = parse_array(opt);
81
otherwise
82
error_pos('Outer level structure must be an object or an array');
83
end
84
jsoncount=jsoncount+1;
85
end % while
86
87
jsoncount=length(data);
88
if(jsoncount==1 && iscell(data))
89
data=data{1};
90
end
91
92
if(~isempty(data))
93
if(isstruct(data)) % data can be a struct array
94
data=jstruct2array(data);
95
elseif(iscell(data))
96
data=jcell2array(data);
97
end
98
end
99
100
101
%%
102
function newdata=parse_collection(id,data,obj)
103
104
if(jsoncount>0 && exist('data','var'))
105
if(~iscell(data))
106
newdata=cell(1);
107
newdata{1}=data;
108
data=newdata;
109
end
110
end
111
112
%%
113
function newdata=jcell2array(data)
114
len=length(data);
115
newdata=data;
116
for i=1:len
117
if(isstruct(data{i}))
118
newdata{i}=jstruct2array(data{i});
119
elseif(iscell(data{i}))
120
newdata{i}=jcell2array(data{i});
121
end
122
end
123
124
%%-------------------------------------------------------------------------
125
function newdata=jstruct2array(data)
126
fn=fieldnames(data);
127
newdata=data;
128
len=length(data);
129
for i=1:length(fn) % depth-first
130
for j=1:len
131
if(isstruct(getfield(data(j),fn{i})))
132
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i})));
133
end
134
end
135
end
136
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn)))
137
newdata=cell(len,1);
138
for j=1:len
139
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_);
140
iscpx=0;
141
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn)))
142
if(data(j).x0x5F_ArrayIsComplex_)
143
iscpx=1;
144
end
145
end
146
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn)))
147
if(data(j).x0x5F_ArrayIsSparse_)
148
if(~isempty(strmatch('x0x5F_ArraySize_',fn)))
149
dim=double(data(j).x0x5F_ArraySize_);
150
if(iscpx && size(ndata,2)==4-any(dim==1))
151
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end));
152
end
153
if isempty(ndata)
154
% All-zeros sparse
155
ndata=sparse(dim(1),prod(dim(2:end)));
156
elseif dim(1)==1
157
% Sparse row vector
158
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end)));
159
elseif dim(2)==1
160
% Sparse column vector
161
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end)));
162
else
163
% Generic sparse array.
164
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end)));
165
end
166
else
167
if(iscpx && size(ndata,2)==4)
168
ndata(:,3)=complex(ndata(:,3),ndata(:,4));
169
end
170
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3));
171
end
172
end
173
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn)))
174
if(iscpx && size(ndata,2)==2)
175
ndata=complex(ndata(:,1),ndata(:,2));
176
end
177
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_);
178
end
179
newdata{j}=ndata;
180
end
181
if(len==1)
182
newdata=newdata{1};
183
end
184
end
185
186
%%-------------------------------------------------------------------------
187
function object = parse_object(varargin)
188
parse_char('{');
189
object = [];
190
type='';
191
count=-1;
192
if(next_char == '$')
193
type=inStr(pos+1); % TODO
194
pos=pos+2;
195
end
196
if(next_char == '#')
197
pos=pos+1;
198
count=double(parse_number());
199
end
200
if next_char ~= '}'
201
num=0;
202
while 1
203
str = parseStr(varargin{:});
204
if isempty(str)
205
error_pos('Name of value at position %d cannot be empty');
206
end
207
%parse_char(':');
208
val = parse_value(varargin{:});
209
num=num+1;
210
eval( sprintf( 'object.%s = val;', valid_field(str) ) );
211
if next_char == '}' || (count>=0 && num>=count)
212
break;
213
end
214
%parse_char(',');
215
end
216
end
217
if(count==-1)
218
parse_char('}');
219
end
220
221
%%-------------------------------------------------------------------------
222
function [cid,len]=elem_info(type)
223
id=strfind('iUIlLdD',type);
224
dataclass={'int8','uint8','int16','int32','int64','single','double'};
225
bytelen=[1,1,2,4,8,4,8];
226
if(id>0)
227
cid=dataclass{id};
228
len=bytelen(id);
229
else
230
error_pos('unsupported type at position %d');
231
end
232
%%-------------------------------------------------------------------------
233
234
235
function [data adv]=parse_block(type,count,varargin)
236
global pos inStr isoct fileendian systemendian
237
[cid,len]=elem_info(type);
238
datastr=inStr(pos:pos+len*count-1);
239
if(isoct)
240
newdata=int8(datastr);
241
else
242
newdata=uint8(datastr);
243
end
244
id=strfind('iUIlLdD',type);
245
if(id<=5 && fileendian~=systemendian)
246
newdata=swapbytes(typecast(newdata,cid));
247
end
248
data=typecast(newdata,cid);
249
adv=double(len*count);
250
251
%%-------------------------------------------------------------------------
252
253
254
function object = parse_array(varargin) % JSON array is written in row-major order
255
global pos inStr isoct
256
parse_char('[');
257
object = cell(0, 1);
258
dim=[];
259
type='';
260
count=-1;
261
if(next_char == '$')
262
type=inStr(pos+1);
263
pos=pos+2;
264
end
265
if(next_char == '#')
266
pos=pos+1;
267
if(next_char=='[')
268
dim=parse_array(varargin{:});
269
count=prod(double(dim));
270
else
271
count=double(parse_number());
272
end
273
end
274
if(~isempty(type))
275
if(count>=0)
276
[object adv]=parse_block(type,count,varargin{:});
277
if(~isempty(dim))
278
object=reshape(object,dim);
279
end
280
pos=pos+adv;
281
return;
282
else
283
endpos=matching_bracket(inStr,pos);
284
[cid,len]=elem_info(type);
285
count=(endpos-pos)/len;
286
[object adv]=parse_block(type,count,varargin{:});
287
pos=pos+adv;
288
parse_char(']');
289
return;
290
end
291
end
292
if next_char ~= ']'
293
while 1
294
val = parse_value(varargin{:});
295
object{end+1} = val;
296
if next_char == ']'
297
break;
298
end
299
%parse_char(',');
300
end
301
end
302
if(jsonopt('SimplifyCell',0,varargin{:})==1)
303
try
304
oldobj=object;
305
object=cell2mat(object')';
306
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
307
object=oldobj;
308
elseif(size(object,1)>1 && ndims(object)==2)
309
object=object';
310
end
311
catch
312
end
313
end
314
if(count==-1)
315
parse_char(']');
316
end
317
318
%%-------------------------------------------------------------------------
319
320
function parse_char(c)
321
global pos inStr len
322
skip_whitespace;
323
if pos > len || inStr(pos) ~= c
324
error_pos(sprintf('Expected %c at position %%d', c));
325
else
326
pos = pos + 1;
327
skip_whitespace;
328
end
329
330
%%-------------------------------------------------------------------------
331
332
function c = next_char
333
global pos inStr len
334
skip_whitespace;
335
if pos > len
336
c = [];
337
else
338
c = inStr(pos);
339
end
340
341
%%-------------------------------------------------------------------------
342
343
function skip_whitespace
344
global pos inStr len
345
while pos <= len && isspace(inStr(pos))
346
pos = pos + 1;
347
end
348
349
%%-------------------------------------------------------------------------
350
function str = parseStr(varargin)
351
global pos inStr esc index_esc len_esc
352
% len, ns = length(inStr), keyboard
353
type=inStr(pos);
354
if type ~= 'S' && type ~= 'C' && type ~= 'H'
355
error_pos('String starting with S expected at position %d');
356
else
357
pos = pos + 1;
358
end
359
if(type == 'C')
360
str=inStr(pos);
361
pos=pos+1;
362
return;
363
end
364
bytelen=double(parse_number());
365
if(length(inStr)>=pos+bytelen-1)
366
str=inStr(pos:pos+bytelen-1);
367
pos=pos+bytelen;
368
else
369
error_pos('End of file while expecting end of inStr');
370
end
371
372
%%-------------------------------------------------------------------------
373
374
function num = parse_number(varargin)
375
global pos inStr len isoct fileendian systemendian
376
id=strfind('iUIlLdD',inStr(pos));
377
if(isempty(id))
378
error_pos('expecting a number at position %d');
379
end
380
type={'int8','uint8','int16','int32','int64','single','double'};
381
bytelen=[1,1,2,4,8,4,8];
382
datastr=inStr(pos+1:pos+bytelen(id));
383
if(isoct)
384
newdata=int8(datastr);
385
else
386
newdata=uint8(datastr);
387
end
388
if(id<=5 && fileendian~=systemendian)
389
newdata=swapbytes(typecast(newdata,type{id}));
390
end
391
num=typecast(newdata,type{id});
392
pos = pos + bytelen(id)+1;
393
394
%%-------------------------------------------------------------------------
395
396
function val = parse_value(varargin)
397
global pos inStr len
398
true = 1; false = 0;
399
400
switch(inStr(pos))
401
case {'S','C','H'}
402
val = parseStr(varargin{:});
403
return;
404
case '['
405
val = parse_array(varargin{:});
406
return;
407
case '{'
408
val = parse_object(varargin{:});
409
if isstruct(val)
410
if(~isempty(strmatch('x0x5F_ArrayType_',fieldnames(val), 'exact')))
411
val=jstruct2array(val);
412
end
413
elseif isempty(val)
414
val = struct;
415
end
416
return;
417
case {'i','U','I','l','L','d','D'}
418
val = parse_number(varargin{:});
419
return;
420
case 'T'
421
val = true;
422
pos = pos + 1;
423
return;
424
case 'F'
425
val = false;
426
pos = pos + 1;
427
return;
428
case {'Z','N'}
429
val = [];
430
pos = pos + 1;
431
return;
432
end
433
error_pos('Value expected at position %d');
434
%%-------------------------------------------------------------------------
435
436
function error_pos(msg)
437
global pos inStr len
438
poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
439
if poShow(3) == poShow(2)
440
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after
441
end
442
msg = [sprintf(msg, pos) ': ' ...
443
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
444
error( ['JSONparser:invalidFormat: ' msg] );
445
446
%%-------------------------------------------------------------------------
447
448
function str = valid_field(str)
449
global isoct
450
% From MATLAB doc: field names must begin with a letter, which may be
451
% followed by any combination of letters, digits, and underscores.
452
% Invalid characters will be converted to underscores, and the prefix
453
% "x0x[Hex code]_" will be added if the first character is not a letter.
454
pos=regexp(str,'^[^A-Za-z]','once');
455
if(~isempty(pos))
456
if(~isoct)
457
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
458
else
459
str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
460
end
461
end
462
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end
463
if(~isoct)
464
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
465
else
466
pos=regexp(str,'[^0-9A-Za-z_]');
467
if(isempty(pos)) return; end
468
str0=str;
469
pos0=[0 pos(:)' length(str)];
470
str='';
471
for i=1:length(pos)
472
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
473
end
474
if(pos(end)~=length(str))
475
str=[str str0(pos0(end-1)+1:pos0(end))];
476
end
477
end
478
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_';
479
480
%%-------------------------------------------------------------------------
481
function endpos = matching_quote(str,pos)
482
len=length(str);
483
while(pos<len)
484
if(str(pos)=='"')
485
if(~(pos>1 && str(pos-1)=='\'))
486
endpos=pos;
487
return;
488
end
489
end
490
pos=pos+1;
491
end
492
error('unmatched quotation mark');
493
%%-------------------------------------------------------------------------
494
function [endpos e1l e1r maxlevel] = matching_bracket(str,pos)
495
global arraytoken
496
level=1;
497
maxlevel=level;
498
endpos=0;
499
bpos=arraytoken(arraytoken>=pos);
500
tokens=str(bpos);
501
len=length(tokens);
502
pos=1;
503
e1l=[];
504
e1r=[];
505
while(pos<=len)
506
c=tokens(pos);
507
if(c==']')
508
level=level-1;
509
if(isempty(e1r)) e1r=bpos(pos); end
510
if(level==0)
511
endpos=bpos(pos);
512
return
513
end
514
end
515
if(c=='[')
516
if(isempty(e1l)) e1l=bpos(pos); end
517
level=level+1;
518
maxlevel=max(maxlevel,level);
519
end
520
if(c=='"')
521
pos=matching_quote(tokens,pos+1);
522
end
523
pos=pos+1;
524
end
525
if(endpos==0)
526
error('unmatched "]"');
527
end
528
529
530