changeset 10086:76df75b10c80

allow more cells in strfind/strrep + supply a general mechanism
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 12 Jan 2010 09:03:42 +0100
parents 82d47b706424
children 090173f2db40
files src/ChangeLog src/DLD-FUNCTIONS/strfind.cc src/oct-obj.cc src/oct-obj.h src/utils.cc src/utils.h
diffstat 6 files changed, 139 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/ChangeLog	Tue Jan 12 09:03:42 2010 +0100
@@ -1,3 +1,12 @@
+2010-01-12  Jaroslav Hajek  <highegg@gmail.com>
+
+	* oct-obj.cc (octave_value_list::any_cell): New method.
+	* oct-obj.h: Declare it.
+	* utils.cc (do_simple_cellfun): New overloaded function.
+	* utils.h: Declare it.
+	* DLD-FUNCTIONS/strfind.cc (Fstrfind): Call it here.
+	(Fstrrep): Also here.
+
 2010-01-11  Rik <octave@nomad.inbox5.com>
 
 	* Makefile.am: Update DOCSTRINGS rules to avoid simple_move_if_change_rule
--- a/src/DLD-FUNCTIONS/strfind.cc	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/DLD-FUNCTIONS/strfind.cc	Tue Jan 12 09:03:42 2010 +0100
@@ -151,10 +151,10 @@
 
   if (nargin == 2)
     {
-      octave_value argstr = args(0), argp = args(1);
-      if (argp.is_string ())
+      octave_value argstr = args(0), argpat = args(1);
+      if (argpat.is_string ())
         {
-          Array<char> needle = argp.char_array_value ();
+          Array<char> needle = argpat.char_array_value ();
           OCTAVE_LOCAL_BUFFER (octave_idx_type, table, UCHAR_MAX);
           qs_preprocess (needle, table);
 
@@ -185,8 +185,10 @@
           else
             error ("strfind: first argument must be a string or cell array of strings");
         }
+      else if (argpat.is_cell ())
+        retval = do_simple_cellfun (Fstrfind, "strfind", args);
       else
-        error ("strfind: pattern must be a string");
+        error ("strfind: pattern must be a string or cell array of strings");
     }
   else
     print_usage ();
@@ -269,11 +271,11 @@
 
   if (nargin == 3)
     {
-      octave_value argstr = args(0), argp = args(1), argr = args(2);
-      if (argp.is_string () && argr.is_string ())
+      octave_value argstr = args(0), argpat = args(1), argrep = args(2);
+      if (argpat.is_string () && argrep.is_string ())
         {
-          const Array<char> pat = argp.char_array_value ();
-          const Array<char> rep = argr.char_array_value ();
+          const Array<char> pat = argpat.char_array_value ();
+          const Array<char> rep = argrep.char_array_value ();
 
           OCTAVE_LOCAL_BUFFER (octave_idx_type, table, UCHAR_MAX);
           qs_preprocess (pat, table);
@@ -303,8 +305,10 @@
           else
             error ("strrep: first argument must be a string or cell array of strings");
         }
+      else if (argpat.is_cell () || argrep.is_cell ())
+        retval = do_simple_cellfun (Fstrrep, "strrep", args);
       else
-        error ("strrep: 2rd and 3rd arguments must be strings");
+        error ("strrep: x and y arguments must be strings or cell arrays of strings");
     }
   else
     print_usage ();
--- a/src/oct-obj.cc	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/oct-obj.cc	Tue Jan 12 09:03:42 2010 +0100
@@ -188,6 +188,19 @@
 }
 
 bool
+octave_value_list::any_cell (void) const
+{
+  bool retval = false;
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    if (retval = elem (i).is_cell ())
+      break;
+  
+  return retval;
+}
+
+bool
 octave_value_list::has_magic_colon (void) const
 {
   octave_idx_type n = length ();
--- a/src/oct-obj.h	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/oct-obj.h	Tue Jan 12 09:03:42 2010 +0100
@@ -137,6 +137,8 @@
 
   bool all_scalars (void) const;
 
+  bool any_cell (void) const;
+
   bool has_magic_colon (void) const;
 
   string_vector make_argv (const std::string& = std::string()) const;
--- a/src/utils.cc	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/utils.cc	Tue Jan 12 09:03:42 2010 +0100
@@ -1397,6 +1397,98 @@
   return retval;
 }
 
+octave_value_list
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args, 
+                   int nargout)
+{
+  octave_value_list new_args = args, retval;
+  int nargin = args.length ();
+  OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);
+  OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);
+  OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);
+
+  const Cell *ccells = cells;
+
+  octave_idx_type numel = 1;
+  dim_vector dims (1, 1);
+
+  for (int i = 0; i < nargin; i++)
+    {
+      octave_value arg = new_args(i);
+      iscell[i] = arg.is_cell ();
+      if (iscell[i])
+        {
+          cells[i] = arg.cell_value ();
+          octave_idx_type n = ccells[i].numel ();
+          if (n == 1)
+            { 
+              iscell[i] = false;
+              new_args(i) = ccells[i](0);
+            }
+          else if (numel == 1)
+            {
+              numel = n;
+              dims = ccells[i].dims ();
+            } 
+          else if (dims != ccells[i].dims ())
+            {
+              error ("%s: cell arguments must have matching sizes", fun_name);
+              break;
+            }
+        }
+    }
+
+  if (! error_state)
+    {
+      for (int i = 0; i < nargout; i++)
+        rcells[i].clear (dims);
+
+      for (octave_idx_type j = 0; j < numel; j++)
+        {
+          for (int i = 0; i < nargin; i++)
+            if (iscell[i])
+              new_args(i) = ccells[i](j);
+
+          OCTAVE_QUIT;
+
+          const octave_value_list tmp = fun (new_args, nargout);
+
+          if (tmp.length () < nargout)
+            {
+              error ("%s: do_simple_cellfun: internal error", fun_name);
+              break;
+            }
+          else
+            {
+              for (int i = 0; i < nargout; i++)
+                rcells[i](j) = tmp(i);
+            }
+        }
+    }
+
+  if (! error_state)
+    {
+      retval.resize (nargout);
+      for (int i = 0; i < nargout; i++)
+        retval(i) = rcells[i];
+    }
+
+  return retval;
+}
+
+octave_value
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args)
+{
+  octave_value retval;
+  const octave_value_list tmp = do_simple_cellfun (fun, fun_name, args, 1);
+  if (tmp.length () > 0)
+    retval = tmp(0);
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/utils.h	Mon Jan 11 22:38:08 2010 -0800
+++ b/src/utils.h	Tue Jan 12 09:03:42 2010 +0100
@@ -126,6 +126,16 @@
 extern "C" OCTINTERP_API int
 octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args);
 
+extern OCTINTERP_API
+octave_value_list
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args, 
+                   int nargout);
+
+extern OCTINTERP_API
+octave_value
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args);
 #endif
 
 /*