Home > utils > finputcheck.m

finputcheck

PURPOSE ^

finputcheck() - check Matlab function {'key','value'} input argument pairs

SYNOPSIS ^

function [g, varargnew] = finputcheck( vararg, fieldlist, callfunc, mode )

DESCRIPTION ^

 finputcheck() - check Matlab function {'key','value'} input argument pairs

 Usage: >> result = finputcheck( varargin, fieldlist );
        >> [result varargin] = finputcheck( varargin, fieldlist, ... 
                                                         callingfunc, mode );
 Input:
   varargin  - 'varargin' argument from a function call using 'key', 'value'
               argument pairs.
   fieldlist - A 3- to 5-column cell array, one row per 'key'. The first
               column contains the key string, the second its type, 
               the third the accepted value range, and the fourth the 
               default value.  Allowed types are 'boolean', 'integer', 
               'real', 'string', 'cell' or 'struct'.  For example,
                       {'key1' 'string' { 'string1' 'string2' } 'defaultval_key1'}
                       {'key2' 'int' { minint maxint } 'defaultval_key2'} 
  callingfunc - Calling function name for error messages. {default: none}.
  mode        - ['ignore'|'error'] ignore keywords that are either not specified 
                in the fieldlist cell array or generate an error. 
                {default: 'error'}.
 Outputs:
   result     - If no error, structure with 'key' as fields and 'value' as 
                content. If error this output contain the string error.
   varargin   - residual varagin containing unrecognized input arguments.
                Requires mode 'ignore' above.

 Note: In case of error, a string is returned containing the error message
       instead of a structure.

 Example:
    g = finputcheck(varargin, ...
               { 'title'         'string'   []       ''; ...
                 'percent'       'real'     [0 1]    1 ; ...
                 'elecamp'       'integer'  [1:10]   [] });
 Note: 
   The 'title' argument should be a string. {no default value}
   The 'percent' argument should be a real number between 0 and 1. {default: 1}
   The 'elecamp' argument should be an integer between 1 and 10 (inclusive).

   Now 'g.title' will contain the title arg (if any, else the default ''), etc.

 Author: Arnaud Delorme, CNL / Salk Institute, 10 July 2002

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % finputcheck() - check Matlab function {'key','value'} input argument pairs
0002 %
0003 % Usage: >> result = finputcheck( varargin, fieldlist );
0004 %        >> [result varargin] = finputcheck( varargin, fieldlist, ...
0005 %                                                         callingfunc, mode );
0006 % Input:
0007 %   varargin  - 'varargin' argument from a function call using 'key', 'value'
0008 %               argument pairs.
0009 %   fieldlist - A 3- to 5-column cell array, one row per 'key'. The first
0010 %               column contains the key string, the second its type,
0011 %               the third the accepted value range, and the fourth the
0012 %               default value.  Allowed types are 'boolean', 'integer',
0013 %               'real', 'string', 'cell' or 'struct'.  For example,
0014 %                       {'key1' 'string' { 'string1' 'string2' } 'defaultval_key1'}
0015 %                       {'key2' 'int' { minint maxint } 'defaultval_key2'}
0016 %  callingfunc - Calling function name for error messages. {default: none}.
0017 %  mode        - ['ignore'|'error'] ignore keywords that are either not specified
0018 %                in the fieldlist cell array or generate an error.
0019 %                {default: 'error'}.
0020 % Outputs:
0021 %   result     - If no error, structure with 'key' as fields and 'value' as
0022 %                content. If error this output contain the string error.
0023 %   varargin   - residual varagin containing unrecognized input arguments.
0024 %                Requires mode 'ignore' above.
0025 %
0026 % Note: In case of error, a string is returned containing the error message
0027 %       instead of a structure.
0028 %
0029 % Example:
0030 %    g = finputcheck(varargin, ...
0031 %               { 'title'         'string'   []       ''; ...
0032 %                 'percent'       'real'     [0 1]    1 ; ...
0033 %                 'elecamp'       'integer'  [1:10]   [] });
0034 % Note:
0035 %   The 'title' argument should be a string. {no default value}
0036 %   The 'percent' argument should be a real number between 0 and 1. {default: 1}
0037 %   The 'elecamp' argument should be an integer between 1 and 10 (inclusive).
0038 %
0039 %   Now 'g.title' will contain the title arg (if any, else the default ''), etc.
0040 %
0041 % Author: Arnaud Delorme, CNL / Salk Institute, 10 July 2002
0042 
0043 %123456789012345678901234567890123456789012345678901234567890123456789012
0044 
0045 % Copyright (C) Arnaud Delorme, CNL / Salk Institute, 10 July 2002, arno@salk.edu
0046 %
0047 % This program is free software; you can redistribute it and/or modify
0048 % it under the terms of the GNU General Public License as published by
0049 % the Free Software Foundation; either version 2 of the License, or
0050 % (at your option) any later version.
0051 %
0052 % This program is distributed in the hope that it will be useful,
0053 % but WITHOUT ANY WARRANTY; without even the implied warranty of
0054 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0055 % GNU General Public License for more details.
0056 %
0057 % You should have received a copy of the GNU General Public License
0058 % along with this program; if not, write to the Free Software
0059 % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0060 
0061 % $Log: finputcheck.m,v $
0062 % Revision 1.24  2006/03/11 05:37:07  arno
0063 % header
0064 %
0065 % Revision 1.23  2004/11/06 02:54:06  scott
0066 % a few further small edits to the help msg -sm
0067 %
0068 % Revision 1.22  2004/11/05 15:23:37  arno
0069 % ,sg
0070 %
0071 % Revision 1.21  2004/11/05 04:10:44  scott
0072 % help msg. -sm
0073 %
0074 % Revision 1.20  2004/06/09 16:30:42  arno
0075 % adding or if several types
0076 %
0077 % Revision 1.19  2003/10/29 16:35:57  arno
0078 % msg typo
0079 %
0080 % Revision 1.18  2003/07/30 23:53:58  arno
0081 % debug multiple return values
0082 %
0083 % Revision 1.17  2003/07/26 00:21:17  arno
0084 % allowing cell array for values
0085 %
0086 % Revision 1.16  2003/06/30 02:10:10  arno
0087 % strmatch exact
0088 %
0089 % Revision 1.15  2003/01/31 02:35:38  arno
0090 % debugging lowercase/upercase problem
0091 %
0092 % Revision 1.14  2002/11/20 01:05:44  arno
0093 % take into account duplicate parameters
0094 %
0095 % Revision 1.13  2002/11/18 17:15:18  arno
0096 % adding float arg (=real)
0097 %
0098 % Revision 1.12  2002/11/15 02:16:50  arno
0099 % header for web
0100 %
0101 % Revision 1.11  2002/09/30 15:29:23  arno
0102 % autorizing cell arrays for types
0103 %
0104 % Revision 1.10  2002/09/30 00:42:08  arno
0105 % debug input arguments
0106 %
0107 % Revision 1.9  2002/07/29 18:00:53  arno
0108 % debugging for NaN
0109 %
0110 % Revision 1.8  2002/07/29 17:24:22  arno
0111 % header
0112 %
0113 % Revision 1.7  2002/07/20 19:10:41  arno
0114 % debugging output
0115 %
0116 % Revision 1.6  2002/07/19 17:58:11  arno
0117 % returning non-matched 'key' 'val' arguments
0118 %
0119 % Revision 1.5  2002/07/19 17:46:53  arno
0120 % g empty if no varargin
0121 %
0122 % Revision 1.4  2002/07/19 16:27:14  arno
0123 % adding ignore mode
0124 %
0125 % Revision 1.3  2002/07/10 02:18:32  arno
0126 % header info
0127 %
0128 % Revision 1.2  2002/07/10 02:17:27  arno
0129 % debugging error message passing
0130 %
0131 % Revision 1.1  2002/07/10 01:03:19  arno
0132 % Initial revision
0133 %
0134 
0135 function [g, varargnew] = finputcheck( vararg, fieldlist, callfunc, mode )
0136 
0137     if nargin < 2
0138         help finputcheck;
0139         return;
0140     end;
0141     if nargin < 3
0142         callfunc = '';
0143     else 
0144         callfunc = [callfunc ' ' ];
0145     end;
0146     if nargin < 4
0147         mode = 'do not ignore';
0148     end;
0149     NAME = 1;
0150     TYPE = 2;
0151     VALS = 3;
0152     DEF  = 4;
0153     SIZE = 5;
0154     
0155     varargnew = {};
0156     % create structure
0157     % ----------------
0158     if ~isempty(vararg)
0159         vararg = removedup(vararg);
0160         for index=1:length(vararg)
0161             if iscell(vararg{index})
0162                 vararg{index} = {vararg{index}};
0163             end;
0164         end;
0165         try
0166             g = struct(vararg{:});
0167         catch
0168             g = [ callfunc 'error: bad ''key'', ''val'' sequence' ]; return;
0169         end;
0170     else 
0171         g = [];
0172     end;
0173     
0174     for index = 1:size(fieldlist,NAME)
0175         % check if present
0176         % ----------------
0177         if ~isfield(g, fieldlist{index, NAME})
0178             g = setfield( g, fieldlist{index, NAME}, fieldlist{index, DEF});
0179         end;
0180         tmpval = getfield( g, {1}, fieldlist{index, NAME});
0181         
0182         % check type
0183         % ----------
0184         if ~iscell( fieldlist{index, TYPE} )
0185             res = fieldtest( fieldlist{index, NAME},  fieldlist{index, TYPE}, ...
0186                            fieldlist{index, VALS}, tmpval, callfunc );
0187             if isstr(res), g = res; return; end;
0188         else 
0189             testres = 0;
0190             tmplist = fieldlist;
0191             for it = 1:length( fieldlist{index, TYPE} )
0192                 if ~iscell(fieldlist{index, VALS})
0193                      res{it} = fieldtest(  fieldlist{index, NAME},  fieldlist{index, TYPE}{it}, ...
0194                                            fieldlist{index, VALS}, tmpval, callfunc );
0195                 else res{it} = fieldtest(  fieldlist{index, NAME},  fieldlist{index, TYPE}{it}, ...
0196                                            fieldlist{index, VALS}{it}, tmpval, callfunc );
0197                 end;
0198                 if ~isstr(res{it}), testres = 1; end;
0199             end;
0200             if testres == 0,
0201                 g = res{1};
0202                 for tmpi = 2:length(res)
0203                     g = [ g 10 'or ' res{tmpi} ];
0204                 end;
0205                 return; 
0206             end;
0207         end;
0208     end;
0209     
0210     % check if fields are defined
0211     % ---------------------------
0212     allfields = fieldnames(g);
0213     for index=1:length(allfields)
0214         if isempty(strmatch(allfields{index}, fieldlist(:, 1)', 'exact'))
0215             if ~strcmpi(mode, 'ignore')
0216                 g = [ callfunc 'error: undefined argument ''' allfields{index} '''']; return;
0217             end;
0218             varargnew{end+1} = allfields{index};
0219             varargnew{end+1} = getfield(g, {1}, allfields{index});
0220         end;
0221     end;
0222 
0223 
0224 function g = fieldtest( fieldname, fieldtype, fieldval, tmpval, callfunc );
0225     NAME = 1;
0226     TYPE = 2;
0227     VALS = 3;
0228     DEF  = 4;
0229     SIZE = 5;
0230     g = [];
0231     
0232     switch fieldtype
0233      case { 'integer' 'real' 'boolean' 'float' }, 
0234       if ~isnumeric(tmpval)
0235           g = [ callfunc 'error: argument ''' fieldname ''' must be numeric' ]; return;
0236       end;
0237       if strcmpi(fieldtype, 'boolean')
0238           if tmpval ~=0 & tmpval ~= 1
0239               g = [ callfunc 'error: argument ''' fieldname ''' must be 0 or 1' ]; return;
0240           end;  
0241       else 
0242           if strcmpi(fieldtype, 'integer')
0243               if ~isempty(fieldval)
0244                   if (isnan(tmpval) & ~any(isnan(fieldval))) ...
0245                           & (~ismember(tmpval, fieldval))
0246                       g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
0247                   end;
0248               end;
0249           else % real or float
0250               if ~isempty(fieldval)
0251                   if tmpval < fieldval(1) | tmpval > fieldval(2)
0252                       g = [ callfunc 'error: value out of range for argument ''' fieldname '''' ]; return;
0253                   end;
0254               end;
0255           end;
0256       end;  
0257       
0258       
0259      case 'string'
0260       if ~isstr(tmpval)
0261           g = [ callfunc 'error: argument ''' fieldname ''' must be a string' ]; return;
0262       end;
0263       if ~isempty(fieldval)
0264           if isempty(strmatch(lower(tmpval), lower(fieldval), 'exact'))
0265               g = [ callfunc 'error: wrong value for argument ''' fieldname '''' ]; return;
0266           end;
0267       end;
0268 
0269       
0270      case 'cell'
0271       if ~iscell(tmpval)
0272           g = [ callfunc 'error: argument ''' fieldname ''' must be a cell array' ]; return;
0273       end;
0274       
0275       
0276      case 'struct'
0277       if ~isstruct(tmpval)
0278           g = [ callfunc 'error: argument ''' fieldname ''' must be a structure' ]; return;
0279       end;
0280       
0281       
0282      case '';
0283      otherwise, error([ 'finputcheck error: unrecognized type ''' fieldname '''' ]);
0284     end;
0285 
0286 % remove duplicates in the list of parameters
0287 % -------------------------------------------
0288 function cella = removedup(cella)
0289     [tmp indices] = unique(cella(1:2:end));
0290     if length(tmp) ~= length(cella)/2
0291         fprintf('Warning: duplicate ''key'', ''val'' parameter(s), keeping the last one(s)\n');
0292     end;
0293     cella = cella(sort(union(indices*2-1, indices*2)));

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003