function parser = matlab2tikzInputParser()
%MATLAB2TIKZINPUTPARSER Input parsing for matlab2tikz..
% This implementation exists because Octave is lacking one.
% Copyright (c) 2008--2013 Nico Schlömer
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
% =========================================================================
% Initialize the structure.
parser = struct ();
% Public Properties
parser.Results = {};
% Enabel/disable parameters case sensitivity.
parser.CaseSensitive = false;
% Enable/disable error for parameters not defined by the constructor.
parser.KeepUnmatched = false;
% Enable/disable passing arguments in a structure.
parser.StructExpand = true;
% Names of parameters defined in input parser constructor.
parser.Parameters = {};
% Names of parameters not defined in the constructor.
parser.Unmatched = struct ();
% Names of parameters using default values.
parser.UsingDefaults = {};
% Handles for functions that act on the object.
parser.addRequired = @addRequired;
parser.addOptional = @addOptional;
parser.addParamValue = @addParamValue;
parser.parse = @parse;
% Initialize the parser plan
parser.plan = {};
end
% =========================================================================
function p = parser_plan (q, arg_type, name, default, validator)
p = q;
plan = p.plan;
if (isempty (plan))
plan = struct ();
n = 1;
else
n = numel (plan) + 1;
end
plan(n).type = arg_type;
plan(n).name = name;
plan(n).default = default;
plan(n).validator = validator;
p.plan = plan;
end
% =========================================================================
function p = addRequired (p, name, validator)
p = parser_plan (p, 'required', name, [], validator);
end
% =========================================================================
function p = addOptional (p, name, default, validator)
p = parser_plan (p, 'optional', name, default, validator);
end
% =========================================================================
function p = addParamValue (p, name, default, validator)
p = parser_plan (p, 'paramvalue', name, default, validator);
end
% =========================================================================
function p = parse (p, varargin)
plan = p.plan;
results = p.Results;
using_defaults = {};
if (p.CaseSensitive)
name_cmp = @strcmp;
else
name_cmp = @strcmpi;
end
if (p.StructExpand)
k = find (cellfun (@isstruct, varargin));
for m = numel(k):-1:1
n = k(m);
s = varargin{n};
c = [fieldnames(s).'; struct2cell(s).'];
c = c(:).';
if (n > 1 && n < numel (varargin))
varargin = horzcat (varargin(1:n-1), c, varargin(n+1:end));
elseif (numel (varargin) == 1)
varargin = c;
elseif (n == 1);
varargin = horzcat (c, varargin(n+1:end));
else % n == numel (varargin)
varargin = horzcat (varargin(1:n-1), c);
end
end
end
if (isempty (results))
results = struct ();
end
type = {plan.type};
n = find( strcmp( type, 'paramvalue' ) );
m = setdiff (1:numel( plan ), n );
plan = plan ([n,m]);
for n = 1 : numel (plan)
found = false;
results.(plan(n).name) = plan(n).default;
if (~ isempty (varargin))
switch plan(n).type
case 'required'
found = true;
if (strcmpi (varargin{1}, plan(n).name))
varargin(1) = [];
end
value = varargin{1};
varargin(1) = [];
case 'optional'
m = find (cellfun (@ischar, varargin));
k = find (name_cmp (plan(n).name, varargin(m)));
if (isempty (k) && validate_arg (plan(n).validator, varargin{1}))
found = true;
value = varargin{1};
varargin(1) = [];
elseif (~ isempty (k))
m = m(k);
found = true;
value = varargin{max(m)+1};
varargin(union(m,m+1)) = [];
end
case 'paramvalue'
m = find( cellfun (@ischar, varargin) );
k = find (name_cmp (plan(n).name, varargin(m)));
if (~ isempty (k))
found = true;
m = m(k);
value = varargin{max(m)+1};
varargin(union(m,m+1)) = [];
end
otherwise
error( sprintf ('%s:parse', mfilename), ...
'parse (%s): Invalid argument type.', mfilename ...
)
end
end
if (found)
if (validate_arg (plan(n).validator, value))
results.(plan(n).name) = value;
else
error( sprintf ('%s:invalidinput', mfilename), ...
'%s: Input argument ''%s'' has invalid value.\n', mfilename, plan(n).name ...
);
end
p.Parameters = union (p.Parameters, {plan(n).name});
elseif (strcmp (plan(n).type, 'required'))
error( sprintf ('%s:missinginput', mfilename), ...
'%s: input ''%s'' is missing.\n', mfilename, plan(n).name ...
);
else
using_defaults = union (using_defaults, {plan(n).name});
end
end
if (~ isempty (varargin))
if (p.KeepUnmatched)
% Include properties that do not match specified properties
for n = 1:2:numel(varargin)
if (ischar (varargin{n}))
results.(varargin{n}) = varargin{n+1};
else
error (sprintf ('%s:invalidinput', mfilename), ...
'%s: invalid input', mfilename)
end
end
end
p.Unmatched = varargin{1:2:end};
end
% Store the results of the parsing
p.Results = results;
p.UsingDefaults = using_defaults;
end
% =========================================================================
function result = validate_arg (validator, arg)
try
result = validator (arg);
catch %#ok
result = false;
end
end
% =========================================================================