]> Creatis software - CreaPhase.git/blobdiff - octave_packages/m/strings/validatestring.m
update packages
[CreaPhase.git] / octave_packages / m / strings / validatestring.m
diff --git a/octave_packages/m/strings/validatestring.m b/octave_packages/m/strings/validatestring.m
new file mode 100644 (file)
index 0000000..08877c0
--- /dev/null
@@ -0,0 +1,163 @@
+## Copyright (C) 2008-2012 Bill Denney
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{validstr} =} validatestring (@var{str}, @var{strarray})
+## @deftypefnx {Function File} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname})
+## @deftypefnx {Function File} {@var{validstr} =} validatestring (@var{str}, @var{strarray}, @var{funcname}, @var{varname})
+## @deftypefnx {Function File} {@var{validstr} =} validatestring (@dots{}, @var{position})
+## Verify that @var{str} is an element, or substring of an element, in
+## @var{strarray}.
+##
+## When @var{str} is a character string to be tested, and @var{strarray} is a
+## cellstr of valid values, then @var{validstr} will be the validated form
+## of @var{str} where validation is defined as @var{str} being a member
+## or substring of @var{validstr}.  This is useful for both verifying
+## and expanding short options, such as "r", to their longer forms, such as
+## "red".  If @var{str} is a substring of @var{validstr}, and there are
+## multiple matches, the shortest match will be returned if all matches are
+## substrings of each other.  Otherwise, an error will be raised because the
+## expansion of @var{str} is ambiguous.  All comparisons are case insensitive.
+##
+## The additional inputs @var{funcname}, @var{varname}, and @var{position}
+## are optional and will make any generated validation error message more
+## specific.
+##
+## Examples:
+## @c Set example in small font to prevent overfull line
+##
+## @smallexample
+## @group
+## validatestring ("r", @{"red", "green", "blue"@})
+## @result{} "red"
+##
+## validatestring ("b", @{"red", "green", "blue", "black"@})
+## @result{} error: validatestring: multiple unique matches were found for 'b':
+##    blue, black
+## @end group
+## @end smallexample
+## 
+## @seealso{strcmp, strcmpi}
+## @end deftypefn
+
+## Author: Bill Denney <bill@denney.ws>
+
+function str = validatestring (str, strarray, varargin)
+
+  if (nargin < 2 || nargin > 5)
+    print_usage ();
+  endif
+
+  position = 0;
+  ## Process input arguments
+  if (! isempty (varargin) && isnumeric (varargin{end}))
+    position = varargin{end};
+    varargin(end) = [];
+  endif
+  
+  funcname = varname = "";
+  char_idx = cellfun ("isclass", varargin, "char");
+  n_chararg = sum (char_idx);
+  if (n_chararg > 2)
+    error ("validatestring: invalid number of character inputs (3)");
+  elseif (n_chararg == 2)
+    [funcname, varname] = deal (varargin{char_idx});
+  elseif (n_chararg == 1)
+    funcname = varargin{char_idx};
+  endif
+
+  ## Check the inputs
+  if (! ischar (str))
+    error ("validatestring: STR must be a character string");
+  elseif (! isrow (str))
+    error ("validatestring: STR must be a single row vector");
+  elseif (! iscellstr (strarray))
+    error ("validatestring: STRARRAY must be a cellstr");
+  elseif (! isempty (funcname) && ! isrow (funcname))
+    error ("validatestring: FUNCNAME must be a single row vector");
+  elseif (! isempty (varname) && ! isrow (varname))
+    error ("validatestring: VARNAME must be a single row vector");
+  elseif (position < 0)
+    error ("validatestring: POSITION must be >= 0");
+  endif
+
+  ## Make static part of error string that uses funcname, varname, and position
+  errstr = "";
+  if (! isempty (funcname))
+    errstr = sprintf ("Function: %s ", funcname);
+  endif
+  if (! isempty (varname))
+    errstr = sprintf ("%sVariable: %s ", errstr, varname);
+  endif
+  if (position > 0)
+    errstr = sprintf ("%sArgument position %d ", errstr, position);
+  endif
+  if (! isempty (errstr))
+    errstr(end:end+1) = ":\n";
+  endif
+
+  matches = strncmpi (str, strarray(:), numel (str));
+  nmatches = sum (matches);
+  if (nmatches == 0)
+    error ("validatestring: %s'%s' does not match any of\n%s", errstr, str,
+           sprintf ("%s, ", strarray{:})(1:end-2));
+  elseif (nmatches == 1)
+    str = strarray{matches};
+  else
+    ## Are the matches substrings of each other?
+    ## If true, choose the shortest.  If not, raise an error.
+    match_idx = find (matches);
+    match_len = cellfun ("length", strarray(match_idx));
+    [min_len, min_idx] = min (match_len); 
+    short_str = strarray{match_idx(min_idx)};
+    submatch = strncmpi (short_str, strarray(match_idx), min_len);    
+    if (all (submatch))
+      str = short_str;
+    else
+      error ("validatestring: %smultiple unique matches were found for '%s':\n%s",
+             errstr, str, sprintf ("%s, ", strarray{match_idx})(1:end-2));
+    endif
+  endif
+
+endfunction
+
+
+%!shared strarray
+%!  strarray = {"octave" "Oct" "octopus" "octaves"};
+%!assert (validatestring ("octave", strarray), "octave")
+%!assert (validatestring ("oct", strarray), "Oct")
+%!assert (validatestring ("octa", strarray), "octave")
+%!  strarray = {"abc1" "def" "abc2"};
+%!assert (validatestring ("d", strarray), "def")
+%!error <'xyz' does not match any> validatestring ("xyz", strarray)
+%!error <Function: DUMMY_TEST> validatestring ("xyz", strarray, "DUMMY_TEST")
+%!error <Function: DUMMY_TEST Variable: DUMMY_VAR:> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
+%!error <Function: DUMMY_TEST Variable: DUMMY_VAR Argument position 5> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
+%!error <multiple unique matches were found for 'abc'> validatestring ("abc", strarray)
+
+%% Test input validation
+%!error validatestring ("xyz")
+%!error validatestring ("xyz", {"xyz"}, "3", "4", 5, 6)
+%!error <invalid number of character inputs> validatestring ("xyz", {"xyz"}, "3", "4", "5")
+%!error <STR must be a character string> validatestring (1, {"xyz"}, "3", "4", 5)
+%!error <STR must be a single row vector> validatestring ("xyz".', {"xyz"}, "3", "4", 5)
+%!error <STRARRAY must be a cellstr> validatestring ("xyz", "xyz", "3", "4", 5)
+%!error <FUNCNAME must be a single row vector> validatestring ("xyz", {"xyz"}, "33".', "4", 5)
+%!error <VARNAME must be a single row vector> validatestring ("xyz", {"xyz"}, "3", "44".', 5)
+%!error <POSITION must be> validatestring ("xyz", {"xyz"}, "3", "4", -5)
+