File: jsonset.m

package info (click to toggle)
octave-iso2mesh 1.9.8%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 11,128 kB
  • sloc: cpp: 11,982; ansic: 10,158; sh: 365; makefile: 59
file content (101 lines) | stat: -rw-r--r-- 3,383 bytes parent folder | download | duplicates (2)
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
function json = jsonset(fname, mmap, varargin)
%
% json=jsonset(fname,mmap,'$.jsonpath1',newval1,'$.jsonpath2','newval2',...)
%
% Fast writing of JSON data records to stream or disk using memory-map
% (mmap) returned by loadjson/loadbj and JSONPath-like keys
%
% authors:Qianqian Fang (q.fang <at> neu.edu)
% initially created on 2022/02/02
%
% input:
%      fname: a JSON/BJData/UBJSON string or stream, or a file name
%      mmap: memory-map returned by loadjson/loadbj of the same data
%            important: mmap must be produced from the same file/string,
%            otherwise calling this function may cause data corruption
%      '$.jsonpath1,2,3,...':  a series of strings in the form of JSONPath
%            as the key to each of the record to be written
%
% output:
%      json: the modified JSON string or, in the case fname is a filename,
%            the cell string made of jsonpaths that are successfully
%            written
%
% examples:
%      % create test data
%       d.arr={[1,2],'a',struct('c',2)}; d.obj=struct('k','test')
%      % convert to json string
%       str=savejson('',d,'compact',1)
%      % parse and return mmap
%       [dat, mmap]=loadjson(str);
%      % display mmap entries
%       savejson('',mmap)
%      % replace value using mmap
%       json=jsonset(str,mmap,'$.arr[2].c','5')
%      % save same json string to file (must set savebinary 1)
%       savejson('',d,'filename','file.json','compact',1,'savebinary',1);
%      % fast write to file
%       json=jsonset('file.json',mmap,'$.arr[2].c','5')
%
% license:
%     BSD 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 (regexp(fname, '^\s*(?:\[.*\])|(?:\{.*\})\s*$', 'once'))
    inputstr = fname;
else
    if (~exist('memmapfile', 'file'))
        fid = fopen(fname, 'r+b');
    end
end

mmap = [mmap{:}];
keylist = mmap(1:2:end);

opt = struct;
for i = 1:2:length(varargin)
    if (isempty(regexp(varargin{i}, '^\$', 'once')))
        opt.(encodevarname(varargin{i})) = varargin{i + 1};
    end
end

json = {};
for i = 1:2:length(varargin)
    if (regexp(varargin{i}, '^\$'))
        [tf, loc] = ismember(varargin{i}, keylist);
        if (tf)
            bmap = mmap{loc * 2};
            if (ischar(varargin{i + 1}))
                val = varargin{i + 1};
            else
                val = savejson('', varargin{i + 1}, 'compact', 1);
            end
            if (length(val) <= bmap(2))
                val = [val repmat(' ', [1, bmap(2) - length(val)])];
                if (exist('inputstr', 'var'))
                    inputstr(bmap(1):bmap(1) + bmap(2) - 1) = val;
                else
                    if (exist('memmapfile', 'file'))
                        rec = {'uint8', [1 bmap(2)],  'x'};
                        fmap = memmapfile(fname, 'writable', true, 'offset', bmap(1) - 1, 'format', rec, 'repeat', 1);
                        fmap.Data.x = uint8(val);
                    else
                        fseek(fid, bmap(1) - 1, 'bof');
                        fwrite(fid, val);
                    end
                    json{end + 1} = {varargin{i}, val};
                end
            end
        end
    end
end

if (exist('fid', 'var') && fid >= 0)
    fclose(fid);
end

if (exist('inputstr', 'var'))
    json = inputstr;
end