1757 lines
59 KiB
Matlab
1757 lines
59 KiB
Matlab
function status = mat2sheets(spreadsheetID, sheetID, sheetpos, d)
|
|
% This function takes values from an array or cell array and places them in
|
|
% a Google spreadsheet. It requires the one-time use of RunOnce (see below)
|
|
% SYNTAX: status = mat2sheets(spreadsheetID, sheetID, pos, d)
|
|
%
|
|
% ARGUMENTS:
|
|
% spreadsheetID: (string), identifier from URL of your Google Sheet
|
|
% sheetID: (string), another identier from URL
|
|
% pos: 1x2 array with indices for [sheetrow, sheetcolumn]
|
|
% to start pasting data
|
|
% d: array or cell array of data to paste into Sheet. If
|
|
% [], pos indicates row or range of rows [start stop]
|
|
% to delete
|
|
%
|
|
% RETURNS: status (0=failed, 1=success)
|
|
%
|
|
% EXAMPLES:
|
|
% For sheet with the following URL:
|
|
% https://docs.google.com/spreadsheets/d/1GPd-vBsX5VUejz5hrxE/edit#gid=552
|
|
%
|
|
% A call may look like:
|
|
% mat2sheets('1GPd-vBsX5VUejz5hrxE', '552', [2 3], [1 2 3 4 5])
|
|
%
|
|
% Would put values 1,2,3,4,5 into cells C2,D2,E2,F2,G2, respectively
|
|
%
|
|
% To delete row(s)
|
|
% mat2sheets('1GPd-vBsX5VUejz5hrxE', '552', 2, []) % delete row 2
|
|
% mat2sheets('1GPd-vBsX5VUejz5hrxE', '552', [2 10], []) % delete rows 2-10 inclusive
|
|
%
|
|
% USING RunOnce().
|
|
% Before using this code, you've got to enable the Drive/Sheets APIs via:
|
|
% https://console.developers.google.com/
|
|
% Here, you will "create credentials" via an OAuth 2.0 client ID that comes
|
|
% with a Client ID and Client Secret. These codes are the two arguments of
|
|
% RunOnce(client_id, client_secret). Run RunOnce with both of these
|
|
% codes passed as strings, and follow the instructions.
|
|
%
|
|
% The following code is inspired by, and makes use of, code
|
|
% originally published in the file exchange by Claudiu Giurumescu.
|
|
% (https://www.mathworks.com/matlabcentral/fileexchange/31221-matlab-to-google-spreadsheets)
|
|
%
|
|
% I wrote this to accomodate for latest changes in Google API, added some
|
|
% comments, and simplified it all so that it can be implemented by the
|
|
% average user (hopefully!)
|
|
%
|
|
% Additionally, I use loadjson by Qianqian Fang to read the input streams
|
|
% from Google for learning meta data about the sheets
|
|
% (https://www.mathworks.com/matlabcentral/fileexchange/33381-jsonlab--a-toolbox-to-encode-decode-json-files)
|
|
%
|
|
% andrew robert bogaard 26 sept 2016
|
|
% updated 25 july 2017 (delete rows)
|
|
% abogaard@uw.edu
|
|
|
|
status = 0;
|
|
aSheets = refreshAccessToken; % refresh and retrieve access token
|
|
if isempty(aSheets), disp('Cannot do anything without Google API access. See readme'); return; end
|
|
|
|
% check if this is a delete row operation
|
|
if isempty(d)
|
|
if numel(sheetpos)==1, sheetpos(2) = sheetpos(1)+1;
|
|
elseif numel(sheetpos)==2, sheetpos(2) = sheetpos(2)+1;
|
|
else, disp('Warning: delete rows requested but sheetpos is not as expected. Quitting.'); return;
|
|
end
|
|
|
|
status = deleteRows(spreadsheetID, sheetID, sheetpos, aSheets);
|
|
return
|
|
end
|
|
|
|
% if not remove row operation, continue below
|
|
|
|
% if error checking, gather sheet meta data
|
|
if ~iscell(d), d = num2cell(d); end % convert to cell array if not already
|
|
[nR, nC, sheetName] = getSheetMetaData(spreadsheetID, sheetID, aSheets); % to ensure we have enough cells
|
|
maxR = sheetpos(1)+size(d,1)-1; % total theoretical rows needed
|
|
maxC = sheetpos(2)+size(d,2)-1; % '' cols needed
|
|
|
|
if ~isempty(nR) % is possible, check that the sheet is large enough
|
|
status = appendRowsColumns(spreadsheetID, sheetID, maxR-nR, maxC-nC, aSheets);
|
|
end
|
|
|
|
%update sheet
|
|
status = pasteSheetData(spreadsheetID, sheetName, sheetpos, d, aSheets);
|
|
|
|
%--------------------------------------------------------------------------
|
|
function status = deleteRows(spreadsheetID, sheetID, rowsdel, aSheets)
|
|
|
|
import java.io.*;
|
|
import java.net.*;
|
|
import java.lang.*;
|
|
com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings
|
|
|
|
% parameters
|
|
url = ['https://sheets.googleapis.com/v4/spreadsheets/' spreadsheetID ':batchUpdate'];
|
|
maxiter = 3;
|
|
status = 1;
|
|
|
|
% build delete request
|
|
request = ['''requests'': [{',...
|
|
'''deleteDimension'': {',...
|
|
'''range'': {',...
|
|
'''sheetId'': ' sheetID ',',...
|
|
'''dimension'': ''ROWS'',',...
|
|
'''startIndex'': ' num2str(rowsdel(1)-1) ',',...
|
|
'''endIndex'': ' num2str(rowsdel(2)-1) ',',...
|
|
'}',...
|
|
'}',...
|
|
'}],'];
|
|
|
|
iter=1;
|
|
success=0;
|
|
while ~success && iter<maxiter
|
|
iter=iter+1;
|
|
con = urlreadwrite(mfilename,url);
|
|
con.setInstanceFollowRedirects(false);
|
|
con.setRequestMethod('POST');
|
|
con.setDoOutput(true);
|
|
con.setDoInput(true);
|
|
con.setRequestProperty('Authorization',['Bearer ' aSheets]);
|
|
con.setRequestProperty('Content-Type','application/json; charset=UTF-8');
|
|
con.setRequestProperty('X-Upload-Content-Length', '0');
|
|
event = ['{',...
|
|
request,...
|
|
'}'];
|
|
|
|
con.setRequestProperty('Content-Length', num2str(length(event)));
|
|
|
|
ps = PrintStream(con.getOutputStream());
|
|
ps.print(event);
|
|
ps.close(); clear ps event;
|
|
|
|
if (con.getResponseCode()~=200)
|
|
con.disconnect();
|
|
continue;
|
|
end
|
|
success=true;
|
|
status = 1;
|
|
end
|
|
|
|
if ~success
|
|
status = 0;
|
|
display(['Failed trying to delete rows. Last response was: ' num2str(con.getResponseCode) '/' con.getResponseMessage().toCharArray()']);
|
|
end
|
|
|
|
%--------------------------------------------------------------------------
|
|
function status = appendRowsColumns(spreadsheetID, sheetID, rowsadd, colsadd, aSheets)
|
|
|
|
import java.io.*;
|
|
import java.net.*;
|
|
import java.lang.*;
|
|
com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings
|
|
|
|
% parameters
|
|
url = ['https://sheets.googleapis.com/v4/spreadsheets/' spreadsheetID ':batchUpdate'];
|
|
maxiter = 3;
|
|
status = 1;
|
|
|
|
% check if rows need to be added
|
|
if rowsadd>0
|
|
request1 = ['''requests'': [{',...
|
|
'''appendDimension'': {',...
|
|
'''sheetId'': ' sheetID ',',...
|
|
'''dimension'': ''ROWS'',',...
|
|
'''length'': ' num2str(rowsadd),...
|
|
'}',...
|
|
'}],'];
|
|
else
|
|
request1=[];
|
|
end
|
|
|
|
if colsadd>0
|
|
request2 = ['''requests'': [{',...
|
|
'''appendDimension'': {',...
|
|
'''sheetId'': ' sheetID ',',...
|
|
'''dimension'': ''COLUMNS'',',...
|
|
'''length'': ' num2str(colsadd),...
|
|
'}',...
|
|
'}],'];
|
|
else
|
|
request2 = [];
|
|
end
|
|
|
|
request = [request1, request2];
|
|
|
|
if isempty(request), return; end
|
|
|
|
iter=1;
|
|
success=0;
|
|
while ~success && iter<maxiter
|
|
iter=iter+1;
|
|
con = urlreadwrite(mfilename,url);
|
|
con.setInstanceFollowRedirects(false);
|
|
con.setRequestMethod('POST');
|
|
con.setDoOutput(true);
|
|
con.setDoInput(true);
|
|
con.setRequestProperty('Authorization',['Bearer ' aSheets]);
|
|
con.setRequestProperty('Content-Type','application/json; charset=UTF-8');
|
|
con.setRequestProperty('X-Upload-Content-Length', '0');
|
|
event = ['{',...
|
|
request,...
|
|
'}'];
|
|
|
|
con.setRequestProperty('Content-Length', num2str(length(event)));
|
|
|
|
ps = PrintStream(con.getOutputStream());
|
|
ps.print(event);
|
|
ps.close(); clear ps event;
|
|
|
|
if (con.getResponseCode()~=200)
|
|
con.disconnect();
|
|
continue;
|
|
end
|
|
success=true;
|
|
status = 1;
|
|
end
|
|
|
|
if ~success
|
|
status = 0;
|
|
display(['Failed trying to add rows/columns. Last response was: ' num2str(con.getResponseCode) '/' con.getResponseMessage().toCharArray()']);
|
|
end
|
|
|
|
%--------------------------------------------------------------------------
|
|
function status = pasteSheetData(spreadsheetID, sheetName, sheetpos, d, aSheets)
|
|
|
|
% include java classes
|
|
import java.io.*;
|
|
import java.net.*;
|
|
import java.lang.*;
|
|
com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings
|
|
|
|
% parameters
|
|
url = ['https://sheets.googleapis.com/v4/spreadsheets/' spreadsheetID '/values:batchUpdate'];
|
|
maxiter = 3;
|
|
status = 1;
|
|
|
|
str_d = savejson('',d); % builds values string in JSON
|
|
str_range = BuildRange(sheetpos, d); % given data d and starting pos, builds range
|
|
|
|
if size(d,1)==1, str_d = ['[' str_d ']']; end
|
|
|
|
success = 0;
|
|
iter = 1;
|
|
while ~success && iter<maxiter
|
|
iter=iter+1;
|
|
con = urlreadwrite(mfilename,url);
|
|
con.setInstanceFollowRedirects(false);
|
|
con.setRequestMethod('POST');
|
|
con.setDoOutput(true);
|
|
con.setDoInput(true);
|
|
con.setRequestProperty('Authorization',['Bearer ' aSheets]);
|
|
con.setRequestProperty('Content-Type','application/json; charset=UTF-8');
|
|
con.setRequestProperty('X-Upload-Content-Length', '0');
|
|
event = ['{',...
|
|
'''valueInputOption'': ''RAW'',',...
|
|
'''data'': [{',...
|
|
'''range'': ''' sheetName '!' str_range ''',',...
|
|
'''values'': ' str_d ',',...
|
|
'}],',...
|
|
'}'];
|
|
|
|
con.setRequestProperty('Content-Length', num2str(length(event)));
|
|
|
|
ps = PrintStream(con.getOutputStream());
|
|
ps.print(event);
|
|
ps.close(); clear ps;
|
|
if (con.getResponseCode()~=200)
|
|
con.disconnect();
|
|
continue;
|
|
end
|
|
success=true;
|
|
end
|
|
|
|
if ~success
|
|
status = 0;
|
|
display(['Failed pasting data. Last response was: ' num2str(con.getResponseCode) '/' con.getResponseMessage().toCharArray()']);
|
|
end
|
|
|
|
function str = BuildRange(sheetpos, ca)
|
|
% for cell array, ca, build the range in A1 notation
|
|
% https://developers.google.com/sheets/reference/rest/v4/spreadsheets.values#ValueRange
|
|
%
|
|
% don't know who to credit the following code to
|
|
%
|
|
% convert number, number format to alpha, number format
|
|
%t = [floor(c/27) + 64 floor((c - 1)/26) - 2 + rem(c - 1, 26) + 65];
|
|
|
|
% The result can have up to three alpha digits. By Peter
|
|
% https://www.mathworks.com/matlabcentral/newsreader/view_thread/85589
|
|
|
|
r = sheetpos(1);
|
|
c = sheetpos(2);
|
|
Digits = zeros(1, 3);
|
|
% Convert number-number format to alpha-number format.
|
|
Digits(1) = max(floor(((c - 1) / 26 - 1) / 26), 0);
|
|
Digits(2) = floor((c - Digits(1) * 26 * 26 - 1) / 26);
|
|
Digits(3) = rem(c - 1, 26) + 1;
|
|
% Delete negative numbers and convert blank cells to spaces.
|
|
Digits(Digits > 0) = Digits(Digits > 0) + 64;
|
|
Digits(Digits == 0) = Digits(Digits == 0) + 32;
|
|
% There may be leading spaces, so trim them away.
|
|
start = strtrim([char(Digits), num2str(r)]);
|
|
|
|
r = sheetpos(1)+size(ca,1)-1;
|
|
c = sheetpos(2)+size(ca,2)-1;
|
|
Digits = zeros(1, 3);
|
|
% Convert number-number format to alpha-number format.
|
|
Digits(1) = max(floor(((c - 1) / 26 - 1) / 26), 0);
|
|
Digits(2) = floor((c - Digits(1) * 26 * 26 - 1) / 26);
|
|
Digits(3) = rem(c - 1, 26) + 1;
|
|
% Delete negative numbers and convert blank cells to spaces.
|
|
Digits(Digits > 0) = Digits(Digits > 0) + 64;
|
|
Digits(Digits == 0) = Digits(Digits == 0) + 32;
|
|
% There may be leading spaces, so trim them away.
|
|
stop = strtrim([char(Digits), num2str(r)]);
|
|
|
|
str = [start ':' stop];
|
|
|
|
%--------------------------------------------------------------------------
|
|
function [nRows, nCols, sheetName] = getSheetMetaData(spreadsheetID, sheetID, aSheets)
|
|
|
|
% include java classes
|
|
import java.io.*;
|
|
import java.net.*;
|
|
import java.lang.*;
|
|
com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings
|
|
|
|
% params
|
|
%url = ['https://spreadsheets.google.com/feeds/worksheets/' sheetID '/private/full/' spreadsheetID];
|
|
url = ['https://sheets.googleapis.com/v4/spreadsheets/' spreadsheetID '?includeGridData=false'];
|
|
MAXITER=10;
|
|
success=false;
|
|
safeguard=0;
|
|
|
|
%init
|
|
nRows = [];
|
|
nCols = [];
|
|
sheetName = [];
|
|
|
|
while (~success && safeguard<MAXITER)
|
|
safeguard=safeguard+1;
|
|
con = urlreadwrite(mfilename,url);
|
|
con.setInstanceFollowRedirects(false);
|
|
con.setRequestMethod('GET');
|
|
con.setDoInput(true);
|
|
con.setRequestProperty('Authorization',['Bearer ' aSheets]);
|
|
|
|
if (con.getResponseCode()~=200)
|
|
con.disconnect();
|
|
continue;
|
|
end
|
|
success=true;
|
|
end
|
|
|
|
if success
|
|
json_return = [];
|
|
isr = java.io.InputStreamReader(con.getInputStream);
|
|
br = java.io.BufferedReader(isr);
|
|
l = br.readLine();
|
|
while ~isempty(l)
|
|
json_return = [json_return, l];
|
|
l = br.readLine();
|
|
end
|
|
j = char(json_return)';
|
|
j = j(:)';
|
|
|
|
opt.SimplifyCell = 1;
|
|
jdat = loadjson(j, opt);
|
|
sIds = nan(size(jdat.sheets));
|
|
if iscell(jdat.sheets(1)) % test for some weird bug
|
|
for i = 1:numel(jdat.sheets)
|
|
jd = jdat.sheets(i);
|
|
jdc = cell2mat(jd);
|
|
sIds(i) = jdc.properties.sheetId;
|
|
end
|
|
|
|
wheresheet = find(sIds==str2double(sheetID));
|
|
|
|
if ~isempty(wheresheet) && length(wheresheet)==1
|
|
jd = jdat.sheets(wheresheet);
|
|
jdc = cell2mat(jd);
|
|
nRows = jdc.properties.gridProperties.rowCount;
|
|
nCols = jdc.properties.gridProperties.columnCount;
|
|
sheetName = jdc.properties.title;
|
|
else
|
|
disp('SheetID doesnt match sheets');
|
|
end
|
|
else
|
|
for i = 1:numel(jdat.sheets)
|
|
sIds(i) = jdat.sheets(i).properties.sheetId;
|
|
end
|
|
|
|
wheresheet = find(sIds==str2double(sheetID));
|
|
|
|
if ~isempty(wheresheet) && length(wheresheet)==1
|
|
nRows = jdat.sheets(wheresheet).properties.gridProperties.rowCount;
|
|
nCols = jdat.sheets(wheresheet).properties.gridProperties.columnCount;
|
|
sheetName = jdat.sheets(wheresheet).properties.title;
|
|
else
|
|
disp('SheetID doesnt match sheets');
|
|
end
|
|
end
|
|
|
|
con.disconnect();
|
|
|
|
else
|
|
display(['Failed gathering metadata. Last response was: ' num2str(con.getResponseCode) '/' con.getResponseMessage().toCharArray()']);
|
|
end
|
|
|
|
%--------------------------------------------------------------------------
|
|
function aSheets = refreshAccessToken
|
|
|
|
aSheets = [];
|
|
|
|
if ~exist('google_tokens.mat', 'file')
|
|
disp('Run RunOnce() first and ensure that google_tokens.mat is in MATLAB''s path');
|
|
return
|
|
end
|
|
|
|
load google_tokens.mat
|
|
|
|
newAccessTokenString=urlread('https://accounts.google.com/o/oauth2/token','POST', ...
|
|
{'client_id', client_id, 'client_secret', client_secret, 'refresh_token', rSheets, 'grant_type', 'refresh_token'});
|
|
|
|
aSheets=[];
|
|
|
|
reply_commas=[1 strfind(newAccessTokenString,',') length(newAccessTokenString)];
|
|
|
|
for i=1:length(reply_commas)-1
|
|
if ~isempty(strfind(newAccessTokenString(reply_commas(i):reply_commas(i+1)),'access_token'))
|
|
tmp=newAccessTokenString(reply_commas(i):reply_commas(i+1));
|
|
index_tmp_colon=strfind(tmp,':');
|
|
tmp=tmp(index_tmp_colon+1:end); clear index_tmp_colon;
|
|
index_quotes=find(tmp=='"');
|
|
aSheets=tmp(index_quotes(1)+1:index_quotes(2)-1); clear index_quotes tmp;
|
|
end
|
|
end
|
|
|
|
save('google_tokens.mat', 'aSheets', '-append');
|
|
|
|
|
|
%--------------------------------------------------------------------------
|
|
function data = loadjson(fname,varargin)
|
|
%
|
|
% data=loadjson(fname,opt)
|
|
% or
|
|
% data=loadjson(fname,'param1',value1,'param2',value2,...)
|
|
%
|
|
% parse a JSON (JavaScript Object Notation) file or string
|
|
%
|
|
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
% created on 2011/09/09, including previous works from
|
|
%
|
|
% Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
|
|
% created on 2009/11/02
|
|
% François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
|
|
% created on 2009/03/22
|
|
% Joel Feenstra:
|
|
% http://www.mathworks.com/matlabcentral/fileexchange/20565
|
|
% created on 2008/07/03
|
|
%
|
|
% $Id$
|
|
%
|
|
% input:
|
|
% fname: input file name, if fname contains "{}" or "[]", fname
|
|
% will be interpreted as a JSON string
|
|
% opt: a struct to store parsing options, opt can be replaced by
|
|
% a list of ('param',value) pairs - the param string is equivallent
|
|
% to a field in opt. opt can have the following
|
|
% fields (first in [.|.] is the default)
|
|
%
|
|
% opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat
|
|
% for each element of the JSON data, and group
|
|
% arrays based on the cell2mat rules.
|
|
% opt.FastArrayParser [1|0 or integer]: if set to 1, use a
|
|
% speed-optimized array parser when loading an
|
|
% array object. The fast array parser may
|
|
% collapse block arrays into a single large
|
|
% array similar to rules defined in cell2mat; 0 to
|
|
% use a legacy parser; if set to a larger-than-1
|
|
% value, this option will specify the minimum
|
|
% dimension to enable the fast array parser. For
|
|
% example, if the input is a 3D array, setting
|
|
% FastArrayParser to 1 will return a 3D array;
|
|
% setting to 2 will return a cell array of 2D
|
|
% arrays; setting to 3 will return to a 2D cell
|
|
% array of 1D vectors; setting to 4 will return a
|
|
% 3D cell array.
|
|
% opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar.
|
|
%
|
|
% output:
|
|
% dat: a cell array, where {...} blocks are converted into cell arrays,
|
|
% and [...] are converted to arrays
|
|
%
|
|
% examples:
|
|
% dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}')
|
|
% dat=loadjson(['examples' filesep 'example1.json'])
|
|
% dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1)
|
|
%
|
|
% license:
|
|
% BSD License, see LICENSE_BSD.txt files for details
|
|
%
|
|
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
|
%
|
|
|
|
global pos inStr len esc index_esc len_esc isoct arraytoken
|
|
|
|
if(regexp(fname,'^\s*(?:\[.+\])|(?:\{.+\})\s*$','once'))
|
|
string=fname;
|
|
elseif(exist(fname,'file'))
|
|
try
|
|
string = fileread(fname);
|
|
catch
|
|
try
|
|
string = urlread(['file://',fname]);
|
|
catch
|
|
string = urlread(['file://',fullfile(pwd,fname)]);
|
|
end
|
|
end
|
|
else
|
|
error('input file does not exist');
|
|
end
|
|
|
|
pos = 1; len = length(string); inStr = string;
|
|
isoct=exist('OCTAVE_VERSION','builtin');
|
|
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
|
|
jstr=regexprep(inStr,'\\\\',' ');
|
|
escquote=regexp(jstr,'\\"');
|
|
arraytoken=sort([arraytoken escquote]);
|
|
|
|
% String delimiters and escape chars identified to improve speed:
|
|
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]');
|
|
index_esc = 1; len_esc = length(esc);
|
|
|
|
opt=varargin2struct(varargin{:});
|
|
|
|
if(jsonopt('ShowProgress',0,opt)==1)
|
|
opt.progressbar_=waitbar(0,'loading ...');
|
|
end
|
|
jsoncount=1;
|
|
while pos <= len
|
|
switch(next_char)
|
|
case '{'
|
|
data{jsoncount} = parse_object(opt);
|
|
case '['
|
|
data{jsoncount} = parse_array(opt);
|
|
otherwise
|
|
error_pos('Outer level structure must be an object or an array');
|
|
end
|
|
jsoncount=jsoncount+1;
|
|
end % while
|
|
|
|
jsoncount=length(data);
|
|
if(jsoncount==1 && iscell(data))
|
|
data=data{1};
|
|
end
|
|
|
|
if(isfield(opt,'progressbar_'))
|
|
close(opt.progressbar_);
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function object = parse_object(varargin)
|
|
parse_char('{');
|
|
object = [];
|
|
if next_char ~= '}'
|
|
while 1
|
|
str = parseStr(varargin{:});
|
|
if isempty(str)
|
|
error_pos('Name of value at position %d cannot be empty');
|
|
end
|
|
parse_char(':');
|
|
val = parse_value(varargin{:});
|
|
object.(valid_field(str))=val;
|
|
if next_char == '}'
|
|
break;
|
|
end
|
|
parse_char(',');
|
|
end
|
|
end
|
|
parse_char('}');
|
|
if(isstruct(object))
|
|
object=struct2jdata(object);
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function object = parse_array(varargin) % JSON array is written in row-major order
|
|
global pos inStr isoct
|
|
parse_char('[');
|
|
object = cell(0, 1);
|
|
dim2=[];
|
|
arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:});
|
|
pbar=-1;
|
|
if(isfield(varargin{1},'progressbar_'))
|
|
pbar=varargin{1}.progressbar_;
|
|
end
|
|
|
|
if next_char ~= ']'
|
|
if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:}))
|
|
[endpos, e1l, e1r]=matching_bracket(inStr,pos);
|
|
arraystr=['[' inStr(pos:endpos)];
|
|
arraystr=regexprep(arraystr,'"_NaN_"','NaN');
|
|
arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf');
|
|
arraystr(arraystr==sprintf('\n'))=[];
|
|
arraystr(arraystr==sprintf('\r'))=[];
|
|
%arraystr=regexprep(arraystr,'\s*,',','); % this is slow,sometimes needed
|
|
if(~isempty(e1l) && ~isempty(e1r)) % the array is in 2D or higher D
|
|
astr=inStr((e1l+1):(e1r-1));
|
|
astr=regexprep(astr,'"_NaN_"','NaN');
|
|
astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf');
|
|
astr(astr==sprintf('\n'))=[];
|
|
astr(astr==sprintf('\r'))=[];
|
|
astr(astr==' ')='';
|
|
if(isempty(find(astr=='[', 1))) % array is 2D
|
|
dim2=length(sscanf(astr,'%f,',[1 inf]));
|
|
end
|
|
else % array is 1D
|
|
astr=arraystr(2:end-1);
|
|
astr(astr==' ')='';
|
|
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]);
|
|
if(nextidx>=length(astr)-1)
|
|
object=obj;
|
|
pos=endpos;
|
|
parse_char(']');
|
|
return;
|
|
end
|
|
end
|
|
if(~isempty(dim2))
|
|
astr=arraystr;
|
|
astr(astr=='[')='';
|
|
astr(astr==']')='';
|
|
astr(astr==' ')='';
|
|
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf);
|
|
if(nextidx>=length(astr)-1)
|
|
object=reshape(obj,dim2,numel(obj)/dim2)';
|
|
pos=endpos;
|
|
parse_char(']');
|
|
if(pbar>0)
|
|
waitbar(pos/length(inStr),pbar,'loading ...');
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
arraystr=regexprep(arraystr,'\]\s*,','];');
|
|
else
|
|
arraystr='[';
|
|
end
|
|
try
|
|
if(isoct && regexp(arraystr,'"','once'))
|
|
error('Octave eval can produce empty cells for JSON-like input');
|
|
end
|
|
object=eval(arraystr);
|
|
pos=endpos;
|
|
catch
|
|
while 1
|
|
newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1);
|
|
val = parse_value(newopt);
|
|
object{end+1} = val;
|
|
if next_char == ']'
|
|
break;
|
|
end
|
|
parse_char(',');
|
|
end
|
|
end
|
|
end
|
|
if(jsonopt('SimplifyCell',0,varargin{:})==1)
|
|
try
|
|
oldobj=object;
|
|
object=cell2mat(object')';
|
|
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
|
|
object=oldobj;
|
|
elseif(size(object,1)>1 && ismatrix(object))
|
|
object=object';
|
|
end
|
|
catch
|
|
end
|
|
end
|
|
parse_char(']');
|
|
|
|
if(pbar>0)
|
|
waitbar(pos/length(inStr),pbar,'loading ...');
|
|
end
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function parse_char(c)
|
|
global pos inStr len
|
|
pos=skip_whitespace(pos,inStr,len);
|
|
if pos > len || inStr(pos) ~= c
|
|
error_pos(sprintf('Expected %c at position %%d', c));
|
|
else
|
|
pos = pos + 1;
|
|
pos=skip_whitespace(pos,inStr,len);
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function c = next_char
|
|
global pos inStr len
|
|
pos=skip_whitespace(pos,inStr,len);
|
|
if pos > len
|
|
c = [];
|
|
else
|
|
c = inStr(pos);
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function newpos=skip_whitespace(pos,inStr,len)
|
|
newpos=pos;
|
|
while newpos <= len && isspace(inStr(newpos))
|
|
newpos = newpos + 1;
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function str = parseStr(varargin)
|
|
global pos inStr len esc index_esc len_esc
|
|
% len, ns = length(inStr), keyboard
|
|
if inStr(pos) ~= '"'
|
|
error_pos('String starting with " expected at position %d');
|
|
else
|
|
pos = pos + 1;
|
|
end
|
|
str = '';
|
|
while pos <= len
|
|
while index_esc <= len_esc && esc(index_esc) < pos
|
|
index_esc = index_esc + 1;
|
|
end
|
|
if index_esc > len_esc
|
|
str = [str inStr(pos:len)];
|
|
pos = len + 1;
|
|
break;
|
|
else
|
|
str = [str inStr(pos:esc(index_esc)-1)];
|
|
pos = esc(index_esc);
|
|
end
|
|
nstr = length(str);
|
|
switch inStr(pos)
|
|
case '"'
|
|
pos = pos + 1;
|
|
if(~isempty(str))
|
|
if(strcmp(str,'_Inf_'))
|
|
str=Inf;
|
|
elseif(strcmp(str,'-_Inf_'))
|
|
str=-Inf;
|
|
elseif(strcmp(str,'_NaN_'))
|
|
str=NaN;
|
|
end
|
|
end
|
|
return;
|
|
case '\'
|
|
if pos+1 > len
|
|
error_pos('End of file reached right after escape character');
|
|
end
|
|
pos = pos + 1;
|
|
switch inStr(pos)
|
|
case {'"' '\' '/'}
|
|
str(nstr+1) = inStr(pos);
|
|
pos = pos + 1;
|
|
case {'b' 'f' 'n' 'r' 't'}
|
|
str(nstr+1) = sprintf(['\' inStr(pos)]);
|
|
pos = pos + 1;
|
|
case 'u'
|
|
if pos+4 > len
|
|
error_pos('End of file reached in escaped unicode character');
|
|
end
|
|
str(nstr+(1:6)) = inStr(pos-1:pos+4);
|
|
pos = pos + 5;
|
|
end
|
|
otherwise % should never happen
|
|
str(nstr+1) = inStr(pos);
|
|
keyboard;
|
|
pos = pos + 1;
|
|
end
|
|
end
|
|
error_pos('End of file while expecting end of inStr');
|
|
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function num = parse_number(varargin)
|
|
global pos inStr isoct
|
|
currstr=inStr(pos:min(pos+30,end));
|
|
if(isoct~=0)
|
|
numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end');
|
|
[num] = sscanf(currstr, '%f', 1);
|
|
delta=numstr+1;
|
|
else
|
|
[num, one, err, delta] = sscanf(currstr, '%f', 1);
|
|
if ~isempty(err)
|
|
error_pos('Error reading number at position %d');
|
|
end
|
|
end
|
|
pos = pos + delta-1;
|
|
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function val = parse_value(varargin)
|
|
global pos inStr len
|
|
|
|
if(isfield(varargin{1},'progressbar_'))
|
|
waitbar(pos/len,varargin{1}.progressbar_,'loading ...');
|
|
end
|
|
|
|
switch(inStr(pos))
|
|
case '"'
|
|
val = parseStr(varargin{:});
|
|
return;
|
|
case '['
|
|
val = parse_array(varargin{:});
|
|
return;
|
|
case '{'
|
|
val = parse_object(varargin{:});
|
|
return;
|
|
case {'-','0','1','2','3','4','5','6','7','8','9'}
|
|
val = parse_number(varargin{:});
|
|
return;
|
|
case 't'
|
|
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true')
|
|
val = true;
|
|
pos = pos + 4;
|
|
return;
|
|
end
|
|
case 'f'
|
|
if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false')
|
|
val = false;
|
|
pos = pos + 5;
|
|
return;
|
|
end
|
|
case 'n'
|
|
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null')
|
|
val = [];
|
|
pos = pos + 4;
|
|
return;
|
|
end
|
|
end
|
|
error_pos('Value expected at position %d');
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function error_pos(msg)
|
|
global pos inStr len
|
|
poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
|
|
if poShow(3) == poShow(2)
|
|
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after
|
|
end
|
|
msg = [sprintf(msg, pos) ': ' ...
|
|
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
|
|
error( ['JSONparser:invalidFormat: ' msg] );
|
|
|
|
%%-------------------------------------------------------------------------
|
|
|
|
function str = valid_field(str)
|
|
global isoct
|
|
% From MATLAB doc: field names must begin with a letter, which may be
|
|
% followed by any combination of letters, digits, and underscores.
|
|
% Invalid characters will be converted to underscores, and the prefix
|
|
% "x0x[Hex code]_" will be added if the first character is not a letter.
|
|
pos=regexp(str,'^[^A-Za-z]','once');
|
|
if(~isempty(pos))
|
|
if(~isoct)
|
|
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
|
|
else
|
|
str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
|
|
end
|
|
end
|
|
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' )))
|
|
return;
|
|
end
|
|
if(~isoct)
|
|
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
|
|
else
|
|
pos=regexp(str,'[^0-9A-Za-z_]');
|
|
if(isempty(pos))
|
|
return;
|
|
end
|
|
str0=str;
|
|
pos0=[0 pos(:)' length(str)];
|
|
str='';
|
|
for i=1:length(pos)
|
|
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
|
|
end
|
|
if(pos(end)~=length(str))
|
|
str=[str str0(pos0(end-1)+1:pos0(end))];
|
|
end
|
|
end
|
|
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_';
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function endpos = matching_quote(str,pos)
|
|
len=length(str);
|
|
while(pos<len)
|
|
if(str(pos)=='"')
|
|
if(~(pos>1 && str(pos-1)=='\'))
|
|
endpos=pos;
|
|
return;
|
|
end
|
|
end
|
|
pos=pos+1;
|
|
end
|
|
error('unmatched quotation mark');
|
|
%%-------------------------------------------------------------------------
|
|
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos)
|
|
global arraytoken
|
|
level=1;
|
|
maxlevel=level;
|
|
endpos=0;
|
|
bpos=arraytoken(arraytoken>=pos);
|
|
tokens=str(bpos);
|
|
len=length(tokens);
|
|
pos=1;
|
|
e1l=[];
|
|
e1r=[];
|
|
while(pos<=len)
|
|
c=tokens(pos);
|
|
if(c==']')
|
|
level=level-1;
|
|
if(isempty(e1r))
|
|
e1r=bpos(pos);
|
|
end
|
|
if(level==0)
|
|
endpos=bpos(pos);
|
|
return
|
|
end
|
|
end
|
|
if(c=='[')
|
|
if(isempty(e1l))
|
|
e1l=bpos(pos);
|
|
end
|
|
level=level+1;
|
|
maxlevel=max(maxlevel,level);
|
|
end
|
|
if(c=='"')
|
|
pos=matching_quote(tokens,pos+1);
|
|
end
|
|
pos=pos+1;
|
|
end
|
|
if(endpos==0)
|
|
error('unmatched "]"');
|
|
end
|
|
%--------------------------------------------------------------------------
|
|
function opt=varargin2struct(varargin)
|
|
%
|
|
% opt=varargin2struct('param1',value1,'param2',value2,...)
|
|
% or
|
|
% opt=varargin2struct(...,optstruct,...)
|
|
%
|
|
% convert a series of input parameters into a structure
|
|
%
|
|
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
% date: 2012/12/22
|
|
%
|
|
% input:
|
|
% 'param', value: the input parameters should be pairs of a string and a value
|
|
% optstruct: if a parameter is a struct, the fields will be merged to the output struct
|
|
%
|
|
% output:
|
|
% opt: a struct where opt.param1=value1, opt.param2=value2 ...
|
|
%
|
|
% license:
|
|
% BSD License, see LICENSE_BSD.txt files for details
|
|
%
|
|
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
|
%
|
|
|
|
len=length(varargin);
|
|
opt=struct;
|
|
if(len==0) return; end
|
|
i=1;
|
|
while(i<=len)
|
|
if(isstruct(varargin{i}))
|
|
opt=mergestruct(opt,varargin{i});
|
|
elseif(ischar(varargin{i}) && i<len)
|
|
opt=setfield(opt,lower(varargin{i}),varargin{i+1});
|
|
i=i+1;
|
|
else
|
|
error('input must be in the form of ...,''name'',value,... pairs or structs');
|
|
end
|
|
i=i+1;
|
|
end
|
|
%--------------------------------------------------------------------------
|
|
function val=jsonopt(key,default,varargin)
|
|
%
|
|
% val=jsonopt(key,default,optstruct)
|
|
%
|
|
% setting options based on a struct. The struct can be produced
|
|
% by varargin2struct from a list of 'param','value' pairs
|
|
%
|
|
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
%
|
|
% $Id: loadjson.m 371 2012-06-20 12:43:06Z fangq $
|
|
%
|
|
% input:
|
|
% key: a string with which one look up a value from a struct
|
|
% default: if the key does not exist, return default
|
|
% optstruct: a struct where each sub-field is a key
|
|
%
|
|
% output:
|
|
% val: if key exists, val=optstruct.key; otherwise val=default
|
|
%
|
|
% license:
|
|
% BSD License, see LICENSE_BSD.txt files for details
|
|
%
|
|
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
|
%
|
|
|
|
val=default;
|
|
if(nargin<=2) return; end
|
|
opt=varargin{1};
|
|
if(isstruct(opt))
|
|
if(isfield(opt,key))
|
|
val=getfield(opt,key);
|
|
elseif(isfield(opt,lower(key)))
|
|
val=getfield(opt,lower(key));
|
|
end
|
|
end
|
|
|
|
%--------------------------------------------------------------------------
|
|
function newdata=struct2jdata(data,varargin)
|
|
%
|
|
% newdata=struct2jdata(data,opt,...)
|
|
%
|
|
% convert a JData object (in the form of a struct array) into an array
|
|
%
|
|
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
%
|
|
% input:
|
|
% data: a struct array. If data contains JData keywords in the first
|
|
% level children, these fields are parsed and regrouped into a
|
|
% data object (arrays, trees, graphs etc) based on JData
|
|
% specification. The JData keywords are
|
|
% "_ArrayType_", "_ArraySize_", "_ArrayData_"
|
|
% "_ArrayIsSparse_", "_ArrayIsComplex_"
|
|
% opt: (optional) a list of 'Param',value pairs for additional options
|
|
% The supported options include
|
|
% 'Recursive', if set to 1, will apply the conversion to
|
|
% every child; 0 to disable
|
|
%
|
|
% output:
|
|
% newdata: the covnerted data if the input data does contain a JData
|
|
% structure; otherwise, the same as the input.
|
|
%
|
|
% examples:
|
|
% obj=struct('_ArrayType_','double','_ArraySize_',[2 3],
|
|
% '_ArrayIsSparse_',1 ,'_ArrayData_',null);
|
|
% ubjdata=struct2jdata(obj);
|
|
%
|
|
% license:
|
|
% BSD License, see LICENSE_BSD.txt files for details
|
|
%
|
|
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
|
%
|
|
|
|
fn=fieldnames(data);
|
|
newdata=data;
|
|
len=length(data);
|
|
if(jsonopt('Recursive',0,varargin{:})==1)
|
|
for i=1:length(fn) % depth-first
|
|
for j=1:len
|
|
if(isstruct(getfield(data(j),fn{i})))
|
|
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i})));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn)))
|
|
newdata=cell(len,1);
|
|
for j=1:len
|
|
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_);
|
|
iscpx=0;
|
|
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn)))
|
|
if(data(j).x0x5F_ArrayIsComplex_)
|
|
iscpx=1;
|
|
end
|
|
end
|
|
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn)))
|
|
if(data(j).x0x5F_ArrayIsSparse_)
|
|
if(~isempty(strmatch('x0x5F_ArraySize_',fn)))
|
|
dim=double(data(j).x0x5F_ArraySize_);
|
|
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
|
|
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn)))
|
|
if(iscpx && size(ndata,2)==2)
|
|
ndata=complex(ndata(:,1),ndata(:,2));
|
|
end
|
|
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_);
|
|
end
|
|
newdata{j}=ndata;
|
|
end
|
|
if(len==1)
|
|
newdata=newdata{1};
|
|
end
|
|
end
|
|
|
|
%--------------------------------------------------------------------------
|
|
function s=mergestruct(s1,s2)
|
|
%
|
|
% s=mergestruct(s1,s2)
|
|
%
|
|
% merge two struct objects into one
|
|
%
|
|
% authors:Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
% date: 2012/12/22
|
|
%
|
|
% input:
|
|
% s1,s2: a struct object, s1 and s2 can not be arrays
|
|
%
|
|
% output:
|
|
% s: the merged struct object. fields in s1 and s2 will be combined in s.
|
|
%
|
|
% license:
|
|
% BSD License, see LICENSE_BSD.txt files for details
|
|
%
|
|
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
|
%
|
|
|
|
if(~isstruct(s1) || ~isstruct(s2))
|
|
error('input parameters contain non-struct');
|
|
end
|
|
if(length(s1)>1 || length(s2)>1)
|
|
error('can not merge struct arrays');
|
|
end
|
|
fn=fieldnames(s2);
|
|
s=s1;
|
|
for i=1:length(fn)
|
|
s=setfield(s,fn{i},getfield(s2,fn{i}));
|
|
end
|
|
|
|
function json=savejson(rootname,obj,varargin)
|
|
%
|
|
% json=savejson(rootname,obj,filename)
|
|
% or
|
|
% json=savejson(rootname,obj,opt)
|
|
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...)
|
|
%
|
|
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
|
|
% Object Notation) string
|
|
%
|
|
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
|
|
% created on 2011/09/09
|
|
%
|
|
% $Id$
|
|
%
|
|
% input:
|
|
% rootname: the name of the root-object, when set to '', the root name
|
|
% is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
|
% the MATLAB variable name will be used as the root name.
|
|
% obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
|
% class instance).
|
|
% filename: a string for the file name to save the output JSON data.
|
|
% opt: a struct for additional options, ignore to use default values.
|
|
% opt can have the following fields (first in [.|.] is the default)
|
|
%
|
|
% opt.FileName [''|string]: a file name to save the output JSON data
|
|
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element
|
|
% of a 1D/2D array;
|
|
% opt.ArrayIndent [1|0]: if 1, output explicit data array with
|
|
% precedent indentation; if 0, no indentation
|
|
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
|
|
% array in JSON array format; if sets to 1, an
|
|
% array will be shown as a struct with fields
|
|
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
|
% sparse arrays, the non-zero elements will be
|
|
% saved to _ArrayData_ field in triplet-format i.e.
|
|
% (ix,iy,val) and "_ArrayIsSparse_" will be added
|
|
% with a value of 1; for a complex array, the
|
|
% _ArrayData_ array will include two columns
|
|
% (4 for sparse) to record the real and imaginary
|
|
% parts, and also "_ArrayIsComplex_":1 is added.
|
|
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem
|
|
% will use true/false rather than 1/0.
|
|
% opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
|
% numerical element will be shown without a square
|
|
% bracket, unless it is the root object; if 0, square
|
|
% brackets are forced for any numerical arrays.
|
|
% opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
|
% even it has only one element; if 0, brackets
|
|
% are ignored when a cell has only 1 element.
|
|
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson
|
|
% will use the name of the passed obj variable as the
|
|
% root object name; if obj is an expression and
|
|
% does not have a name, 'root' will be used; if this
|
|
% is set to 0 and rootname is empty, the root level
|
|
% will be merged down to the lower level.
|
|
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern
|
|
% to represent +/-Inf. The matched pattern is '([-+]*)Inf'
|
|
% and $1 represents the sign. For those who want to use
|
|
% 1e999 to represent Inf, they can set opt.Inf to '$11e999'
|
|
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern
|
|
% to represent NaN
|
|
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
|
% for example, if opt.JSONP='foo', the JSON data is
|
|
% wrapped inside a function call as 'foo(...);'
|
|
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
|
% back to the string form
|
|
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode.
|
|
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs)
|
|
%
|
|
% opt can be replaced by a list of ('param',value) pairs. The param
|
|
% string is equivallent to a field in opt and is case sensitive.
|
|
% output:
|
|
% json: a string in the JSON format (see http://json.org)
|
|
%
|
|
% examples:
|
|
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
|
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
|
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
|
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
|
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
|
% 'SpecialData',[nan, inf, -inf]);
|
|
% savejson('jmesh',jsonmesh)
|
|
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g')
|
|
%
|
|
% 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(nargin==1)
|
|
varname=inputname(1);
|
|
obj=rootname;
|
|
if(isempty(varname))
|
|
varname='root';
|
|
end
|
|
rootname=varname;
|
|
else
|
|
varname=inputname(2);
|
|
end
|
|
if(length(varargin)==1 && ischar(varargin{1}))
|
|
opt=struct('filename',varargin{1});
|
|
else
|
|
opt=varargin2struct(varargin{:});
|
|
end
|
|
opt.IsOctave=exist('OCTAVE_VERSION','builtin');
|
|
if(isfield(opt,'norowbracket'))
|
|
warning('Option ''NoRowBracket'' is depreciated, please use ''SingletArray'' and set its value to not(NoRowBracket)');
|
|
if(~isfield(opt,'singletarray'))
|
|
opt.singletarray=not(opt.norowbracket);
|
|
end
|
|
end
|
|
rootisarray=0;
|
|
rootlevel=1;
|
|
forceroot=jsonopt('ForceRootName',0,opt);
|
|
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || ...
|
|
iscell(obj) || isobject(obj)) && isempty(rootname) && forceroot==0)
|
|
rootisarray=1;
|
|
rootlevel=0;
|
|
else
|
|
if(isempty(rootname))
|
|
rootname=varname;
|
|
end
|
|
end
|
|
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot)
|
|
rootname='root';
|
|
end
|
|
|
|
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
|
if(jsonopt('Compact',0,opt)==1)
|
|
whitespaces=struct('tab','','newline','','sep',',');
|
|
end
|
|
if(~isfield(opt,'whitespaces_'))
|
|
opt.whitespaces_=whitespaces;
|
|
end
|
|
|
|
nl=whitespaces.newline;
|
|
|
|
json=obj2json(rootname,obj,rootlevel,opt);
|
|
if(rootisarray)
|
|
json=sprintf('%s%s',json,nl);
|
|
else
|
|
json=sprintf('{%s%s%s}\n',nl,json,nl);
|
|
end
|
|
|
|
jsonp=jsonopt('JSONP','',opt);
|
|
if(~isempty(jsonp))
|
|
json=sprintf('%s(%s);%s',jsonp,json,nl);
|
|
end
|
|
|
|
% save to a file if FileName is set, suggested by Patrick Rapin
|
|
filename=jsonopt('FileName','',opt);
|
|
if(~isempty(filename))
|
|
if(jsonopt('SaveBinary',0,opt)==1)
|
|
fid = fopen(filename, 'wb');
|
|
fwrite(fid,json);
|
|
else
|
|
fid = fopen(filename, 'wt');
|
|
fwrite(fid,json,'char');
|
|
end
|
|
fclose(fid);
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=obj2json(name,item,level,varargin)
|
|
|
|
if(iscell(item))
|
|
txt=cell2json(name,item,level,varargin{:});
|
|
elseif(isstruct(item))
|
|
txt=struct2json(name,item,level,varargin{:});
|
|
elseif(ischar(item))
|
|
txt=str2json(name,item,level,varargin{:});
|
|
elseif(isobject(item))
|
|
txt=matlabobject2json(name,item,level,varargin{:});
|
|
else
|
|
txt=mat2json(name,item,level,varargin{:});
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=cell2json(name,item,level,varargin)
|
|
txt={};
|
|
if(~iscell(item))
|
|
error('input is not a cell');
|
|
end
|
|
|
|
dim=size(item);
|
|
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
|
item=reshape(item,dim(1),numel(item)/dim(1));
|
|
dim=size(item);
|
|
end
|
|
len=numel(item);
|
|
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:});
|
|
padding0=repmat(ws.tab,1,level);
|
|
padding2=repmat(ws.tab,1,level+1);
|
|
nl=ws.newline;
|
|
bracketlevel=~jsonopt('singletcell',1,varargin{:});
|
|
if(len>bracketlevel)
|
|
if(~isempty(name))
|
|
txt={padding0, '"', checkname(name,varargin{:}),'": [', nl}; name='';
|
|
else
|
|
txt={padding0, '[', nl};
|
|
end
|
|
elseif(len==0)
|
|
if(~isempty(name))
|
|
txt={padding0, '"' checkname(name,varargin{:}) '": []'}; name='';
|
|
else
|
|
txt={padding0, '[]'};
|
|
end
|
|
end
|
|
for i=1:dim(1)
|
|
if(dim(1)>1)
|
|
txt(end+1:end+3)={padding2,'[',nl};
|
|
end
|
|
for j=1:dim(2)
|
|
txt{end+1}=obj2json(name,item{i,j},level+(dim(1)>1)+(len>bracketlevel),varargin{:});
|
|
if(j<dim(2))
|
|
txt(end+1:end+2)={',' nl};
|
|
end
|
|
end
|
|
if(dim(1)>1)
|
|
txt(end+1:end+3)={nl,padding2,']'};
|
|
end
|
|
if(i<dim(1))
|
|
txt(end+1:end+2)={',' nl};
|
|
end
|
|
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
|
|
end
|
|
if(len>bracketlevel)
|
|
txt(end+1:end+3)={nl,padding0,']'};
|
|
end
|
|
txt = sprintf('%s',txt{:});
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=struct2json(name,item,level,varargin)
|
|
txt={};
|
|
if(~isstruct(item))
|
|
error('input is not a struct');
|
|
end
|
|
dim=size(item);
|
|
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
|
item=reshape(item,dim(1),numel(item)/dim(1));
|
|
dim=size(item);
|
|
end
|
|
len=numel(item);
|
|
forcearray= (len>1 || (jsonopt('SingletArray',0,varargin{:})==1 && level>0));
|
|
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'));
|
|
ws=jsonopt('whitespaces_',ws,varargin{:});
|
|
padding0=repmat(ws.tab,1,level);
|
|
padding2=repmat(ws.tab,1,level+1);
|
|
padding1=repmat(ws.tab,1,level+(dim(1)>1)+forcearray);
|
|
nl=ws.newline;
|
|
|
|
if(isempty(item))
|
|
if(~isempty(name))
|
|
txt={padding0, '"', checkname(name,varargin{:}),'": []'};
|
|
else
|
|
txt={padding0, '[]'};
|
|
end
|
|
txt = sprintf('%s',txt{:});
|
|
return;
|
|
end
|
|
if(~isempty(name))
|
|
if(forcearray)
|
|
txt={padding0, '"', checkname(name,varargin{:}),'": [', nl};
|
|
end
|
|
else
|
|
if(forcearray)
|
|
txt={padding0, '[', nl};
|
|
end
|
|
end
|
|
for j=1:dim(2)
|
|
if(dim(1)>1)
|
|
txt(end+1:end+3)={padding2,'[',nl};
|
|
end
|
|
for i=1:dim(1)
|
|
names = fieldnames(item(i,j));
|
|
if(~isempty(name) && len==1 && ~forcearray)
|
|
txt(end+1:end+5)={padding1, '"', checkname(name,varargin{:}),'": {', nl};
|
|
else
|
|
txt(end+1:end+3)={padding1, '{', nl};
|
|
end
|
|
if(~isempty(names))
|
|
for e=1:length(names)
|
|
txt{end+1}=obj2json(names{e},item(i,j).(names{e}),...
|
|
level+(dim(1)>1)+1+forcearray,varargin{:});
|
|
if(e<length(names))
|
|
txt{end+1}=',';
|
|
end
|
|
txt{end+1}=nl;
|
|
end
|
|
end
|
|
txt(end+1:end+2)={padding1,'}'};
|
|
if(i<dim(1))
|
|
txt(end+1:end+2)={',' nl};
|
|
end
|
|
end
|
|
if(dim(1)>1)
|
|
txt(end+1:end+3)={nl,padding2,']'};
|
|
end
|
|
if(j<dim(2))
|
|
txt(end+1:end+2)={',' nl};
|
|
end
|
|
end
|
|
if(forcearray)
|
|
txt(end+1:end+3)={nl,padding0,']'};
|
|
end
|
|
txt = sprintf('%s',txt{:});
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=str2json(name,item,level,varargin)
|
|
txt={};
|
|
if(~ischar(item))
|
|
error('input is not a string');
|
|
end
|
|
item=reshape(item, max(size(item),[1 0]));
|
|
len=size(item,1);
|
|
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
|
ws=jsonopt('whitespaces_',ws,varargin{:});
|
|
padding1=repmat(ws.tab,1,level);
|
|
padding0=repmat(ws.tab,1,level+1);
|
|
nl=ws.newline;
|
|
sep=ws.sep;
|
|
|
|
if(~isempty(name))
|
|
if(len>1)
|
|
txt={padding1, '"', checkname(name,varargin{:}),'": [', nl};
|
|
end
|
|
else
|
|
if(len>1)
|
|
txt={padding1, '[', nl};
|
|
end
|
|
end
|
|
for e=1:len
|
|
val=escapejsonstring(item(e,:));
|
|
if(len==1)
|
|
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"'];
|
|
if(isempty(name))
|
|
obj=['"',val,'"'];
|
|
end
|
|
txt(end+1:end+2)={padding1, obj};
|
|
else
|
|
txt(end+1:end+4)={padding0,'"',val,'"'};
|
|
end
|
|
if(e==len)
|
|
sep='';
|
|
end
|
|
txt{end+1}=sep;
|
|
end
|
|
if(len>1)
|
|
txt(end+1:end+3)={nl,padding1,']'};
|
|
end
|
|
txt = sprintf('%s',txt{:});
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=mat2json(name,item,level,varargin)
|
|
if(~isnumeric(item) && ~islogical(item))
|
|
error('input is not an array');
|
|
end
|
|
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
|
ws=jsonopt('whitespaces_',ws,varargin{:});
|
|
padding1=repmat(ws.tab,1,level);
|
|
padding0=repmat(ws.tab,1,level+1);
|
|
nl=ws.newline;
|
|
sep=ws.sep;
|
|
|
|
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ...
|
|
(isempty(item) && any(size(item))) ||jsonopt('ArrayToStruct',0,varargin{:}))
|
|
if(isempty(name))
|
|
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
|
|
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
|
|
else
|
|
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
|
|
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
|
|
end
|
|
else
|
|
if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0 && level>0)
|
|
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']','');
|
|
else
|
|
numtxt=matdata2json(item,level+1,varargin{:});
|
|
end
|
|
if(isempty(name))
|
|
txt=sprintf('%s%s',padding1,numtxt);
|
|
else
|
|
if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0)
|
|
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
|
|
else
|
|
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
|
|
end
|
|
end
|
|
return;
|
|
end
|
|
dataformat='%s%s%s%s%s';
|
|
|
|
if(issparse(item))
|
|
[ix,iy]=find(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', sep);
|
|
end
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep);
|
|
if(size(item,1)==1)
|
|
% Row vector, store only column indices.
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
|
matdata2json([iy(:),data'],level+2,varargin{:}), nl);
|
|
elseif(size(item,2)==1)
|
|
% Column vector, store only row indices.
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
|
matdata2json([ix,data],level+2,varargin{:}), nl);
|
|
else
|
|
% General case, store row and column indices.
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
|
matdata2json([ix,iy,data],level+2,varargin{:}), nl);
|
|
end
|
|
else
|
|
if(isreal(item))
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
|
matdata2json(item(:)',level+2,varargin{:}), nl);
|
|
else
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
|
|
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
|
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl);
|
|
end
|
|
end
|
|
txt=sprintf('%s%s%s',txt,padding1,'}');
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=matlabobject2json(name,item,level,varargin)
|
|
if numel(item) == 0 %empty object
|
|
st = struct();
|
|
else
|
|
% "st = struct(item);" would produce an inmutable warning, because it
|
|
% make the protected and private properties visible. Instead we get the
|
|
% visible properties
|
|
propertynames = properties(item);
|
|
for p = 1:numel(propertynames)
|
|
for o = numel(item):-1:1 % aray of objects
|
|
st(o).(propertynames{p}) = item(o).(propertynames{p});
|
|
end
|
|
end
|
|
end
|
|
txt=struct2json(name,st,level,varargin{:});
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function txt=matdata2json(mat,level,varargin)
|
|
|
|
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
|
ws=jsonopt('whitespaces_',ws,varargin{:});
|
|
tab=ws.tab;
|
|
nl=ws.newline;
|
|
|
|
if(size(mat,1)==1)
|
|
pre='';
|
|
post='';
|
|
level=level-1;
|
|
else
|
|
pre=sprintf('[%s',nl);
|
|
post=sprintf('%s%s]',nl,repmat(tab,1,level-1));
|
|
end
|
|
|
|
if(isempty(mat))
|
|
txt='null';
|
|
return;
|
|
end
|
|
floatformat=jsonopt('FloatFormat','%.10g',varargin{:});
|
|
%if(numel(mat)>1)
|
|
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]];
|
|
%else
|
|
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]];
|
|
%end
|
|
|
|
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1)
|
|
formatstr=[repmat(tab,1,level) formatstr];
|
|
end
|
|
|
|
txt=sprintf(formatstr,mat');
|
|
txt(end-length(nl):end)=[];
|
|
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1)
|
|
txt=regexprep(txt,'1','true');
|
|
txt=regexprep(txt,'0','false');
|
|
end
|
|
%txt=regexprep(mat2str(mat),'\s+',',');
|
|
%txt=regexprep(txt,';',sprintf('],\n['));
|
|
% if(nargin>=2 && size(mat,1)>1)
|
|
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']);
|
|
% end
|
|
txt=[pre txt post];
|
|
if(any(isinf(mat(:))))
|
|
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:}));
|
|
end
|
|
if(any(isnan(mat(:))))
|
|
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:}));
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function newname=checkname(name,varargin)
|
|
isunpack=jsonopt('UnpackHex',1,varargin{:});
|
|
newname=name;
|
|
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once')))
|
|
return
|
|
end
|
|
if(isunpack)
|
|
isoct=jsonopt('IsOctave',0,varargin{:});
|
|
if(~isoct)
|
|
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}');
|
|
else
|
|
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start');
|
|
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end');
|
|
if(isempty(pos))
|
|
return;
|
|
end
|
|
str0=name;
|
|
pos0=[0 pend(:)' length(name)];
|
|
newname='';
|
|
for i=1:length(pos)
|
|
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))];
|
|
end
|
|
if(pos(end)~=length(name))
|
|
newname=[newname str0(pos0(end-1)+1:pos0(end))];
|
|
end
|
|
end
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function newstr=escapejsonstring(str)
|
|
newstr=str;
|
|
isoct=exist('OCTAVE_VERSION','builtin');
|
|
if(isoct)
|
|
vv=sscanf(OCTAVE_VERSION,'%f');
|
|
if(vv(1)>=3.8)
|
|
isoct=0;
|
|
end
|
|
end
|
|
if(isoct)
|
|
escapechars={'\\','\"','\/','\a','\f','\n','\r','\t','\v'};
|
|
for i=1:length(escapechars);
|
|
newstr=regexprep(newstr,escapechars{i},escapechars{i});
|
|
end
|
|
newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\$1');
|
|
else
|
|
escapechars={'\\','\"','\/','\a','\b','\f','\n','\r','\t','\v'};
|
|
for i=1:length(escapechars);
|
|
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\'));
|
|
end
|
|
newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\\$1');
|
|
end
|
|
|
|
%%-------------------------------------------------------------------------
|
|
function [urlConnection,errorid,errormsg] = urlreadwrite(fcn,urlChar)
|
|
%URLREADWRITE A helper function for URLREAD and URLWRITE.
|
|
|
|
% Matthew J. Simoneau, June 2005
|
|
% Copyright 1984-2009 The MathWorks, Inc.
|
|
% $Revision: 1.1.6.5 $ $Date: 2009/09/28 20:28:02 $
|
|
|
|
% Default output arguments.
|
|
urlConnection = [];
|
|
errorid = '';
|
|
errormsg = '';
|
|
|
|
% Determine the protocol (before the ":").
|
|
protocol = urlChar(1:min(find(urlChar==':'))-1);
|
|
|
|
% Try to use the native handler, not the ice.* classes.
|
|
switch protocol
|
|
case 'http'
|
|
try
|
|
handler = sun.net.www.protocol.http.Handler;
|
|
catch exception %#ok
|
|
handler = [];
|
|
end
|
|
case 'https'
|
|
try
|
|
handler = sun.net.www.protocol.https.Handler;
|
|
catch exception %#ok
|
|
handler = [];
|
|
end
|
|
otherwise
|
|
handler = [];
|
|
end
|
|
|
|
% Create the URL object.
|
|
try
|
|
if isempty(handler)
|
|
url = java.net.URL(urlChar);
|
|
else
|
|
url = java.net.URL([],urlChar,handler);
|
|
end
|
|
catch exception %#ok
|
|
errorid = ['MATLAB:' fcn ':InvalidUrl'];
|
|
errormsg = 'Either this URL could not be parsed or the protocol is not supported.';
|
|
return
|
|
end
|
|
|
|
% Get the proxy information using MathWorks facilities for unified proxy
|
|
% preference settings.
|
|
mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create();
|
|
proxy = mwtcp.getProxy();
|
|
|
|
|
|
% Open a connection to the URL.
|
|
if isempty(proxy)
|
|
urlConnection = url.openConnection;
|
|
else
|
|
urlConnection = url.openConnection(proxy);
|
|
end
|