GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
strfns.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cctype>
28 
29 #include <queue>
30 #include <sstream>
31 
32 #include "dMatrix.h"
33 
34 #include "Cell.h"
35 #include "defun.h"
36 #include "error.h"
37 #include "gripes.h"
38 #include "ov.h"
39 #include "oct-obj.h"
40 #include "unwind-prot.h"
41 #include "utils.h"
42 
43 DEFUN (char, args, ,
44  "-*- texinfo -*-\n\
45 @deftypefn {Built-in Function} {} char (@var{x})\n\
46 @deftypefnx {Built-in Function} {} char (@var{x}, @dots{})\n\
47 @deftypefnx {Built-in Function} {} char (@var{s1}, @var{s2}, @dots{})\n\
48 @deftypefnx {Built-in Function} {} char (@var{cell_array})\n\
49 Create a string array from one or more numeric matrices, character\n\
50 matrices, or cell arrays.\n\
51 \n\
52 Arguments are concatenated vertically. The returned values are padded with\n\
53 blanks as needed to make each row of the string array have the same length.\n\
54 Empty input strings are significant and will concatenated in the output.\n\
55 \n\
56 For numerical input, each element is converted to the corresponding ASCII\n\
57 character. A range error results if an input is outside the ASCII range\n\
58 (0-255).\n\
59 \n\
60 For cell arrays, each element is concatenated separately. Cell arrays\n\
61 converted through @code{char} can mostly be converted back with\n\
62 @code{cellstr}. For example:\n\
63 \n\
64 @example\n\
65 @group\n\
66 char ([97, 98, 99], \"\", @{\"98\", \"99\", 100@}, \"str1\", [\"ha\", \"lf\"])\n\
67  @result{} [\"abc \"\n\
68  \" \"\n\
69  \"98 \"\n\
70  \"99 \"\n\
71  \"d \"\n\
72  \"str1 \"\n\
73  \"half \"]\n\
74 @end group\n\
75 @end example\n\
76 @seealso{strvcat, cellstr}\n\
77 @end deftypefn")
78 {
79  octave_value retval;
80 
81  int nargin = args.length ();
82 
83  if (nargin == 0)
84  retval = "";
85  else if (nargin == 1)
86  retval = args(0).convert_to_str (true, true,
87  args(0).is_dq_string () ? '"' : '\'');
88  else
89  {
90  int n_elts = 0;
91 
92  int max_len = 0;
93 
94  std::queue<string_vector> args_as_strings;
95 
96  for (int i = 0; i < nargin; i++)
97  {
98  string_vector s = args(i).all_strings ();
99 
100  if (error_state)
101  {
102  error ("char: unable to convert some args to strings");
103  return retval;
104  }
105 
106  if (s.length () > 0)
107  n_elts += s.length ();
108  else
109  n_elts += 1;
110 
111  int s_max_len = s.max_length ();
112 
113  if (s_max_len > max_len)
114  max_len = s_max_len;
115 
116  args_as_strings.push (s);
117  }
118 
119  string_vector result (n_elts);
120 
121  int k = 0;
122 
123  for (int i = 0; i < nargin; i++)
124  {
125  string_vector s = args_as_strings.front ();
126  args_as_strings.pop ();
127 
128  int n = s.length ();
129 
130  if (n > 0)
131  {
132  for (int j = 0; j < n; j++)
133  {
134  std::string t = s[j];
135  int t_len = t.length ();
136 
137  if (max_len > t_len)
138  t += std::string (max_len - t_len, ' ');
139 
140  result[k++] = t;
141  }
142  }
143  else
144  result[k++] = std::string (max_len, ' ');
145  }
146 
147  retval = octave_value (result, '\'');
148  }
149 
150  return retval;
151 }
152 
153 /*
154 %!assert (char (), '');
155 %!assert (char (100), "d");
156 %!assert (char (100,100), ["d";"d"])
157 %!assert (char ({100,100}), ["d";"d"])
158 %!assert (char ([100,100]), ["dd"])
159 %!assert (char ({100,{100}}), ["d";"d"])
160 %!assert (char (100, [], 100), ["d";" ";"d"])
161 %!assert (char ({100, [], 100}), ["d";" ";"d"])
162 %!assert (char ({100,{100, {""}}}), ["d";"d";" "])
163 %!assert (char (["a";"be"], {"c", 100}), ["a";"be";"c";"d"])
164 %!assert (char ("a", "bb", "ccc"), ["a "; "bb "; "ccc"])
165 %!assert (char ([65, 83, 67, 73, 73]), "ASCII")
166 
167 %!test
168 %! x = char ("foo", "bar", "foobar");
169 %! assert (x(1,:), "foo ");
170 %! assert (x(2,:), "bar ");
171 %! assert (x(3,:), "foobar");
172 */
173 
174 DEFUN (strvcat, args, ,
175  "-*- texinfo -*-\n\
176 @deftypefn {Built-in Function} {} strvcat (@var{x})\n\
177 @deftypefnx {Built-in Function} {} strvcat (@var{x}, @dots{})\n\
178 @deftypefnx {Built-in Function} {} strvcat (@var{s1}, @var{s2}, @dots{})\n\
179 @deftypefnx {Built-in Function} {} strvcat (@var{cell_array})\n\
180 Create a character array from one or more numeric matrices, character\n\
181 matrices, or cell arrays.\n\
182 \n\
183 Arguments are concatenated vertically. The returned values are padded with\n\
184 blanks as needed to make each row of the string array have the same length.\n\
185 Unlike @code{char}, empty strings are removed and will not appear in the\n\
186 output.\n\
187 \n\
188 For numerical input, each element is converted to the corresponding ASCII\n\
189 character. A range error results if an input is outside the ASCII range\n\
190 (0-255).\n\
191 \n\
192 For cell arrays, each element is concatenated separately. Cell arrays\n\
193 converted through @code{strvcat} can mostly be converted back with\n\
194 @code{cellstr}. For example:\n\
195 \n\
196 @example\n\
197 @group\n\
198 strvcat ([97, 98, 99], \"\", @{\"98\", \"99\", 100@}, \"str1\", [\"ha\", \"lf\"])\n\
199  @result{} [\"abc \"\n\
200  \"98 \"\n\
201  \"99 \"\n\
202  \"d \"\n\
203  \"str1 \"\n\
204  \"half \"]\n\
205 @end group\n\
206 @end example\n\
207 @seealso{char, strcat, cstrcat}\n\
208 @end deftypefn")
209 {
210  octave_value retval;
211 
212  int nargin = args.length ();
213 
214  if (nargin > 0)
215  {
216  int n_elts = 0;
217 
218  size_t max_len = 0;
219 
220  std::queue<string_vector> args_as_strings;
221 
222  for (int i = 0; i < nargin; i++)
223  {
224  string_vector s = args(i).all_strings ();
225 
226  if (error_state)
227  {
228  error ("strvcat: unable to convert some args to strings");
229  return retval;
230  }
231 
232  size_t n = s.length ();
233 
234  // do not count empty strings in calculation of number of elements
235  if (n > 0)
236  {
237  for (size_t j = 0; j < n; j++)
238  {
239  if (s[j].length () > 0)
240  n_elts++;
241  }
242  }
243 
244  size_t s_max_len = s.max_length ();
245 
246  if (s_max_len > max_len)
247  max_len = s_max_len;
248 
249  args_as_strings.push (s);
250  }
251 
252  string_vector result (n_elts);
253 
254  octave_idx_type k = 0;
255 
256  for (int i = 0; i < nargin; i++)
257  {
258  string_vector s = args_as_strings.front ();
259  args_as_strings.pop ();
260 
261  size_t n = s.length ();
262 
263  if (n > 0)
264  {
265  for (size_t j = 0; j < n; j++)
266  {
267  std::string t = s[j];
268  if (t.length () > 0)
269  {
270  size_t t_len = t.length ();
271 
272  if (max_len > t_len)
273  t += std::string (max_len - t_len, ' ');
274 
275  result[k++] = t;
276  }
277  }
278  }
279  }
280 
281  retval = octave_value (result, '\'');
282  }
283  else
284  print_usage ();
285 
286  return retval;
287 }
288 
289 /*
290 %!assert (strvcat (""), "");
291 %!assert (strvcat (100) == "d");
292 %!assert (strvcat (100,100), ["d";"d"])
293 %!assert (strvcat ({100,100}), ["d";"d"])
294 %!assert (strvcat ([100,100]), ["dd"])
295 %!assert (strvcat ({100,{100}}), ["d";"d"])
296 %!assert (strvcat (100, [], 100), ["d";"d"])
297 %!assert (strvcat ({100, [], 100}), ["d";"d"])
298 %!assert (strvcat ({100,{100, {""}}}), ["d";"d"])
299 %!assert (strvcat (["a";"be"], {"c", 100}), ["a";"be";"c";"d"])
300 %!assert (strvcat ("a", "bb", "ccc"), ["a "; "bb "; "ccc"])
301 
302 %!error strvcat ()
303 */
304 
305 
306 DEFUN (ischar, args, ,
307  "-*- texinfo -*-\n\
308 @deftypefn {Built-in Function} {} ischar (@var{x})\n\
309 Return true if @var{x} is a character array.\n\
310 @seealso{isfloat, isinteger, islogical, isnumeric, iscellstr, isa}\n\
311 @end deftypefn")
312 {
313  octave_value retval;
314 
315  int nargin = args.length ();
316 
317  if (nargin == 1 && args(0).is_defined ())
318  retval = args(0).is_string ();
319  else
320  print_usage ();
321 
322  return retval;
323 }
324 
325 /*
326 %!assert (ischar ("a"), true)
327 %!assert (ischar (["ab";"cd"]), true)
328 %!assert (ischar ({"ab"}), false)
329 %!assert (ischar (1), false)
330 %!assert (ischar ([1, 2]), false)
331 %!assert (ischar ([]), false)
332 %!assert (ischar ([1, 2; 3, 4]), false)
333 %!assert (ischar (""), true)
334 %!assert (ischar ("test"), true)
335 %!assert (ischar (["test"; "ing"]), true)
336 %!assert (ischar (struct ("foo", "bar")), false)
337 
338 %!error ischar ()
339 %!error ischar ("test", 1)
340 */
341 
342 static octave_value
343 do_strcmp_fun (const octave_value& arg0, const octave_value& arg1,
344  octave_idx_type n, const char *fcn_name,
345  bool (*array_op) (const charNDArray&, const charNDArray&,
347  bool (*str_op) (const std::string&, const std::string&,
349 
350 {
351  octave_value retval;
352 
353  bool s1_string = arg0.is_string ();
354  bool s1_cell = arg0.is_cell ();
355  bool s2_string = arg1.is_string ();
356  bool s2_cell = arg1.is_cell ();
357 
358  if (s1_string && s2_string)
359  retval = array_op (arg0.char_array_value (), arg1.char_array_value (), n);
360  else if ((s1_string && s2_cell) || (s1_cell && s2_string))
361  {
362  octave_value str_val, cell_val;
363 
364  if (s1_string)
365  {
366  str_val = arg0;
367  cell_val = arg1;
368  }
369  else
370  {
371  str_val = arg1;
372  cell_val = arg0;
373  }
374 
375  const Cell cell = cell_val.cell_value ();
376  const string_vector str = str_val.all_strings ();
377  octave_idx_type r = str.length ();
378 
379  if (r == 0 || r == 1)
380  {
381  // Broadcast the string.
382 
383  boolNDArray output (cell_val.dims (), false);
384 
385  std::string s = r == 0 ? std::string () : str[0];
386 
387  if (cell_val.is_cellstr ())
388  {
389  const Array<std::string> cellstr = cell_val.cellstr_value ();
390  for (octave_idx_type i = 0; i < cellstr.length (); i++)
391  output(i) = str_op (cellstr(i), s, n);
392  }
393  else
394  {
395  // FIXME: should we warn here?
396  for (octave_idx_type i = 0; i < cell.length (); i++)
397  {
398  if (cell(i).is_string ())
399  output(i) = str_op (cell(i).string_value (), s, n);
400  }
401  }
402 
403  retval = output;
404  }
405  else if (r > 1)
406  {
407  if (cell.length () == 1)
408  {
409  // Broadcast the cell.
410 
411  const dim_vector dv (r, 1);
412  boolNDArray output (dv, false);
413 
414  if (cell(0).is_string ())
415  {
416  const std::string str2 = cell(0).string_value ();
417 
418  for (octave_idx_type i = 0; i < r; i++)
419  output(i) = str_op (str[i], str2, n);
420  }
421 
422  retval = output;
423  }
424  else
425  {
426  // Must match in all dimensions.
427 
428  boolNDArray output (cell.dims (), false);
429 
430  if (cell.length () == r)
431  {
432  if (cell_val.is_cellstr ())
433  {
434  const Array<std::string> cellstr
435  = cell_val.cellstr_value ();
436  for (octave_idx_type i = 0; i < cellstr.length (); i++)
437  output(i) = str_op (str[i], cellstr(i), n);
438  }
439  else
440  {
441  // FIXME: should we warn here?
442  for (octave_idx_type i = 0; i < r; i++)
443  {
444  if (cell(i).is_string ())
445  output(i) = str_op (str[i],
446  cell(i).string_value (), n);
447  }
448  }
449 
450  retval = output;
451  }
452  else
453  retval = false;
454  }
455  }
456  }
457  else if (s1_cell && s2_cell)
458  {
459  octave_value cell1_val, cell2_val;
460  octave_idx_type r1 = arg0.numel (), r2;
461 
462  if (r1 == 1)
463  {
464  // Make the singleton cell2.
465 
466  cell1_val = arg1;
467  cell2_val = arg0;
468  }
469  else
470  {
471  cell1_val = arg0;
472  cell2_val = arg1;
473  }
474 
475  const Cell cell1 = cell1_val.cell_value ();
476  const Cell cell2 = cell2_val.cell_value ();
477  r1 = cell1.numel ();
478  r2 = cell2.numel ();
479 
480  const dim_vector size1 = cell1.dims ();
481  const dim_vector size2 = cell2.dims ();
482 
483  boolNDArray output (size1, false);
484 
485  if (r2 == 1)
486  {
487  // Broadcast cell2.
488 
489  if (cell2(0).is_string ())
490  {
491  const std::string str2 = cell2(0).string_value ();
492 
493  if (cell1_val.is_cellstr ())
494  {
495  const Array<std::string> cellstr = cell1_val.cellstr_value ();
496  for (octave_idx_type i = 0; i < cellstr.length (); i++)
497  output(i) = str_op (cellstr(i), str2, n);
498  }
499  else
500  {
501  // FIXME: should we warn here?
502  for (octave_idx_type i = 0; i < r1; i++)
503  {
504  if (cell1(i).is_string ())
505  {
506  const std::string str1 = cell1(i).string_value ();
507  output(i) = str_op (str1, str2, n);
508  }
509  }
510  }
511  }
512  }
513  else
514  {
515  if (size1 != size2)
516  {
517  error ("%s: nonconformant cell arrays", fcn_name);
518  return retval;
519  }
520 
521  if (cell1.is_cellstr () && cell2.is_cellstr ())
522  {
523  const Array<std::string> cellstr1 = cell1_val.cellstr_value ();
524  const Array<std::string> cellstr2 = cell2_val.cellstr_value ();
525  for (octave_idx_type i = 0; i < r1; i++)
526  output (i) = str_op (cellstr1(i), cellstr2(i), n);
527  }
528  else
529  {
530  // FIXME: should we warn here?
531  for (octave_idx_type i = 0; i < r1; i++)
532  {
533  if (cell1(i).is_string () && cell2(i).is_string ())
534  {
535  const std::string str1 = cell1(i).string_value ();
536  const std::string str2 = cell2(i).string_value ();
537  output(i) = str_op (str1, str2, n);
538  }
539  }
540  }
541  }
542 
543  retval = output;
544  }
545  else
546  retval = false;
547 
548  return retval;
549 }
550 
551 // If both args are arrays, dimensions may be significant.
552 static bool
554 {
555  return (s1.dims () == s2.dims ()
556  && std::equal (s1.data (), s1.data () + s1.numel (), s2.data ()));
557 }
558 
559 // Otherwise, just use strings.
560 static bool
561 strcmp_str_op (const std::string& s1, const std::string& s2,
563 {
564  return s1 == s2;
565 }
566 
567 DEFUN (strcmp, args, ,
568  "-*- texinfo -*-\n\
569 @deftypefn {Built-in Function} {} strcmp (@var{s1}, @var{s2})\n\
570 Return 1 if the character strings @var{s1} and @var{s2} are the same,\n\
571 and 0 otherwise.\n\
572 \n\
573 If either @var{s1} or @var{s2} is a cell array of strings, then an array\n\
574 of the same size is returned, containing the values described above for\n\
575 every member of the cell array. The other argument may also be a cell\n\
576 array of strings (of the same size or with only one element), char matrix\n\
577 or character string.\n\
578 \n\
579 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmp\n\
580 function returns 1 if the character strings are equal, and 0 otherwise.\n\
581 This is just the opposite of the corresponding C library function.\n\
582 @seealso{strcmpi, strncmp, strncmpi}\n\
583 @end deftypefn")
584 {
585  octave_value retval;
586 
587  if (args.length () == 2)
588  {
589  retval = do_strcmp_fun (args(0), args(1), 0,
590  "strcmp", strcmp_array_op, strcmp_str_op);
591  }
592  else
593  print_usage ();
594 
595  return retval;
596 }
597 
598 /*
599 %!shared x
600 %! x = char (zeros (0, 2));
601 %!assert (strcmp ("", x), false)
602 %!assert (strcmp (x, ""), false)
603 %!assert (strcmp (x, x), true)
604 ## %!assert (strcmp ({""}, x), true)
605 ## %!assert (strcmp ({x}, ""), false)
606 ## %!assert (strcmp ({x}, x), true)
607 ## %!assert (strcmp ("", {x}), false)
608 ## %!assert (strcmp (x, {""}), false)
609 ## %!assert (strcmp (x, {x}), true)
610 ## %!assert (strcmp ({x; x}, ""), [false; false])
611 ## %!assert (strcmp ({x; x}, {""}), [false; false])
612 ## %!assert (strcmp ("", {x; x}), [false; false])
613 ## %!assert (strcmp ({""}, {x; x}), [false; false])
614 %!assert (strcmp ({"foo"}, x), false)
615 %!assert (strcmp ({"foo"}, "foo"), true)
616 %!assert (strcmp ({"foo"}, x), false)
617 %!assert (strcmp (x, {"foo"}), false)
618 %!assert (strcmp ("foo", {"foo"}), true)
619 %!assert (strcmp (x, {"foo"}), false)
620 %!shared y
621 %! y = char (zeros (2, 0));
622 %!assert (strcmp ("", y), false)
623 %!assert (strcmp (y, ""), false)
624 %!assert (strcmp (y, y), true)
625 %!assert (strcmp ({""}, y), [true; true])
626 %!assert (strcmp ({y}, ""), true)
627 %!assert (strcmp ({y}, y), [true; true])
628 %!assert (strcmp ("", {y}), true)
629 %!assert (strcmp (y, {""}), [true; true])
630 %!assert (strcmp (y, {y}), [true; true])
631 %!assert (strcmp ({y; y}, ""), [true; true])
632 %!assert (strcmp ({y; y}, {""}), [true; true])
633 %!assert (strcmp ("", {y; y}), [true; true])
634 %!assert (strcmp ({""}, {y; y}), [true; true])
635 %!assert (strcmp ({"foo"}, y), [false; false])
636 %!assert (strcmp ({"foo"}, y), [false; false])
637 %!assert (strcmp (y, {"foo"}), [false; false])
638 %!assert (strcmp (y, {"foo"}), [false; false])
639 %!assert (strcmp ("foobar", "foobar"), true)
640 %!assert (strcmp ("fooba", "foobar"), false)
641 
642 %!error strcmp ()
643 %!error strcmp ("foo", "bar", 3)
644 */
645 
646 // Apparently, Matlab ignores the dims with strncmp. It also
647 static bool
649  octave_idx_type n)
650 {
651  octave_idx_type l1 = s1.numel ();
652  octave_idx_type l2 = s2.numel ();
653  return (n > 0 && n <= l1 && n <= l2
654  && std::equal (s1.data (), s1.data () + n, s2.data ()));
655 }
656 
657 // Otherwise, just use strings. Note that we neither extract substrings (which
658 // would mean a copy, at least in GCC), nor use string::compare (which is a
659 // 3-way compare).
660 static bool
661 strncmp_str_op (const std::string& s1, const std::string& s2, octave_idx_type n)
662 {
663  octave_idx_type l1 = s1.length ();
664  octave_idx_type l2 = s2.length ();
665  return (n > 0 && n <= l1 && n <= l2
666  && std::equal (s1.data (), s1.data () + n, s2.data ()));
667 }
668 
669 DEFUN (strncmp, args, ,
670  "-*- texinfo -*-\n\
671 @deftypefn {Built-in Function} {} strncmp (@var{s1}, @var{s2}, @var{n})\n\
672 Return 1 if the first @var{n} characters of strings @var{s1} and @var{s2} are\n\
673 the same, and 0 otherwise.\n\
674 \n\
675 @example\n\
676 @group\n\
677 strncmp (\"abce\", \"abcd\", 3)\n\
678  @result{} 1\n\
679 @end group\n\
680 @end example\n\
681 \n\
682 If either @var{s1} or @var{s2} is a cell array of strings, then an array\n\
683 of the same size is returned, containing the values described above for\n\
684 every member of the cell array. The other argument may also be a cell\n\
685 array of strings (of the same size or with only one element), char matrix\n\
686 or character string.\n\
687 \n\
688 @example\n\
689 @group\n\
690 strncmp (\"abce\", @{\"abcd\", \"bca\", \"abc\"@}, 3)\n\
691  @result{} [1, 0, 1]\n\
692 @end group\n\
693 @end example\n\
694 \n\
695 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmp\n\
696 function returns 1 if the character strings are equal, and 0 otherwise.\n\
697 This is just the opposite of the corresponding C library function.\n\
698 @seealso{strncmpi, strcmp, strcmpi}\n\
699 @end deftypefn")
700 {
701  octave_value retval;
702 
703  if (args.length () == 3)
704  {
705  octave_idx_type n = args(2).idx_type_value ();
706 
707  if (! error_state)
708  {
709  if (n > 0)
710  {
711  retval = do_strcmp_fun (args(0), args(1), n, "strncmp",
713  }
714  else
715  error ("strncmp: N must be greater than 0");
716  }
717  }
718  else
719  print_usage ();
720 
721  return retval;
722 }
723 
724 /*
725 %!assert (strncmp ("abce", "abc", 3), true)
726 %!assert (strncmp (100, 100, 1), false)
727 %!assert (strncmp ("abce", {"abcd", "bca", "abc"}, 3), logical ([1, 0, 1]))
728 %!assert (strncmp ("abc", {"abcd", "bca", "abc"}, 4), logical ([0, 0, 0]))
729 %!assert (strncmp ({"abcd", "bca", "abc"},"abce", 3), logical ([1, 0, 1]))
730 %!assert (strncmp ({"abcd", "bca", "abc"},{"abcd", "bca", "abe"}, 3), logical ([1, 1, 0]))
731 %!assert (strncmp ("abc", {"abcd", 10}, 2), logical ([1, 0]))
732 
733 %!error strncmp ()
734 %!error strncmp ("abc", "def")
735 */
736 
737 // case-insensitive character equality functor
738 struct icmp_char_eq : public std::binary_function<char, char, bool>
739 {
740  bool operator () (char x, char y) const
741  { return std::toupper (x) == std::toupper (y); }
742 };
743 
744 // strcmpi is equivalent to strcmp in that it checks all dims.
745 static bool
747 {
748  return (s1.dims () == s2.dims ()
749  && std::equal (s1.data (), s1.data () + s1.numel (), s2.data (),
750  icmp_char_eq ()));
751 }
752 
753 // Ditto for string.
754 static bool
755 strcmpi_str_op (const std::string& s1, const std::string& s2,
757 {
758  return (s1.size () == s2.size ()
759  && std::equal (s1.data (), s1.data () + s1.size (), s2.data (),
760  icmp_char_eq ()));
761 }
762 
763 DEFUNX ("strcmpi", Fstrcmpi, args, ,
764  "-*- texinfo -*-\n\
765 @deftypefn {Built-in Function} {} strcmpi (@var{s1}, @var{s2})\n\
766 Return 1 if the character strings @var{s1} and @var{s2} are the same,\n\
767 disregarding case of alphabetic characters, and 0 otherwise.\n\
768 \n\
769 If either @var{s1} or @var{s2} is a cell array of strings, then an array\n\
770 of the same size is returned, containing the values described above for\n\
771 every member of the cell array. The other argument may also be a cell\n\
772 array of strings (of the same size or with only one element), char matrix\n\
773 or character string.\n\
774 \n\
775 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmp\n\
776 function returns 1 if the character strings are equal, and 0 otherwise.\n\
777 This is just the opposite of the corresponding C library function.\n\
778 \n\
779 @strong{Caution:} National alphabets are not supported.\n\
780 @seealso{strcmp, strncmp, strncmpi}\n\
781 @end deftypefn")
782 {
783  octave_value retval;
784 
785  if (args.length () == 2)
786  {
787  retval = do_strcmp_fun (args(0), args(1), 0,
788  "strcmpi", strcmpi_array_op, strcmpi_str_op);
789  }
790  else
791  print_usage ();
792 
793  return retval;
794 }
795 
796 /*
797 %!assert (strcmpi ("abc123", "ABC123"), true)
798 */
799 
800 // Like strncmp.
801 static bool
803  octave_idx_type n)
804 {
805  octave_idx_type l1 = s1.numel ();
806  octave_idx_type l2 = s2.numel ();
807  return (n > 0 && n <= l1 && n <= l2
808  && std::equal (s1.data (), s1.data () + n, s2.data (),
809  icmp_char_eq ()));
810 }
811 
812 // Ditto.
813 static bool
814 strncmpi_str_op (const std::string& s1, const std::string& s2,
815  octave_idx_type n)
816 {
817  octave_idx_type l1 = s1.length ();
818  octave_idx_type l2 = s2.length ();
819  return (n > 0 && n <= l1 && n <= l2
820  && std::equal (s1.data (), s1.data () + n, s2.data (),
821  icmp_char_eq ()));
822 }
823 
824 DEFUNX ("strncmpi", Fstrncmpi, args, ,
825  "-*- texinfo -*-\n\
826 @deftypefn {Built-in Function} {} strncmpi (@var{s1}, @var{s2}, @var{n})\n\
827 Return 1 if the first @var{n} character of @var{s1} and @var{s2} are the\n\
828 same, disregarding case of alphabetic characters, and 0 otherwise.\n\
829 \n\
830 If either @var{s1} or @var{s2} is a cell array of strings, then an array\n\
831 of the same size is returned, containing the values described above for\n\
832 every member of the cell array. The other argument may also be a cell\n\
833 array of strings (of the same size or with only one element), char matrix\n\
834 or character string.\n\
835 \n\
836 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmpi\n\
837 function returns 1 if the character strings are equal, and 0 otherwise.\n\
838 This is just the opposite of the corresponding C library function.\n\
839 \n\
840 @strong{Caution:} National alphabets are not supported.\n\
841 @seealso{strncmp, strcmp, strcmpi}\n\
842 @end deftypefn")
843 {
844  octave_value retval;
845 
846  if (args.length () == 3)
847  {
848  octave_idx_type n = args(2).idx_type_value ();
849 
850  if (! error_state)
851  {
852  if (n > 0)
853  {
854  retval = do_strcmp_fun (args(0), args(1), n, "strncmpi",
856  }
857  else
858  error ("strncmpi: N must be greater than 0");
859  }
860  }
861  else
862  print_usage ();
863 
864  return retval;
865 }
866 
867 /*
868 %!assert (strncmpi ("abc123", "ABC456", 3), true)
869 */
870 
871 DEFUN (list_in_columns, args, ,
872  "-*- texinfo -*-\n\
873 @deftypefn {Built-in Function} {} list_in_columns (@var{arg}, @var{width}, @var{prefix})\n\
874 Return a string containing the elements of @var{arg} listed in columns with\n\
875 an overall maximum width of @var{width} and optional prefix @var{prefix}.\n\
876 \n\
877 The argument @var{arg} must be a cell array of character strings or a\n\
878 character array.\n\
879 \n\
880 If @var{width} is not specified or is an empty matrix, or less than or equal\n\
881 to zero, the width of the terminal screen is used. Newline characters are\n\
882 used to break the lines in the output string. For example:\n\
883 @c Set example in small font to prevent overfull line\n\
884 \n\
885 @smallexample\n\
886 @group\n\
887 list_in_columns (@{\"abc\", \"def\", \"ghijkl\", \"mnop\", \"qrs\", \"tuv\"@}, 20)\n\
888  @result{} abc mnop\n\
889  def qrs\n\
890  ghijkl tuv\n\
891 \n\
892 whos ans\n\
893  @result{}\n\
894  Variables in the current scope:\n\
895 \n\
896  Attr Name Size Bytes Class\n\
897  ==== ==== ==== ===== =====\n\
898  ans 1x37 37 char\n\
899 \n\
900  Total is 37 elements using 37 bytes\n\
901 @end group\n\
902 @end smallexample\n\
903 \n\
904 @seealso{terminal_size}\n\
905 @end deftypefn")
906 {
907  octave_value retval;
908 
909  int nargin = args.length ();
910 
911  if (nargin < 1 || nargin > 3)
912  {
913  print_usage ();
914  return retval;
915  }
916 
917  string_vector s = args(0).all_strings ();
918 
919  if (error_state)
920  {
921  error ("list_in_columns: ARG must be a cellstr or char array");
922  return retval;
923  }
924 
925  int width = -1;
926 
927  if (nargin > 1 && ! args(1).is_empty ())
928  {
929  width = args(1).int_value ();
930 
931  if (error_state)
932  {
933  error ("list_in_columns: WIDTH must be an integer");
934  return retval;
935  }
936  }
937 
938  std::string prefix;
939 
940  if (nargin > 2)
941  {
942  if (args(2).is_string ())
943  prefix = args(2).string_value ();
944  else
945  {
946  error ("list_in_columns: PREFIX must be a string");
947  return retval;
948  }
949  }
950 
951  std::ostringstream buf;
952 
953  s.list_in_columns (buf, width, prefix);
954 
955  retval = buf.str ();
956 
957  return retval;
958 }
959 
960 /*
961 %!test
962 %! input = {"abc", "def", "ghijkl", "mnop", "qrs", "tuv"};
963 %! result = "abc mnop\ndef qrs\nghijkl tuv\n";
964 %! assert (list_in_columns (input, 20), result);
965 %!test
966 %! input = ["abc"; "def"; "ghijkl"; "mnop"; "qrs"; "tuv"];
967 %! result = "abc mnop \ndef qrs \nghijkl tuv \n";
968 %! assert (list_in_columns (input, 20), result);
969 %!test
970 %! input = ["abc"; "def"; "ghijkl"; "mnop"; "qrs"; "tuv"];
971 %! result = " abc mnop \n def qrs \n ghijkl tuv \n";
972 %! assert (list_in_columns (input, 20, " "), result);
973 
974 %!error list_in_columns ()
975 %!error list_in_columns (["abc", "def"], 20, 2)
976 %!error list_in_columns (["abc", "def"], 20, " ", 3)
977 %!error <invalid conversion from string to real scalar> list_in_columns (["abc", "def"], "a")
978 */
Definition: Cell.h:35
charNDArray char_array_value(bool frc_str_conv=false) const
Definition: ov.h:817
octave_idx_type max_length(void) const
Definition: str-vec.h:75
static bool strncmpi_array_op(const charNDArray &s1, const charNDArray &s2, octave_idx_type n)
Definition: strfns.cc:802
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
static bool strcmpi_str_op(const std::string &s1, const std::string &s2, octave_idx_type)
Definition: strfns.cc:755
bool is_defined(void) const
Definition: ov.h:520
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix=std::string()) const
Definition: str-vec.cc:215
static bool strncmp_str_op(const std::string &s1, const std::string &s2, octave_idx_type n)
Definition: strfns.cc:661
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
bool is_cell(void) const
Definition: ov.h:529
static bool strcmpi_array_op(const charNDArray &s1, const charNDArray &s2, octave_idx_type)
Definition: strfns.cc:746
static octave_value do_strcmp_fun(const octave_value &arg0, const octave_value &arg1, octave_idx_type n, const char *fcn_name, bool(*array_op)(const charNDArray &, const charNDArray &, octave_idx_type), bool(*str_op)(const std::string &, const std::string &, octave_idx_type))
Definition: strfns.cc:343
string_vector all_strings(bool pad=false) const
Definition: ov.h:894
Cell cell_value(void) const
Definition: ov.cc:1566
static MArray< double > const octave_idx_type const octave_idx_type octave_idx_type octave_idx_type r2
Array< std::string > cellstr_value(void) const
Definition: ov.h:900
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
static bool strcmp_str_op(const std::string &s1, const std::string &s2, octave_idx_type)
Definition: strfns.cc:561
octave_value convert_to_str(bool pad=false, bool force=false, char type= '\'') const
Definition: ov.h:1017
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
std::string string_value(bool force=false) const
Definition: ov.h:897
static bool strncmp_array_op(const charNDArray &s1, const charNDArray &s2, octave_idx_type n)
Definition: strfns.cc:648
static bool strcmp_array_op(const charNDArray &s1, const charNDArray &s2, octave_idx_type)
Definition: strfns.cc:553
bool is_string(void) const
Definition: ov.h:562
OCTAVE_EXPORT octave_value_list Fstrcmpi(const octave_value_list &args, int)
Definition: strfns.cc:781
const T * data(void) const
Definition: Array.h:479
int error_state
Definition: error.cc:101
#define DEFUNX(name, fname, args_name, nargout_name, doc)
Definition: defun.h:52
bool is_cellstr(void) const
Definition: ov.h:532
OCTAVE_EXPORT octave_value_list Fstrncmpi(const octave_value_list &args, int)
Definition: strfns.cc:842
bool is_cellstr(void) const
Definition: Cell.cc:127
octave_idx_type length(void) const
Definition: ov.cc:1525
dim_vector dims(void) const
Definition: ov.h:470
static bool strncmpi_str_op(const std::string &s1, const std::string &s2, octave_idx_type n)
Definition: strfns.cc:814
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
bool is_dq_string(void) const
Definition: ov.h:568
static MArray< double > const octave_idx_type const octave_idx_type octave_idx_type r1
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
F77_RET_T const double * x
bool operator()(char x, char y) const
Definition: strfns.cc:740