From 804a9932d44e8fce05549ea08fbf6f6832eb0868 Mon Sep 17 00:00:00 2001
From: Qianqian Fang <fangq@nmr.mgh.harvard.edu>
Date: Tue, 18 Dec 2012 17:58:11 +0000
Subject: [PATCH] jsonlab fixes by Niclas Borlin

git-svn-id: http://svn.code.sf.net/p/iso2mesh/code/trunk/jsonlab@394 786e58fb-9377-0410-9ff7-e4ac0ac0635c
---
 AUTHORS.txt                   |  9 +++++
 examples/demo_jsonlab_basic.m | 64 +++++++++++++++++++++++++++++++++++
 loadjson.m                    | 23 ++++++++++---
 savejson.m                    | 16 +++++++--
 4 files changed, 106 insertions(+), 6 deletions(-)

diff --git a/AUTHORS.txt b/AUTHORS.txt
index 1a6a06b..80446a8 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -25,3 +25,12 @@ This toolbox contains patches submitted by the following contributors:
 - Blake Johnson <bjohnso at bbn.com>
   part of revision 341
 
+- Niclas Borlin <Niclas.Borlin at cs.umu.se>
+  various fixes in revision 394, including
+  - loadjson crashes for all-zero sparse matrix.
+  - loadjson crashes for empty sparse matrix.
+  - Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson.
+  - loadjson crashes for sparse real column vector.
+  - loadjson crashes for sparse complex column vector.
+  - Data is corrupted by savejson for sparse real row vector.
+  - savejson crashes for sparse complex row vector. 
diff --git a/examples/demo_jsonlab_basic.m b/examples/demo_jsonlab_basic.m
index 75128d5..d094a64 100644
--- a/examples/demo_jsonlab_basic.m
+++ b/examples/demo_jsonlab_basic.m
@@ -56,6 +56,70 @@ data2json=data2json-data2json*i
 savejson('complex_sparse',data2json)
 json2data=loadjson(ans)
 
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  an all-zero sparse matrix\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=sparse(2,3);
+savejson('all_zero_sparse',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  an empty sparse matrix\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=sparse([]);
+savejson('empty_sparse',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  an empty 0-by-0 real matrix\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=[];
+savejson('empty_0by0_real',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  an empty 0-by-3 real matrix\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=zeros(0,3);
+savejson('empty_0by3_real',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  a sparse real column vector\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=sparse([0,3,0,1,4]');
+savejson('sparse_column_vector',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  a sparse complex column vector\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=data2json-1i*data2json;
+savejson('complex_sparse_column_vector',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  a sparse real row vector\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=sparse([0,3,0,1,4]);
+savejson('sparse_row_vector',data2json)
+json2data=loadjson(ans)
+
+fprintf(1,'\n%%=================================================\n')
+fprintf(1,'%%  a sparse complex row vector\n')
+fprintf(1,'%%=================================================\n\n')
+
+data2json=data2json-1i*data2json;
+savejson('complex_sparse_row_vector',data2json)
+json2data=loadjson(ans)
+
 fprintf(1,'\n%%=================================================\n')
 fprintf(1,'%%  a structure\n')
 fprintf(1,'%%=================================================\n\n')
diff --git a/loadjson.m b/loadjson.m
index 4563b80..2dfcd27 100644
--- a/loadjson.m
+++ b/loadjson.m
@@ -133,13 +133,28 @@ if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayDa
     end
     if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn)))
         if(data(j).x0x5F_ArrayIsSparse_)
-            if(iscpx && size(ndata,2)==4)
-                ndata(:,3)=complex(ndata(:,3),ndata(:,4));
-            end
             if(~isempty(strmatch('x0x5F_ArraySize_',fn)))
                 dim=data(j).x0x5F_ArraySize_;
-                ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end)));
+                if(iscpx && size(ndata,2)==4-any(dim==1))
+                    ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end));
+                end
+                if isempty(ndata)
+                    % All-zeros sparse
+                    ndata=sparse(dim(1),prod(dim(2:end)));
+                elseif dim(1)==1
+                    % Sparse row vector
+                    ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end)));
+                elseif dim(2)==1
+                    % Sparse column vector
+                    ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end)));
+                else
+                    % Generic sparse array.
+                    ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end)));
+                end
             else
+                if(iscpx && size(ndata,2)==4)
+                    ndata(:,3)=complex(ndata(:,3),ndata(:,4));
+                end
                 ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3));
             end
         end
diff --git a/savejson.m b/savejson.m
index f9da0a5..3163272 100644
--- a/savejson.m
+++ b/savejson.m
@@ -255,7 +255,8 @@ end
 padding1=repmat(sprintf('\t'),1,level);
 padding0=repmat(sprintf('\t'),1,level+1);
 
-if(length(size(item))>2 || issparse(item) || ~isreal(item) || jsonopt('ArrayToStruct',0,varargin{:}))
+if(length(size(item))>2 || issparse(item) || ~isreal(item) || ...
+   isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:}))
     if(isempty(name))
     	txt=sprintf('%s{\n%s"_ArrayType_": "%s",\n%s"_ArraySize_": %s,\n',...
               padding1,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') );
@@ -283,13 +284,24 @@ if(issparse(item))
     data=full(item(find(item)));
     if(~isreal(item))
        data=[real(data(:)),imag(data(:))];
+       if(size(item,1)==1)
+           % Kludge to have data's 'transposedness' match item's.
+           % (Necessary for complex row vector handling below.)
+           data=data';
+       end
        txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sprintf(',\n'));
     end
     txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sprintf(',\n'));
-    if(find(size(item)==1))
+    if(size(item,1)==1)
+        % Row vector, store only column indices.
+        txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
+           matdata2json([iy(:),data'],level+2,varargin{:}), sprintf('\n'));
+    elseif(size(item,2)==1)
+        % Column vector, store only row indices.
         txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
            matdata2json([ix,data],level+2,varargin{:}), sprintf('\n'));
     else
+        % General case, store row and column indices.
         txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
            matdata2json([ix,iy,data],level+2,varargin{:}), sprintf('\n'));
     end
-- 
GitLab