1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
|
function data = loadmsgpack(fname, varargin)
%
% data = loadmsgpack(fname,varargin)
%
% LOADMSGPACK parses a msgpack byte buffer into Matlab data structures
% LOADMSGPACK(BYTES)
% reads BYTES as msgpack data, and creates Matlab data structures
% from it.
% - strings are converted to strings
% - numbers are converted to appropriate numeric values
% - true, false are converted to logical 1, 0
% - nil is converted to []
% - arrays are converted to cell arrays
% - maps are converted to containers.Map
%
% (c) 2016 Bastian Bechtold
% modified by Qianqian Fang <q.fang at neu.edu>
%
% license:
% BSD 3-clause license 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 (exist(fname, 'file'))
fid = fopen(fname, 'rb');
bytes = fread(fid, inf, 'uint8=>char')';
fclose(fid);
else
bytes = fname;
end
opt = varargin2struct(varargin{:});
opt.simplifycell = jsonopt('SimplifyCell', 1, opt);
opt.simplifycellarray = jsonopt('SimplifyCellArray', 0, opt);
jsoncount = 1;
idx = 0;
while idx <= length(bytes)
[obj, idx] = parse(uint8(bytes(:)), 1, opt);
data{jsoncount} = obj;
jsoncount = jsoncount + 1;
end
jsoncount = length(data);
if (jsoncount == 1 && iscell(data))
data = data{1};
end
if (iscell(data))
data = cellfun(@(x) jdatadecode(x), data, 'UniformOutput', false);
elseif (isstruct(data))
data = jdatadecode(data, 'Base64', 0, opt);
end
function [obj, idx] = parse(bytes, idx, varargin)
% masks:
b10000000 = 128;
b01111111 = 127;
b11000000 = 192;
b00111111 = 63;
b11100000 = 224;
b00011111 = 31;
b11110000 = 240;
b00001111 = 15;
% values:
b00000000 = 0;
b10010000 = 144;
b10100000 = 160;
currentbyte = bytes(idx);
if bitand(b10000000, currentbyte) == b00000000
% decode positive fixint
obj = int8(currentbyte);
idx = idx + 1;
return
elseif bitand(b11100000, currentbyte) == b11100000
% decode negative fixint
obj = typecast(currentbyte, 'int8');
idx = idx + 1;
return
elseif bitand(b11110000, currentbyte) == b10000000
% decode fixmap
len = double(bitand(b00001111, currentbyte));
[obj, idx] = parsemap(len, bytes, idx + 1, varargin{:});
return
elseif bitand(b11110000, currentbyte) == b10010000
% decode fixarray
len = double(bitand(b00001111, currentbyte));
[obj, idx] = parsearray(len, bytes, idx + 1, varargin{:});
return
elseif bitand(b11100000, currentbyte) == b10100000
% decode fixstr
len = double(bitand(b00011111, currentbyte));
[obj, idx] = parsestring(len, bytes, idx + 1);
return
end
switch currentbyte
case 192 % nil
obj = [];
idx = idx + 1;
% case 193 % unused
case 194 % false
obj = false;
idx = idx + 1;
case 195 % true
obj = true;
idx = idx + 1;
case 196 % bin8
len = double(bytes(idx + 1));
[obj, idx] = parsebytes(len, bytes, idx + 2);
case 197 % bin16
len = double(bytes2scalar(bytes(idx + 1:idx + 2), 'uint16'));
[obj, idx] = parsebytes(len, bytes, idx + 3);
case 198 % bin32
len = double(bytes2scalar(bytes(idx + 1:idx + 4), 'uint32'));
[obj, idx] = parsebytes(len, bytes, idx + 5);
case 199 % ext8
len = double(bytes(idx + 1));
[obj, idx] = parseext(len, bytes, idx + 1);
case 200 % ext16
len = double(bytes2scalar(bytes(idx + 1:idx + 2), 'uint16'));
[obj, idx] = parseext(len, bytes, idx + 3);
case 201 % ext32
len = double(bytes2scalar(bytes(idx + 1:idx + 4), 'uint32'));
[obj, idx] = parseext(len, bytes, idx + 5);
case 202 % float32
obj = bytes2scalar(bytes(idx + 1:idx + 4), 'single');
idx = idx + 5;
case 203 % float64
obj = bytes2scalar(bytes(idx + 1:idx + 8), 'double');
idx = idx + 9;
case 204 % uint8
obj = bytes(idx + 1);
idx = idx + 2;
case 205 % uint16
obj = bytes2scalar(bytes(idx + 1:idx + 2), 'uint16');
idx = idx + 3;
case 206 % uint32
obj = bytes2scalar(bytes(idx + 1:idx + 4), 'uint32');
idx = idx + 5;
case 207 % uint64
obj = bytes2scalar(bytes(idx + 1:idx + 8), 'uint64');
idx = idx + 9;
case 208 % int8
obj = bytes2scalar(bytes(idx + 1), 'int8');
idx = idx + 2;
case 209 % int16
obj = bytes2scalar(bytes(idx + 1:idx + 2), 'int16');
idx = idx + 3;
case 210 % int32
obj = bytes2scalar(bytes(idx + 1:idx + 4), 'int32');
idx = idx + 5;
case 211 % int64
obj = bytes2scalar(bytes(idx + 1:idx + 8), 'int64');
idx = idx + 9;
case 212 % fixext1
[obj, idx] = parseext(1, bytes, idx + 1);
case 213 % fixext2
[obj, idx] = parseext(2, bytes, idx + 1);
case 214 % fixext4
[obj, idx] = parseext(4, bytes, idx + 1);
case 215 % fixext8
[obj, idx] = parseext(8, bytes, idx + 1);
case 216 % fixext16
[obj, idx] = parseext(16, bytes, idx + 1);
case 217 % str8
len = double(bytes(idx + 1));
[obj, idx] = parsestring(len, bytes, idx + 2);
case 218 % str16
len = double(bytes2scalar(bytes(idx + 1:idx + 2), 'uint16'));
[obj, idx] = parsestring(len, bytes, idx + 3);
case 219 % str32
len = double(bytes2scalar(bytes(idx + 1:idx + 4), 'uint32'));
[obj, idx] = parsestring(len, bytes, idx + 5);
case 220 % array16
len = double(bytes2scalar(bytes(idx + 1:idx + 2), 'uint16'));
[obj, idx] = parsearray(len, bytes, idx + 3, varargin{:});
case 221 % array32
len = double(bytes2scalar(bytes(idx + 1:idx + 4), 'uint32'));
[obj, idx] = parsearray(len, bytes, idx + 5, varargin{:});
case 222 % map16
len = double(bytes2scalar(bytes(idx + 1:idx + 2), 'uint16'));
[obj, idx] = parsemap(len, bytes, idx + 3, varargin{:});
case 223 % map32
len = double(bytes2scalar(bytes(idx + 1:idx + 4), 'uint32'));
[obj, idx] = parsemap(len, bytes, idx + 5, varargin{:});
otherwise
error('JSONLAB:MSGPACK:InvalidFormat', ...
['Unknown type "' dec2bin(currentbyte) '"']);
end
function value = bytes2scalar(bytes, type)
% reverse byte order to convert from little-endian to big-endian
value = typecast(bytes(end:-1:1), type);
function [str, idx] = parsestring(len, bytes, idx)
if (~isoctavemesh)
str = native2unicode(bytes(idx:idx + len - 1)', 'utf-8');
else
str = char(bytes(idx:idx + len - 1)');
end
idx = idx + len;
function [out, idx] = parsebytes(len, bytes, idx)
out = bytes(idx:idx + len - 1);
idx = idx + len;
function [out, idx] = parseext(len, bytes, idx)
obj.type = bytes(idx);
obj.data = bytes(idx + 1:idx + len);
idx = idx + len + 1;
function [out, idx] = parsearray(len, bytes, idx, varargin)
out = cell(1, len);
for n = 1:len
[out{n}, idx] = parse(bytes, idx, varargin{:});
end
if (len == 1)
out = out{1};
end
if (varargin{1}.simplifycell)
if (iscell(out) && ~isempty(out) && isnumeric(out{1}))
if (all(cellfun(@(e) isequal(size(out{1}), size(e)), out(2:end))))
try
oldobj = out;
if (iscell(out) && length(out) > 1 && ndims(out{1}) >= 2)
catdim = size(out{1});
catdim = ndims(out{1}) - (catdim(end) == 1) + 1;
out = cat(catdim, out{:});
out = permute(out, ndims(out):-1:1);
else
out = cell2mat(out')';
end
if (iscell(oldobj) && isstruct(out) && numel(out) > 1 && varargin{1}.simplifycellarray == 0)
out = oldobj;
end
catch
end
end
end
if (~iscell(out) && size(out, 2) > 1 && ndims(out) == 2)
out = out';
end
end
function [out, idx] = parsemap(len, bytes, idx, varargin)
out = struct();
for n = 1:len
[key, idx] = parse(bytes, idx, varargin{:});
[out.(encodevarname(char(key))), idx] = parse(bytes, idx, varargin{:});
end
|