changeset 20166:196871335aa8

Allow call with empty argument list in strcat related functions (bug #44981) * libinterp/corefcn/strfns.cc (strvcat): return an empty string for an empty argument list. Simply dropping the input checking, will return an empty string. This makes it more consistent with cat(), vertcat, and horzcat() functions, which return [] for this cases. It makes it easier to support "strcat (cell{:})" when cell is empty. * scripts/strings/cstrcat.m, scripts/strings/strcat.m: same as above. But because [cellstr{:}] when cellstr is empty returns double ([]), we specifically return "".
author Carnë Draug <carandraug@octave.org>
date Fri, 01 May 2015 16:21:39 +0100
parents 65e22ba879f0
children b369c6dcacb4
files libinterp/corefcn/strfns.cc scripts/strings/cstrcat.m scripts/strings/strcat.m
diffstat 3 files changed, 58 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/strfns.cc	Sun May 03 22:52:07 2015 +0100
+++ b/libinterp/corefcn/strfns.cc	Fri May 01 16:21:39 2015 +0100
@@ -209,78 +209,70 @@
   octave_value retval;
 
   int nargin = args.length ();
-
-  if (nargin > 0)
-    {
-      int n_elts = 0;
-
-      size_t max_len = 0;
-
-      std::queue<string_vector> args_as_strings;
+  int n_elts = 0;
+  size_t max_len = 0;
+  std::queue<string_vector> args_as_strings;
 
-      for (int i = 0; i < nargin; i++)
-        {
-          string_vector s = args(i).all_strings ();
-
-          if (error_state)
-            {
-              error ("strvcat: unable to convert some args to strings");
-              return retval;
-            }
+  for (int i = 0; i < nargin; i++)
+    {
+      string_vector s = args(i).all_strings ();
 
-          size_t n = s.length ();
+      if (error_state)
+        {
+          error ("strvcat: unable to convert some args to strings");
+          return retval;
+        }
 
-          // do not count empty strings in calculation of number of elements
-          if (n > 0)
+      size_t n = s.length ();
+
+      // do not count empty strings in calculation of number of elements
+      if (n > 0)
+        {
+          for (size_t j = 0; j < n; j++)
             {
-              for (size_t j = 0; j < n; j++)
-                {
-                  if (s[j].length () > 0)
-                    n_elts++;
-                }
+              if (s[j].length () > 0)
+                n_elts++;
             }
-
-          size_t s_max_len = s.max_length ();
-
-          if (s_max_len > max_len)
-            max_len = s_max_len;
-
-          args_as_strings.push (s);
         }
 
-      string_vector result (n_elts);
+      size_t s_max_len = s.max_length ();
+
+      if (s_max_len > max_len)
+        max_len = s_max_len;
+
+      args_as_strings.push (s);
+    }
+
+  string_vector result (n_elts);
 
-      octave_idx_type k = 0;
+  octave_idx_type k = 0;
 
-      for (int i = 0; i < nargin; i++)
+  for (int i = 0; i < nargin; i++)
+    {
+      string_vector s = args_as_strings.front ();
+      args_as_strings.pop ();
+
+      size_t n = s.length ();
+
+      if (n > 0)
         {
-          string_vector s = args_as_strings.front ();
-          args_as_strings.pop ();
-
-          size_t n = s.length ();
-
-          if (n > 0)
+          for (size_t j = 0; j < n; j++)
             {
-              for (size_t j = 0; j < n; j++)
+              std::string t = s[j];
+              if (t.length () > 0)
                 {
-                  std::string t = s[j];
-                  if (t.length () > 0)
-                    {
-                      size_t t_len = t.length ();
+                  size_t t_len = t.length ();
 
-                      if (max_len > t_len)
-                        t += std::string (max_len - t_len, ' ');
+                  if (max_len > t_len)
+                    t += std::string (max_len - t_len, ' ');
 
-                      result[k++] = t;
-                    }
+                  result[k++] = t;
                 }
             }
         }
+    }
 
-      retval = octave_value (result, '\'');
-    }
-  else
-    print_usage ();
+  retval = octave_value (result, '\'');
 
   return retval;
 }
@@ -297,8 +289,7 @@
 %!assert (strvcat ({100,{100, {""}}}), ["d";"d"])
 %!assert (strvcat (["a";"be"], {"c", 100}), ["a";"be";"c";"d"])
 %!assert (strvcat ("a", "bb", "ccc"), ["a  "; "bb "; "ccc"])
-
-%!error strvcat ()
+%!assert (strvcat (), "")
 */
 
 
--- a/scripts/strings/cstrcat.m	Sun May 03 22:52:07 2015 +0100
+++ b/scripts/strings/cstrcat.m	Fri May 01 16:21:39 2015 +0100
@@ -43,14 +43,16 @@
 
 function st = cstrcat (varargin)
 
-  if (nargin < 1)
-    print_usage ();
+  if (nargin == 0)
+    ## Special because if varargin is empty, iscellstr still returns
+    ## true but then "[varargin{:}]" would be of class double.
+    st = "";
   elseif (! iscellstr (varargin))
+    st = [varargin{:}];
+  else
     error ("cstrcat: expecting arguments to character strings");
   endif
 
-  st = [varargin{:}];
-
 endfunction
 
 
@@ -63,7 +65,8 @@
 %!assert (cstrcat ("foo", "bar"), "foobar")
 %!assert (cstrcat (["a"; "bb"], ["foo"; "bar"]), ["a foo"; "bbbar"])
 
+%!assert (cstrcat (), "")
+
 ## Test input validation
-%!error cstrcat ()
 %!error cstrcat (1, 2)
 
--- a/scripts/strings/strcat.m	Sun May 03 22:52:07 2015 +0100
+++ b/scripts/strings/strcat.m	Fri May 01 16:21:39 2015 +0100
@@ -81,10 +81,8 @@
 function st = strcat (varargin)
 
   if (nargin == 0)
-    print_usage ();
-  endif
-
-  if (nargin == 1)
+    st = "";
+  elseif (nargin == 1)
     st = varargin{1};
   else
     ## Convert to cells of strings
@@ -148,5 +146,5 @@
 %!assert (strcat (1, 2), strcat (char (1), char (2)))
 %!assert (strcat ("", 2), strcat ([], char (2)))
 
-%!error strcat ()
+%!assert (strcat (), "")