Skip to content

Commit

Permalink
Merge branch 'master' of github.com:fangq/jsonlab
Browse files Browse the repository at this point in the history
  • Loading branch information
fangq committed Apr 17, 2023
2 parents 3c32aff + 8c8464f commit 9554a44
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 58 deletions.
57 changes: 57 additions & 0 deletions .github/workflows/run_test.yml
@@ -0,0 +1,57 @@
name: JSONLab CI

on: [push, pull_request]

jobs:
octave_test:
name: Octave tests
strategy:
# provided octave versions: ubuntu-20.04 = 5.2, ubuntu-22.04 = 6.4, macos-11 = 8.1, windows-2019 = 7.3
matrix:
os: [ubuntu-20.04, ubuntu-22.04, macos-11, windows-2019]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash

steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Install dependencies
run: |
[[ "$RUNNER_OS" == "Linux" ]] && sudo apt-get update && sudo apt-get install -y octave
[[ "$RUNNER_OS" == "macOS" ]] && brew install octave
if [[ "$RUNNER_OS" == "Windows" ]]; then
curl --retry 3 -kL http://cdimage.debian.org/mirror/gnu.org/gnu/octave/windows/octave-7.3.0-w64-64.7z --output octave_7.3.0.7z
7z x octave_7.3.0.7z -ooctave -y
echo "$PWD/octave/octave-7.3.0-w64-64/mingw64/bin" >> $GITHUB_PATH
fi
- name: Run octave test
run: |
octave-cli --version
octave-cli --eval "addpath(pwd);cd test;run_jsonlab_test"
octave-cli --eval "addpath(pwd);cd examples; demo_jsonlab_basic; jsonlab_selftest"
matlab_test:
name: MATLAB test
strategy:
matrix:
os: [ubuntu-20.04, macos-11, windows-2019]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Set up MATLAB
uses: matlab-actions/setup-matlab@v1
- name: Run MATLAB test
uses: matlab-actions/run-command@v1
with:
command: addpath(pwd);cd test;run_jsonlab_test
- name: Run MATLAB examples
uses: matlab-actions/run-command@v1
with:
command: addpath(pwd);cd examples; demo_jsonlab_basic; jsonlab_selftest
38 changes: 19 additions & 19 deletions README.rst
Expand Up @@ -138,7 +138,7 @@ To read BJData data files generated by JSONLab v2.0, you should call
data=loadbj('my_old_data_file.bjd','Endian','B')
You are strongly encouraged to convert all pre-v2.9 JSONLab generated BJD or .jamm
You are strongly encouraged to convert all pre-v2.9 JSONLab generated BJD or .pmat
files using the new format.


Expand Down Expand Up @@ -323,7 +323,7 @@ for reading and writing below files types:
- JSON based files: ``.json`, ``.jdt`` (text JData file), ``.jmsh`` (text JMesh file),
``.jnii`` (text JNIfTI file), ``.jnirs`` (text JSNIRF file)
- BJData based files: ``.bjd`, ``.jdb` (binary JData file), ``.bmsh`` (binary JMesh file),
``.bnii`` (binary JNIfTI file), ``.bnirs`` (binary JSNIRF file), ``.jamm`` (MATLAB session file)
``.bnii`` (binary JNIfTI file), ``.bnirs`` (binary JSNIRF file), ``.pmat`` (MATLAB session file)
- UBJSON based files: ``.ubj``
- MessagePack based files: ``.msgpack``
- HDF5 based files: ``.h5``, ``.hdf5``, ``.snirf`` (SNIRF fNIRS data files) - require `EasyH5 toolbox <https://github.com/NeuroJSON/easyh5>`_
Expand Down Expand Up @@ -442,20 +442,20 @@ Using ``jsave/jload`` to share workspace
Starting from JSONLab v2.0, we provide a pair of functions, ``jsave/jload`` to store
and retrieve variables from the current workspace, similar to the ``save/load``
functions in MATLAB and Octave. The files that ``jsave/jload`` reads/writes is by
default a binary JData file with a suffix ``.jamm``. The file size is comparable
default a binary JData file with a suffix ``.pmat``. The file size is comparable
(can be smaller if use ``lzma`` compression) to ``.mat`` files. This feature
is currently experimental.

The main benefits of using .jamm file to share matlab variables include
The main benefits of using .pmat file to share matlab variables include

* a ``.jamm`` file can be 50% smaller than a ``.mat`` file when using
* a ``.pmat`` file can be 50% smaller than a ``.mat`` file when using
``jsave(..., "compression","lzma")``; the only drawback is longer saving time.
* a ``.jamm`` file can be readily read/opened among many programming environments, including
* a ``.pmat`` file can be readily read/opened among many programming environments, including
Python, JavaScript, Go, Java etc, where .mat file support is not generally available.
Parsers of ``.jamm`` files are largely compatible with UBJSON's parsers available at
Parsers of ``.pmat`` files are largely compatible with UBJSON's parsers available at
http://ubjson.org/?page_id=48
* a ``.jamm`` file is quasi-human-readable, one can see the internal data fields
even in a command line, for example using ``strings -n 2 file.jamm | astyle``,
* a ``.pmat`` file is quasi-human-readable, one can see the internal data fields
even in a command line, for example using ``strings -n 2 file.pmat | astyle``,
making the binary data easy to be understood, shared and reused.
* ``jsave/jload`` can also use MessagePack and JSON formats as the underlying
data storage format, addressing needs from a diverse set of applications.
Expand All @@ -467,10 +467,10 @@ jsave.m

.. code-block:: matlab
jsave % save the current workspace to jamdata.jamm
jsave mydata.jamm
jsave('mydata.jamm','vars',{'var1','var2'})
jsave('mydata.jamm','compression','lzma')
jsave % save the current workspace to default.pmat
jsave mydata.pmat
jsave('mydata.pmat','vars',{'var1','var2'})
jsave('mydata.pmat','compression','lzma')
jsave('mydata.json','compression','gzip')
----------
Expand All @@ -479,10 +479,10 @@ jload.m

.. code-block:: matlab
jload % load variables from jamdata.jamm to the current workspace
jload mydata.jamm % load variables from mydata.jamm
vars=jload('mydata.jamm','vars',{'var1','var2'}) % return vars.var1, vars.var2
jload('mydata.jamm','simplifycell',0)
jload % load variables from default.pmat to the current workspace
jload mydata.pmat % load variables from mydata.pmat
vars=jload('mydata.pmat','vars',{'var1','var2'}) % return vars.var1, vars.var2
jload('mydata.pmat','simplifycell',0)
jload('mydata.json')
Expand All @@ -501,7 +501,7 @@ However, we strongly recommend one to use a lightweight ``jdata`` module,
developed by the same author, to perform the extra JData encoding and decoding
and convert JSON data directly to convenient Python/Numpy data structures.
The ``jdata`` module can also directly read/write UBJSON/Binary JData outputs
from JSONLab (``.bjd, .ubj, .bnii, .bnirs, .jamm`` etc). Using binary JData
from JSONLab (``.bjd, .ubj, .bnii, .bnirs, .pmat`` etc). Using binary JData
files are expected to produce much smaller file sizes and faster parsing,
while maintaining excellent portability and generality.

Expand Down Expand Up @@ -547,7 +547,7 @@ Once the necessary modules are installed, one can type ``python`` (or ``python3`
data1=jd.loadt('myfile.json',object_pairs_hook=OrderedDict);
data2=jd.loadb('myfile.ubj',object_pairs_hook=OrderedDict);
data3=jd.loadb('myfile.jamm',object_pairs_hook=OrderedDict);
data3=jd.loadb('myfile.pmat',object_pairs_hook=OrderedDict);
where ``jd.loadt()`` function loads a text-based JSON file, performs
JData decoding and converts the enclosed data into Python ``dict``, ``list``
Expand Down
38 changes: 19 additions & 19 deletions README.txt
Expand Up @@ -135,7 +135,7 @@ To read BJData data files generated by JSONLab v2.0, you should call

data=loadbj('my_old_data_file.bjd','Endian','B')

You are strongly encouraged to convert all pre-v2.9 JSONLab generated BJD or .jamm
You are strongly encouraged to convert all pre-v2.9 JSONLab generated BJD or .pmat
files using the new format.


Expand Down Expand Up @@ -291,7 +291,7 @@ for reading and writing below files types:
* JSON based files: `.json`, `.jdt` (text JData file), `.jmsh` (text JMesh file), \
`.jnii` (text JNIfTI file), `.jnirs` (text JSNIRF file)
* BJData based files: `.bjd`, `.jdb` (binary JData file), `.bmsh` (binary JMesh file), \
`.bnii` (binary JNIfTI file), `.bnirs` (binary JSNIRF file), `.jamm` (MATLAB session file)
`.bnii` (binary JNIfTI file), `.bnirs` (binary JSNIRF file), `.pmat` (MATLAB session file)
* UBJSON based files: `.ubj`
* MessagePack based files: `.msgpack`
* HDF5 based files: `.h5`, `.hdf5`, `.snirf` (SNIRF fNIRS data files) - require [https://github.com/fangq/easyh5 EasyH5 toolbox]
Expand Down Expand Up @@ -383,20 +383,20 @@ IV.Using `jsave/jload` to share workspace
Starting from JSONLab v2.0, we provide a pair of functions, `jsave/jload` to store
and retrieve variables from the current workspace, similar to the `save/load`
functions in MATLAB and Octave. The files that `jsave/jload` reads/writes is by
default a binary JData file with a suffix `.jamm`. The file size is comparable
default a binary JData file with a suffix `.pmat`. The file size is comparable
(can be smaller if use `lzma` compression) to `.mat` files. This feature
is currently experimental.

The main benefits of using .jamm file to share matlab variables include
The main benefits of using .pmat file to share matlab variables include

* a `.jamm` file can be 50% smaller than a `.mat` file when using \
* a `.pmat` file can be 50% smaller than a `.mat` file when using \
`jsave(..., "compression","lzma")`; the only drawback is longer saving time.
* a `.jamm` file can be readily read/opened among many programming environments, including \
* a `.pmat` file can be readily read/opened among many programming environments, including \
Python, JavaScript, Go, Java etc, where `.mat` file support is not generally available. \
Parsers of `.jamm` is largely compatible with UBJSON's parsers available at \
Parsers of `.pmat` is largely compatible with UBJSON's parsers available at \
http://ubjson.org/?page_id=48
* a `.jamm` file is quasi-human-readable, one can see the internal data fields \
even in a command line, for example using `strings -n 2 file.jamm | astyle`, \
* a `.pmat` file is quasi-human-readable, one can see the internal data fields \
even in a command line, for example using `strings -n 2 file.pmat | astyle`, \
making the binary data easy to be understood, shared and reused.
* `jsave/jload` can also use MessagePack and JSON formats as the underlying \
data storage format, addressing needs from diverse applications. \
Expand All @@ -405,18 +405,18 @@ The main benefits of using .jamm file to share matlab variables include

=== jsave.m ===

jsave % save the current workspace to jamdata.jamm
jsave mydata.jamm
jsave('mydata.jamm','vars',{'var1','var2'})
jsave('mydata.jamm','compression','lzma')
jsave % save the current workspace to default.pmat
jsave mydata.pmat
jsave('mydata.pmat','vars',{'var1','var2'})
jsave('mydata.pmat','compression','lzma')
jsave('mydata.json','compression','gzip')

=== jload.m ===

jload % load variables from jamdata.jamm to the current workspace
jload mydata.jamm % load variables from mydata.jamm
vars=jload('mydata.jamm','vars',{'var1','var2'}) % return vars.var1, vars.var2
jload('mydata.jamm','simplifycell',0)
jload % load variables from default.pmat to the current workspace
jload mydata.pmat % load variables from mydata.pmat
vars=jload('mydata.pmat','vars',{'var1','var2'}) % return vars.var1, vars.var2
jload('mydata.pmat','simplifycell',0)
jload('mydata.json')

-------------------------------------------------------------------------------
Expand All @@ -434,7 +434,7 @@ However, we strongly recommend one to use a lightweight `jdata` module,
developed by the same author, to perform the extra JData encoding and decoding
and convert JSON data directly to convenient Python/Numpy data structures.
The `jdata` module can also directly read/write UBJSON/Binary JData outputs
from JSONLab (`.bjd, .ubj, .bnii, .bnirs, .jamm` etc). Using binary JData
from JSONLab (`.bjd, .ubj, .bnii, .bnirs, .pmat` etc). Using binary JData
files are exptected to produce much smaller file sizes and faster parsing,
while maintainining excellent portability and generality.

Expand Down Expand Up @@ -469,7 +469,7 @@ Once the necessary modules are installed, one can type `python` (or `python3`),

data1=jd.loadt('myfile.json',object_pairs_hook=OrderedDict);
data2=jd.loadb('myfile.ubj',object_pairs_hook=OrderedDict);
data3=jd.loadb('myfile.jamm',object_pairs_hook=OrderedDict);
data3=jd.loadb('myfile.pmat',object_pairs_hook=OrderedDict);

where `jd.loadt()` function loads a text-based JSON file, performs
JData decoding and converts the enclosed data into Python `dict`, `list`
Expand Down
3 changes: 2 additions & 1 deletion encodevarname.m
Expand Up @@ -50,7 +50,8 @@
if(exist('unicode2native','builtin'))
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
else
cpos=regexp(str,'[^0-9A-Za-z_]');
cpos=find(~ismember(str, ['0':'9','A':'Z','a':'z','_']));
%cpos=regexp(str,'[^0-9A-Za-z_]');
if(isempty(cpos))
return;
end
Expand Down
2 changes: 1 addition & 1 deletion jdatadecode.m
Expand Up @@ -476,7 +476,7 @@
switch(lower(fext))
case {'.json','.jnii','.jdt','.jdat','.jmsh','.jnirs'}
newdata=loadjson(uripath, opt);
case {'.bjd' ,'.bnii','.jdb','.jbat','.bmsh','.bnirs', '.jamm'}
case {'.bjd' ,'.bnii','.jdb','.jbat','.bmsh','.bnirs', '.pmat'}
newdata=loadbj(uripath, opt);
case {'.ubj'}
newdata=loadubjson(uripath, opt);
Expand Down
14 changes: 7 additions & 7 deletions jload.m
Expand Up @@ -13,9 +13,9 @@
% created on 2020/05/31
%
% input:
% fname: (optional) input file name; if not given, load 'jamdata.jamm'
% fname: (optional) input file name; if not given, load 'default.pmat'
% if fname has a '.json' or '.jdt' suffix, a text-based
% JSON/JData file will be expected; if the suffix is '.jamm' or
% JSON/JData file will be expected; if the suffix is '.pmat' or
% '.jdb', a Binary JData file will be expected.
% opt: (optional) a struct to store parsing options, opt can be replaced by
% a list of ('param',value) pairs - the param string is equivallent
Expand All @@ -41,10 +41,10 @@
% load the variables to the current workspace ('caller')
%
% examples:
% jload % load all variables in jamdata.jamm to the 'caller' workspace
% jload mydat.jamm
% jload('mydat.jamm','vars', {'v1','v2',...}) % load selected variables
% varlist=jload('mydat.jamm','simplifycell',1)
% jload % load all variables in default.pmat to the 'caller' workspace
% jload mydat.pmat
% jload('mydat.pmat','vars', {'v1','v2',...}) % load selected variables
% varlist=jload('mydat.pmat','simplifycell',1)
%
% license:
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
Expand All @@ -53,7 +53,7 @@
%

if(nargin==0)
filename=[pwd filesep 'jamdata.jamm'];
filename=[pwd filesep 'default.pmat'];
end

opt=varargin2struct(varargin{:});
Expand Down
12 changes: 6 additions & 6 deletions jsave.m
Expand Up @@ -11,9 +11,9 @@
% created on 2020/05/31
%
% input:
% fname: (optional) output file name; if not given, save to 'jamdata.jamm'
% fname: (optional) output file name; if not given, save to 'default.pmat'
% if fname has a '.json' or '.jdt' suffix, a text-based
% JSON/JData file will be created (slow); if the suffix is '.jamm' or
% JSON/JData file will be created (slow); if the suffix is '.pmat' or
% '.jdb', a Binary JData (https://github.com/NeuroJSON/bjdata/) file will be created.
% opt: (optional) a struct to store parsing options, opt can be replaced by
% a list of ('param',value) pairs - the param string is equivallent
Expand All @@ -34,9 +34,9 @@
% varlist: a list of variables loaded
%
% examples:
% jsave % save all variables in the 'caller' workspace to jamdata.jamm
% jsave('mydat.jamm','vars', {'v1','v2',...}) % save selected variables
% jsave('mydat.jamm','compression','lzma')
% jsave % save all variables in the 'caller' workspace to jamdata.pmat
% jsave('mydat.pmat','vars', {'v1','v2',...}) % save selected variables
% jsave('mydat.pmat','compression','lzma')
%
% license:
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
Expand All @@ -45,7 +45,7 @@
%

if(nargin==0)
filename=[pwd filesep 'jamdata.jamm'];
filename=[pwd filesep 'default.pmat'];
end

opt=varargin2struct(varargin{:});
Expand Down
2 changes: 1 addition & 1 deletion loadbj.m
Expand Up @@ -101,7 +101,7 @@
fid = fopen(fname,'rb');
string = fread(fid,jsonopt('MaxBuffer',inf,opt),'uint8=>char')';
fclose(fid);
elseif(regexp(fname, '^\s*[\[\{SCHiUIulmLMhdDTFZN]'))
elseif(length(fname) && any(fname(1)=='[{SCHiUIulmLMhdDTFZN'))
string=fname;
else
error_pos('input file does not exist or buffer is invalid');
Expand Down
6 changes: 3 additions & 3 deletions loadjson.m
Expand Up @@ -514,7 +514,7 @@

function [num, pos] = parse_number(inputstr, pos, varargin)
currstr=inputstr(pos:min(pos+30,end));
[num, one, err, delta] = sscanf(currstr, '%f', 1);
[num, tmp, err, delta] = sscanf(currstr, '%f', 1);
if ~isempty(err)
pos=error_pos('Error reading number at position %d',inputstr,pos);
end
Expand All @@ -529,7 +529,7 @@
end
varargout{3}=index_esc;
if(nargout>3)
varargout{4}={};
varargout{4}={};
end
switch(inputstr(pos))
case '"'
Expand Down Expand Up @@ -600,7 +600,7 @@
object(str)=val;
else
object.(encodevarname(str,varargin{:}))=val;
end
end
[cc,pos]=next_char(inputstr,pos);
if cc == '}'
break;
Expand Down
5 changes: 4 additions & 1 deletion test/run_jsonlab_test.m
Expand Up @@ -3,7 +3,7 @@ function run_jsonlab_test(tests)
% run_jsonlab_test
% or
% run_jsonlab_test(tests)
% run_jsonlab_test({'js','jso','bj','bjo'})
% run_jsonlab_test({'js','jso','bj','bjo','jmap','bmap','bugs'})
%
% Unit testing for JSONLab JSON, BJData/UBJSON encoders and decoders
%
Expand All @@ -16,6 +16,9 @@ function run_jsonlab_test(tests)
% 'jso': test savejson/loadjson special options
% 'bj': test savebj/loadbj
% 'bjo': test savebj/loadbj special options
% 'jmap': test jsonmmap features in loadjson
% 'bmap': test jsonmmap features in loadbj
% 'bugs': test specific bug fixes
%
% license:
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
Expand Down

0 comments on commit 9554a44

Please sign in to comment.