function json = jsonget(fname, mmap, varargin)
%
% json=jsonget(fname,mmap,'$.jsonpath1','$.jsonpath2',...)
%
% Fast reading of JSON data records using memory-map (mmap) returned by
% loadjson 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 retrieved; if no paths
%            are given, all items in mmap are retrieved
%
% output:
%      json: a cell array, made of elements {'$.jsonpath_i',json_string_i}
%
% examples:
%      str='[[1,2],"a",{"c":2}]{"k":"test"}';
%      [dat, mmap]=loadjson(str);
%      savejson('',dat,'filename','mydata.json','compact',1);
%      json=jsonget(str,mmap,'$[0]','$[2].c')
%      json=jsonget('mydata.json',mmap,'$[0]','$[2].c')
%
% 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 (ischar(fname) || isa(fname, 'string'))
    if (regexp(fname, '^\s*(?:\[.*\])|(?:\{.*\})\s*$', 'once'))
        inputstr = fname;
    elseif (~exist('memmapfile', 'file'))
        if (exist(fname, 'file'))
            try
                fid = fopen(fname, 'rb');
            catch
            end
        end
    end
end

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

loc = 1:length(keylist);
if (length(varargin) >= 1)
    [tf, loc] = ismember(varargin, keylist);
    if (any(tf))
        keylist = keylist(loc);
    else
        keylist = {};
    end
end

json = {};

if (isstruct(fname) || iscell(fname) || isa(fname, 'table') || isa(fname, 'containers.Map'))
    for i = 1:length(keylist)
        json{end + 1} = jsonpath(fname, keylist{i});
    end
    if (length(json) == 1)
        json = json{1};
    end
    return
end

for i = 1:length(keylist)
    bmap = mmap{loc(i) * 2};
    rec = {'uint8', [1, bmap(2)],  'x'};
    if (exist('inputstr', 'var'))
        json{end + 1} = {keylist{i}, inputstr(bmap(1):bmap(1) + bmap(2) - 1)};
    else
        if (exist('fid', 'var') && fid >= 0)
            fseek(fid, bmap(1), -1);
            json{end + 1} = {keylist{i}, fread(fid, bmap(1), 'uint8=>char')};
        else
            fmap = memmapfile(fname, 'writable', false, 'offset', bmap(1), 'format', rec);
            json{end + 1} = {keylist{i}, char(fmap.Data(1).x)};
        end
    end
end

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