GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
strfns.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cctype>
31 
32 #include <queue>
33 #include <sstream>
34 
35 #include "dMatrix.h"
36 #include "localcharset-wrapper.h"
37 #include "uniconv-wrappers.h"
38 #include "unistr-wrappers.h"
39 
40 #include "Cell.h"
41 #include "defun.h"
42 #include "error.h"
43 #include "errwarn.h"
44 #include "ov.h"
45 #include "ovl.h"
46 #include "unwind-prot.h"
47 #include "utils.h"
48 
49 #include "oct-string.h"
50 
51 DEFUN (char, args, ,
52  doc: /* -*- texinfo -*-
53 @deftypefn {} {} char (@var{x})
54 @deftypefnx {} {} char (@var{x}, @dots{})
55 @deftypefnx {} {} char (@var{s1}, @var{s2}, @dots{})
56 @deftypefnx {} {} char (@var{cell_array})
57 Create a string array from one or more numeric matrices, character
58 matrices, or cell arrays.
59 
60 Arguments are concatenated vertically. The returned values are padded with
61 blanks as needed to make each row of the string array have the same length.
62 Empty input strings are significant and will concatenated in the output.
63 
64 For numerical input, each element is converted to the corresponding ASCII
65 character. A range error results if an input is outside the ASCII range
66 (0-255).
67 
68 For cell arrays, each element is concatenated separately. Cell arrays
69 converted through @code{char} can mostly be converted back with
70 @code{cellstr}. For example:
71 
72 @example
73 @group
74 char ([97, 98, 99], "", @{"98", "99", 100@}, "str1", ["ha", "lf"])
75  @result{} ["abc "
76  " "
77  "98 "
78  "99 "
79  "d "
80  "str1"
81  "half"]
82 @end group
83 @end example
84 @seealso{strvcat, cellstr}
85 @end deftypefn */)
86 {
88 
89  int nargin = args.length ();
90 
91  if (nargin == 0)
92  retval = "";
93  else if (nargin == 1)
94  retval = args(0).convert_to_str (true, true,
95  args(0).is_dq_string () ? '"' : '\'');
96  else
97  {
98  int n_elts = 0;
99 
100  int max_len = 0;
101 
102  std::queue<string_vector> args_as_strings;
103 
104  for (int i = 0; i < nargin; i++)
105  {
106  string_vector s = args(i).xstring_vector_value ("char: unable to convert some args to strings");
107 
108  if (s.numel () > 0)
109  n_elts += s.numel ();
110  else
111  n_elts += 1;
112 
113  int s_max_len = s.max_length ();
114 
115  if (s_max_len > max_len)
116  max_len = s_max_len;
117 
118  args_as_strings.push (s);
119  }
120 
121  string_vector result (n_elts);
122 
123  int k = 0;
124 
125  for (int i = 0; i < nargin; i++)
126  {
127  string_vector s = args_as_strings.front ();
128  args_as_strings.pop ();
129 
130  int n = s.numel ();
131 
132  if (n > 0)
133  {
134  for (int j = 0; j < n; j++)
135  {
136  std::string t = s[j];
137  int t_len = t.length ();
138 
139  if (max_len > t_len)
140  t += std::string (max_len - t_len, ' ');
141 
142  result[k++] = t;
143  }
144  }
145  else
146  result[k++] = std::string (max_len, ' ');
147  }
148 
149  retval = octave_value (result, '\'');
150  }
151 
152  return retval;
153 }
154 
155 /*
156 %!assert (char (), '')
157 %!assert (char (100), "d")
158 %!assert (char (100,100), ["d";"d"])
159 %!assert (char ({100,100}), ["d";"d"])
160 %!assert (char ([100,100]), ["dd"])
161 %!assert (char ({100,{100}}), ["d";"d"])
162 %!assert (char (100, [], 100), ["d";" ";"d"])
163 %!assert (char ({100, [], 100}), ["d";" ";"d"])
164 %!assert (char ({100,{100, {""}}}), ["d";"d";" "])
165 %!assert (char (["a ";"be"], {"c", 100}), ["a ";"be";"c ";"d "])
166 %!assert (char ("a", "bb", "ccc"), ["a "; "bb "; "ccc"])
167 %!assert (char ([65, 83, 67, 73, 73]), "ASCII")
168 
169 %!test
170 %! x = char ("foo", "bar", "foobar");
171 %! assert (x(1,:), "foo ");
172 %! assert (x(2,:), "bar ");
173 %! assert (x(3,:), "foobar");
174 */
175 
176 DEFUN (strvcat, args, ,
177  doc: /* -*- texinfo -*-
178 @deftypefn {} {} strvcat (@var{x})
179 @deftypefnx {} {} strvcat (@var{x}, @dots{})
180 @deftypefnx {} {} strvcat (@var{s1}, @var{s2}, @dots{})
181 @deftypefnx {} {} strvcat (@var{cell_array})
182 Create a character array from one or more numeric matrices, character
183 matrices, or cell arrays.
184 
185 Arguments are concatenated vertically. The returned values are padded with
186 blanks as needed to make each row of the string array have the same length.
187 Unlike @code{char}, empty strings are removed and will not appear in the
188 output.
189 
190 For numerical input, each element is converted to the corresponding ASCII
191 character. A range error results if an input is outside the ASCII range
192 (0-255).
193 
194 For cell arrays, each element is concatenated separately. Cell arrays
195 converted through @code{strvcat} can mostly be converted back with
196 @code{cellstr}. For example:
197 
198 @example
199 @group
200 strvcat ([97, 98, 99], "", @{"98", "99", 100@}, "str1", ["ha", "lf"])
201  @result{} ["abc "
202  "98 "
203  "99 "
204  "d "
205  "str1"
206  "half"]
207 @end group
208 @end example
209 @seealso{char, strcat, cstrcat}
210 @end deftypefn */)
211 {
212  int nargin = args.length ();
213  int n_elts = 0;
214  size_t max_len = 0;
215  std::queue<string_vector> args_as_strings;
216 
217  for (int i = 0; i < nargin; i++)
218  {
219  string_vector s = args(i).xstring_vector_value ("strvcat: unable to convert some args to strings");
220 
221  size_t n = s.numel ();
222 
223  // do not count empty strings in calculation of number of elements
224  if (n > 0)
225  {
226  for (size_t j = 0; j < n; j++)
227  {
228  if (! s[j].empty ())
229  n_elts++;
230  }
231  }
232 
233  size_t s_max_len = s.max_length ();
234 
235  if (s_max_len > max_len)
236  max_len = s_max_len;
237 
238  args_as_strings.push (s);
239  }
240 
241  string_vector result (n_elts);
242 
243  octave_idx_type k = 0;
244 
245  for (int i = 0; i < nargin; i++)
246  {
247  string_vector s = args_as_strings.front ();
248  args_as_strings.pop ();
249 
250  size_t n = s.numel ();
251 
252  if (n > 0)
253  {
254  for (size_t j = 0; j < n; j++)
255  {
256  std::string t = s[j];
257  if (t.length () > 0)
258  {
259  size_t t_len = t.length ();
260 
261  if (max_len > t_len)
262  t += std::string (max_len - t_len, ' ');
263 
264  result[k++] = t;
265  }
266  }
267  }
268  }
269 
270  // Cannot use ovl. Relies on overloaded octave_value call.
271  return octave_value (result, '\'');
272 }
273 
274 /*
275 %!assert (strvcat (""), "")
276 %!assert (strvcat (100) == "d")
277 %!assert (strvcat (100,100), ["d";"d"])
278 %!assert (strvcat ({100,100}), ["d";"d"])
279 %!assert (strvcat ([100,100]), ["dd"])
280 %!assert (strvcat ({100,{100}}), ["d";"d"])
281 %!assert (strvcat (100, [], 100), ["d";"d"])
282 %!assert (strvcat ({100, [], 100}), ["d";"d"])
283 %!assert (strvcat ({100,{100, {""}}}), ["d";"d"])
284 %!assert (strvcat (["a ";"be"], {"c", 100}), ["a ";"be";"c ";"d "])
285 %!assert (strvcat ("a", "bb", "ccc"), ["a "; "bb "; "ccc"])
286 %!assert (strvcat (), "")
287 */
288 
289 DEFUN (ischar, args, ,
290  doc: /* -*- texinfo -*-
291 @deftypefn {} {} ischar (@var{x})
292 Return true if @var{x} is a character array.
293 @seealso{isfloat, isinteger, islogical, isnumeric, isstring, iscellstr, isa}
294 @end deftypefn */)
295 {
296  if (args.length () != 1)
297  print_usage ();
298 
299  return ovl (args(0).is_string ());
300 }
301 
302 /*
303 %!assert (ischar ("a"), true)
304 %!assert (ischar (["ab";"cd"]), true)
305 %!assert (ischar ({"ab"}), false)
306 %!assert (ischar (1), false)
307 %!assert (ischar ([1, 2]), false)
308 %!assert (ischar ([]), false)
309 %!assert (ischar ([1, 2; 3, 4]), false)
310 %!assert (ischar (""), true)
311 %!assert (ischar ("test"), true)
312 %!assert (ischar (["test"; "ing"]), true)
313 %!assert (ischar (struct ("foo", "bar")), false)
314 
315 %!error ischar ()
316 %!error ischar ("test", 1)
317 */
318 
319 static octave_value
320 do_strcmp_fun (const octave_value& arg0, const octave_value& arg1,
321  octave_idx_type n, const char *fcn_name,
322  bool (*array_op) (const Array<char>&, const Array<char>&,
324  bool (*str_op) (const std::string&, const std::string&,
325  std::string::size_type))
326 
327 {
329 
330  bool s1_string = arg0.is_string ();
331  bool s1_cell = arg0.iscell ();
332  bool s2_string = arg1.is_string ();
333  bool s2_cell = arg1.iscell ();
334 
335  if (s1_string && s2_string)
336  retval = array_op (arg0.char_array_value (), arg1.char_array_value (), n);
337  else if ((s1_string && s2_cell) || (s1_cell && s2_string))
338  {
339  octave_value str_val, cell_val;
340 
341  if (s1_string)
342  {
343  str_val = arg0;
344  cell_val = arg1;
345  }
346  else
347  {
348  str_val = arg1;
349  cell_val = arg0;
350  }
351 
352  const Cell cell = cell_val.cell_value ();
353  const string_vector str = str_val.string_vector_value ();
354  octave_idx_type r = str.numel ();
355 
356  if (r == 0 || r == 1)
357  {
358  // Broadcast the string.
359 
360  boolNDArray output (cell_val.dims (), false);
361 
362  std::string s = (r == 0 ? "" : str[0]);
363 
364  if (cell_val.iscellstr ())
365  {
366  const Array<std::string> cellstr = cell_val.cellstr_value ();
367  for (octave_idx_type i = 0; i < cellstr.numel (); i++)
368  output(i) = str_op (cellstr(i), s, n);
369  }
370  else
371  {
372  // FIXME: should we warn here?
373  for (octave_idx_type i = 0; i < cell.numel (); i++)
374  {
375  if (cell(i).is_string ())
376  output(i) = str_op (cell(i).string_value (), s, n);
377  }
378  }
379 
380  retval = output;
381  }
382  else if (r > 1)
383  {
384  if (cell.numel () == 1)
385  {
386  // Broadcast the cell.
387 
388  const dim_vector dv (r, 1);
389  boolNDArray output (dv, false);
390 
391  if (cell(0).is_string ())
392  {
393  const std::string str2 = cell(0).string_value ();
394 
395  for (octave_idx_type i = 0; i < r; i++)
396  output(i) = str_op (str[i], str2, n);
397  }
398 
399  retval = output;
400  }
401  else
402  {
403  // Must match in all dimensions.
404 
405  boolNDArray output (cell.dims (), false);
406 
407  if (cell.numel () == r)
408  {
409  if (cell_val.iscellstr ())
410  {
411  const Array<std::string> cellstr
412  = cell_val.cellstr_value ();
413  for (octave_idx_type i = 0; i < cellstr.numel (); i++)
414  output(i) = str_op (str[i], cellstr(i), n);
415  }
416  else
417  {
418  // FIXME: should we warn here?
419  for (octave_idx_type i = 0; i < r; i++)
420  {
421  if (cell(i).is_string ())
422  output(i) = str_op (str[i],
423  cell(i).string_value (), n);
424  }
425  }
426 
427  retval = output;
428  }
429  else
430  retval = false;
431  }
432  }
433  }
434  else if (s1_cell && s2_cell)
435  {
436  octave_value cell1_val, cell2_val;
437  octave_idx_type r1 = arg0.numel (), r2;
438 
439  if (r1 == 1)
440  {
441  // Make the singleton cell2.
442 
443  cell1_val = arg1;
444  cell2_val = arg0;
445  }
446  else
447  {
448  cell1_val = arg0;
449  cell2_val = arg1;
450  }
451 
452  const Cell cell1 = cell1_val.cell_value ();
453  const Cell cell2 = cell2_val.cell_value ();
454  r1 = cell1.numel ();
455  r2 = cell2.numel ();
456 
457  const dim_vector size1 = cell1.dims ();
458  const dim_vector size2 = cell2.dims ();
459 
460  boolNDArray output (size1, false);
461 
462  if (r2 == 1)
463  {
464  // Broadcast cell2.
465 
466  if (cell2(0).is_string ())
467  {
468  const std::string str2 = cell2(0).string_value ();
469 
470  if (cell1_val.iscellstr ())
471  {
472  const Array<std::string> cellstr = cell1_val.cellstr_value ();
473  for (octave_idx_type i = 0; i < cellstr.numel (); i++)
474  output(i) = str_op (cellstr(i), str2, n);
475  }
476  else
477  {
478  // FIXME: should we warn here?
479  for (octave_idx_type i = 0; i < r1; i++)
480  {
481  if (cell1(i).is_string ())
482  {
483  const std::string str1 = cell1(i).string_value ();
484  output(i) = str_op (str1, str2, n);
485  }
486  }
487  }
488  }
489  }
490  else
491  {
492  if (size1 != size2)
493  error ("%s: nonconformant cell arrays", fcn_name);
494 
495  if (cell1.iscellstr () && cell2.iscellstr ())
496  {
497  const Array<std::string> cellstr1 = cell1_val.cellstr_value ();
498  const Array<std::string> cellstr2 = cell2_val.cellstr_value ();
499  for (octave_idx_type i = 0; i < r1; i++)
500  output (i) = str_op (cellstr1(i), cellstr2(i), n);
501  }
502  else
503  {
504  // FIXME: should we warn here?
505  for (octave_idx_type i = 0; i < r1; i++)
506  {
507  if (cell1(i).is_string () && cell2(i).is_string ())
508  {
509  const std::string str1 = cell1(i).string_value ();
510  const std::string str2 = cell2(i).string_value ();
511  output(i) = str_op (str1, str2, n);
512  }
513  }
514  }
515  }
516 
517  retval = output;
518  }
519  else
520  retval = false;
521 
522  return retval;
523 }
524 
525 
526 // These are required so that they match the same signature as strncmp
527 // and strncmpi and can therefore be used in do_strcmp_fun.
528 
529 template <typename T, typename T_size_type>
530 static bool
531 strcmp_ignore_n (const T& s1, const T& s2, T_size_type)
532 { return octave::string::strcmp (s1, s2); }
533 
534 template <typename T, typename T_size_type>
535 static bool
536 strcmpi_ignore_n (const T& s1, const T& s2, T_size_type)
537 { return octave::string::strcmpi (s1, s2); }
538 
539 
540 DEFUN (strcmp, args, ,
541  doc: /* -*- texinfo -*-
542 @deftypefn {} {} strcmp (@var{s1}, @var{s2})
543 Return 1 if the character strings @var{s1} and @var{s2} are the same,
544 and 0 otherwise.
545 
546 If either @var{s1} or @var{s2} is a cell array of strings, then an array
547 of the same size is returned, containing the values described above for
548 every member of the cell array. The other argument may also be a cell
549 array of strings (of the same size or with only one element), char matrix
550 or character string.
551 
552 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmp
553 function returns 1 if the character strings are equal, and 0 otherwise.
554 This is just the opposite of the corresponding C library function.
555 @seealso{strcmpi, strncmp, strncmpi}
556 @end deftypefn */)
557 {
558  if (args.length () != 2)
559  print_usage ();
560 
561  return ovl (do_strcmp_fun (args(0), args(1), 0, "strcmp",
563 }
564 
565 /*
566 %!shared x
567 %! x = char (zeros (0, 2));
568 %!assert (strcmp ("", x), false)
569 %!assert (strcmp (x, ""), false)
570 %!assert (strcmp (x, x), true)
571 ## %!assert (strcmp ({""}, x), true)
572 ## %!assert (strcmp ({x}, ""), false)
573 ## %!assert (strcmp ({x}, x), true)
574 ## %!assert (strcmp ("", {x}), false)
575 ## %!assert (strcmp (x, {""}), false)
576 ## %!assert (strcmp (x, {x}), true)
577 ## %!assert (strcmp ({x; x}, ""), [false; false])
578 ## %!assert (strcmp ({x; x}, {""}), [false; false])
579 ## %!assert (strcmp ("", {x; x}), [false; false])
580 ## %!assert (strcmp ({""}, {x; x}), [false; false])
581 %!assert (strcmp ({"foo"}, x), false)
582 %!assert (strcmp ({"foo"}, "foo"), true)
583 %!assert (strcmp ({"foo"}, x), false)
584 %!assert (strcmp (x, {"foo"}), false)
585 %!assert (strcmp ("foo", {"foo"}), true)
586 %!assert (strcmp (x, {"foo"}), false)
587 %!shared y
588 %! y = char (zeros (2, 0));
589 %!assert (strcmp ("", y), false)
590 %!assert (strcmp (y, ""), false)
591 %!assert (strcmp (y, y), true)
592 %!assert (strcmp ({""}, y), [true; true])
593 %!assert (strcmp ({y}, ""), true)
594 %!assert (strcmp ({y}, y), [true; true])
595 %!assert (strcmp ("", {y}), true)
596 %!assert (strcmp (y, {""}), [true; true])
597 %!assert (strcmp (y, {y}), [true; true])
598 %!assert (strcmp ({y; y}, ""), [true; true])
599 %!assert (strcmp ({y; y}, {""}), [true; true])
600 %!assert (strcmp ("", {y; y}), [true; true])
601 %!assert (strcmp ({""}, {y; y}), [true; true])
602 %!assert (strcmp ({"foo"}, y), [false; false])
603 %!assert (strcmp ({"foo"}, y), [false; false])
604 %!assert (strcmp (y, {"foo"}), [false; false])
605 %!assert (strcmp (y, {"foo"}), [false; false])
606 %!assert (strcmp ("foobar", "foobar"), true)
607 %!assert (strcmp ("foobar", "fooBar"), false)
608 %!assert (strcmp ("fooba", "foobar"), false)
609 
610 %!error strcmp ()
611 %!error strcmp ("foo", "bar", 3)
612 */
613 
614 DEFUN (strncmp, args, ,
615  doc: /* -*- texinfo -*-
616 @deftypefn {} {} strncmp (@var{s1}, @var{s2}, @var{n})
617 Return 1 if the first @var{n} characters of strings @var{s1} and @var{s2}
618 are the same, and 0 otherwise.
619 
620 @example
621 @group
622 strncmp ("abce", "abcd", 3)
623  @result{} 1
624 @end group
625 @end example
626 
627 If either @var{s1} or @var{s2} is a cell array of strings, then an array
628 of the same size is returned, containing the values described above for
629 every member of the cell array. The other argument may also be a cell
630 array of strings (of the same size or with only one element), char matrix
631 or character string.
632 
633 @example
634 @group
635 strncmp ("abce", @{"abcd", "bca", "abc"@}, 3)
636  @result{} [1, 0, 1]
637 @end group
638 @end example
639 
640 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmp
641 function returns 1 if the character strings are equal, and 0 otherwise.
642 This is just the opposite of the corresponding C library function.
643 @seealso{strncmpi, strcmp, strcmpi}
644 @end deftypefn */)
645 {
646  if (args.length () != 3)
647  print_usage ();
648 
649  octave_idx_type n = args(2).idx_type_value ();
650 
651  if (n > 0)
652  return ovl (do_strcmp_fun (args(0), args(1), n, "strncmp",
655  else
656  error ("strncmp: N must be greater than 0");
657 }
658 
659 /*
660 %!assert (strncmp ("abce", "abc", 3), true)
661 %!assert (strncmp ("abce", "aBc", 3), false)
662 %!assert (strncmp (100, 100, 1), false)
663 %!assert (strncmp ("abce", {"abcd", "bca", "abc"}, 3), logical ([1, 0, 1]))
664 %!assert (strncmp ("abc", {"abcd", "bca", "abc"}, 4), logical ([0, 0, 1]))
665 %!assert (strncmp ({"abcd", "bca", "abc"},"abce", 3), logical ([1, 0, 1]))
666 %!assert (strncmp ({"abcd", "bca", "abc"},{"abcd", "bca", "abe"}, 3), logical ([1, 1, 0]))
667 %!assert (strncmp ("abc", {"abcd", 10}, 2), logical ([1, 0]))
668 
669 %!assert <*54373> (strncmp ("abc", "abc", 100))
670 
671 %!error strncmp ()
672 %!error strncmp ("abc", "def")
673 */
674 
675 DEFUNX ("strcmpi", Fstrcmpi, args, ,
676  doc: /* -*- texinfo -*-
677 @deftypefn {} {} strcmpi (@var{s1}, @var{s2})
678 Return 1 if the character strings @var{s1} and @var{s2} are the same,
679 disregarding case of alphabetic characters, and 0 otherwise.
680 
681 If either @var{s1} or @var{s2} is a cell array of strings, then an array
682 of the same size is returned, containing the values described above for
683 every member of the cell array. The other argument may also be a cell
684 array of strings (of the same size or with only one element), char matrix
685 or character string.
686 
687 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strcmp
688 function returns 1 if the character strings are equal, and 0 otherwise.
689 This is just the opposite of the corresponding C library function.
690 
691 @strong{Caution:} National alphabets are not supported.
692 @seealso{strcmp, strncmp, strncmpi}
693 @end deftypefn */)
694 {
695  if (args.length () != 2)
696  print_usage ();
697 
698  return ovl (do_strcmp_fun (args(0), args(1), 0, "strcmpi",
700 }
701 
702 /*
703 %!assert (strcmpi ("abc123", "ABC123"), true)
704 */
705 
706 DEFUNX ("strncmpi", Fstrncmpi, args, ,
707  doc: /* -*- texinfo -*-
708 @deftypefn {} {} strncmpi (@var{s1}, @var{s2}, @var{n})
709 Return 1 if the first @var{n} character of @var{s1} and @var{s2} are the
710 same, disregarding case of alphabetic characters, and 0 otherwise.
711 
712 If either @var{s1} or @var{s2} is a cell array of strings, then an array
713 of the same size is returned, containing the values described above for
714 every member of the cell array. The other argument may also be a cell
715 array of strings (of the same size or with only one element), char matrix
716 or character string.
717 
718 @strong{Caution:} For compatibility with @sc{matlab}, Octave's strncmpi
719 function returns 1 if the character strings are equal, and 0 otherwise.
720 This is just the opposite of the corresponding C library function.
721 
722 @strong{Caution:} National alphabets are not supported.
723 @seealso{strncmp, strcmp, strcmpi}
724 @end deftypefn */)
725 {
726  if (args.length () != 3)
727  print_usage ();
728 
729  octave_idx_type n = args(2).idx_type_value ();
730 
731  if (n > 0)
732  return ovl (do_strcmp_fun (args(0), args(1), n, "strncmpi",
735  else
736  error ("strncmpi: N must be greater than 0");
737 }
738 
739 /*
740 %!assert (strncmpi ("abc123", "ABC456", 3), true)
741 
742 %!assert <*54373> (strncmpi ("abc", "abC", 100))
743 */
744 
745 DEFUN (str2double, args, ,
746  doc: /* -*- texinfo -*-
747 @deftypefn {} {} str2double (@var{s})
748 Convert a string to a real or complex number.
749 
750 The string must be in one of the following formats where a and b are real
751 numbers and the complex unit is @qcode{'i'} or @qcode{'j'}:
752 
753 @itemize
754 @item a + bi
755 
756 @item a + b*i
757 
758 @item a + i*b
759 
760 @item bi + a
761 
762 @item b*i + a
763 
764 @item i*b + a
765 @end itemize
766 
767 If present, a and/or b are of the form @nospell{[+-]d[,.]d[[eE][+-]d]} where
768 the brackets indicate optional arguments and @qcode{'d'} indicates zero or
769 more digits. The special input values @code{Inf}, @code{NaN}, and @code{NA}
770 are also accepted.
771 
772 @var{s} may be a character string, character matrix, or cell array. For
773 character arrays the conversion is repeated for every row, and a double or
774 complex array is returned. Empty rows in @var{s} are deleted and not
775 returned in the numeric array. For cell arrays each character string
776 element is processed and a double or complex array of the same dimensions as
777 @var{s} is returned.
778 
779 For unconvertible scalar or character string input @code{str2double} returns
780 a NaN@. Similarly, for character array input @code{str2double} returns a
781 NaN for any row of @var{s} that could not be converted. For a cell array,
782 @code{str2double} returns a NaN for any element of @var{s} for which
783 conversion fails. Note that numeric elements in a mixed string/numeric
784 cell array are not strings and the conversion will fail for these elements
785 and return NaN.
786 
787 @code{str2double} can replace @code{str2num}, and it avoids the security
788 risk of using @code{eval} on unknown data.
789 @seealso{str2num}
790 @end deftypefn */)
791 {
792  if (args.length () != 1)
793  print_usage ();
794 
796 
797  if (args(0).is_string ())
798  {
799  if (args(0).rows () == 0 || args(0).columns () == 0)
801  else if (args(0).rows () == 1 && args(0).ndims () == 2)
802  retval = octave::string::str2double (args(0).string_value ());
803  else
804  {
805  const string_vector sv = args(0).string_vector_value ();
806 
808  }
809  }
810  else if (args(0).iscell ())
811  {
812  const Cell cell = args(0).cell_value ();
813 
815 
816  for (octave_idx_type i = 0; i < cell.numel (); i++)
817  {
818  if (cell(i).is_string ())
819  output(i) = octave::string::str2double (cell(i).string_value ());
820  }
821  retval = output;
822  }
823  else
825 
826  return retval;
827 }
828 
829 /*
830 %!assert (str2double ("1"), 1)
831 %!assert (str2double ("-.1e-5"), -1e-6)
832 %!testif ; ! ismac ()
833 %! assert (str2double (char ("1", "2 3", "4i")), [1; NaN; 4i]);
834 %!xtest <47413>
835 %! ## Same test code as above, but intended only for test statistics on Mac.
836 %! if (! ismac ()), return; endif
837 %! assert (str2double (char ("1", "2 3", "4i")), [1; NaN; 4i]);
838 %!assert (str2double ("1,222.5"), 1222.5)
839 %!assert (str2double ("i"), i)
840 %!assert (str2double ("2j"), 2i)
841 %!assert (str2double ("2 + j"), 2+j)
842 %!assert (str2double ("i*2 + 3"), 3+2i)
843 %!assert (str2double (".5*i + 3.5"), 3.5+0.5i)
844 %!assert (str2double ("1e-3 + i*.25"), 1e-3 + 0.25i)
845 %!assert (str2double (char ("2 + j","1.25e-3","-05")), [2+i; 1.25e-3; -5])
846 %!assert (str2double ({"2 + j","1.25e-3","-05"}), [2+i, 1.25e-3, -5])
847 %!assert (str2double (1), NaN)
848 %!assert (str2double ("1 2 3 4"), NaN)
849 %!assert (str2double ("Hello World"), NaN)
850 %!assert (str2double ("NaN"), NaN)
851 %!assert (str2double ("NA"), NA)
852 %!assert (str2double ("Inf"), Inf)
853 %!assert (str2double ("iNF"), Inf)
854 %!assert (str2double ("-Inf"), -Inf)
855 %!assert (str2double ("Inf*i"), complex (0, Inf))
856 %!assert (str2double ("iNF*i"), complex (0, Inf))
857 %!assert (str2double ("NaN + Inf*i"), complex (NaN, Inf))
858 %!assert (str2double ("Inf - Inf*i"), complex (Inf, -Inf))
859 %!assert (str2double ("-i*NaN - Inf"), complex (-Inf, -NaN))
860 %!testif ; ! ismac ()
861 %! assert (str2double ({"abc", "4i"}), [NaN + 0i, 4i]);
862 %!xtest <47413>
863 %! if (! ismac ()), return; endif
864 %! assert (str2double ({"abc", "4i"}), [NaN + 0i, 4i]);
865 %!testif ; ! ismac ()
866 %! assert (str2double ({2, "4i"}), [NaN + 0i, 4i])
867 %!xtest <47413>
868 %! if (! ismac ()), return; endif
869 %! assert (str2double ({2, "4i"}), [NaN + 0i, 4i])
870 %!assert (str2double (zeros (3,1,2)), NaN)
871 %!assert (str2double (''), NaN)
872 %!assert (str2double ([]), NaN)
873 %!assert (str2double (char(zeros(3,0))), NaN)
874 */
875 
876 DEFUN (__native2unicode__, args, ,
877  doc: /* -*- texinfo -*-
878 @deftypefn {} {@var{utf8_str} =} __native2unicode__ (@var{native_bytes}, @var{codepage})
879 Convert byte stream @var{native_bytes} to UTF-8 using @var{codepage}.
880 
881 @seealso{native2unicode, __unicode2native__}
882 @end deftypefn */)
883 {
884  int nargin = args.length ();
885 
886  if (nargin != 2)
887  print_usage ();
888 
889  if (args(0).is_string ())
890  return ovl (args(0));
891 
892  std::string tmp = args(1).string_value ();
893  const char *codepage
894  = (tmp.empty () ? octave_locale_charset_wrapper () : tmp.c_str ());
895 
896  charNDArray native_bytes = args(0).char_array_value ();
897 
898  const char *src = native_bytes.data ();
899  size_t srclen = native_bytes.numel ();
900 
901  size_t length;
902  uint8_t *utf8_str = nullptr;
903 
905 
906  utf8_str = octave_u8_conv_from_encoding (codepage, src, srclen, &length);
907 
908  if (! utf8_str)
909  {
910  if (errno == ENOSYS)
911  error ("native2unicode: iconv() is not supported. Installing GNU "
912  "libiconv and then re-compiling Octave could fix this.");
913  else
914  error ("native2unicode: converting from codepage '%s' to UTF-8: %s",
915  codepage, std::strerror (errno));
916  }
917 
918  frame.add_fcn (::free, static_cast<void *> (utf8_str));
919 
921 
923 
924  for (octave_idx_type i = 0; i < len; i++)
925  retval.xelem(i) = utf8_str[i];
926 
927  return ovl (retval);
928 }
929 
930 DEFUN (__unicode2native__, args, ,
931  doc: /* -*- texinfo -*-
932 @deftypefn {} {@var{native_bytes} =} __unicode2native__ (@var{utf8_str}, @var{codepage})
933 Convert UTF-8 string @var{utf8_str} to byte stream @var{native_bytes} using
934 @var{codepage}.
935 
936 @seealso{unicode2native, __native2unicode__}
937 @end deftypefn */)
938 {
939  int nargin = args.length ();
940 
941  if (nargin != 2)
942  print_usage ();
943 
944  std::string tmp = args(1).string_value ();
945  const char *codepage
946  = (tmp.empty () ? octave_locale_charset_wrapper () : tmp.c_str ());
947 
948  charNDArray utf8_str = args(0).char_array_value ();
949 
950  const uint8_t *src = reinterpret_cast<const uint8_t *> (utf8_str.data ());
951  size_t srclen = utf8_str.numel ();
952 
953  size_t length;
954  char *native_bytes = nullptr;
955 
957 
958  native_bytes = octave_u8_conv_to_encoding (codepage, src, srclen, &length);
959 
960  if (! native_bytes)
961  {
962  if (errno == ENOSYS)
963  error ("unicode2native: iconv() is not supported. Installing GNU "
964  "libiconv and then re-compiling Octave could fix this.");
965  else
966  error ("unicode2native: converting from UTF-8 to codepage '%s': %s",
967  codepage, std::strerror (errno));
968  }
969 
970  frame.add_fcn (::free, static_cast<void *> (native_bytes));
971 
973 
975 
976  for (octave_idx_type i = 0; i < len; i++)
977  retval.xelem(i) = native_bytes[i];
978 
979  return ovl (retval);
980 }
981 
982 DEFUN (__locale_charset__, , ,
983  doc: /* -*- texinfo -*-
984 @deftypefn {} {@var{charset} =} __locale_charset__ ()
985 Return the identifier for the charset used if the encoding is set to
986 @qcode{"locale"}.
987 @end deftypefn */)
988 {
989  const char *charset = octave_locale_charset_wrapper ();
990  std::string charset_str (charset);
991  return ovl (charset_str);
992 }
993 
994 DEFUN (unicode_idx, args, ,
995  doc: /* -*- texinfo -*-
996 @deftypefn {} {@var{idx} =} unicode_idx (@var{str})
997 Return an array with the indices for each UTF-8 encoded character in @var{str}.
998 
999 @example
1000 @group
1001 unicode_idx ("aäbc")
1002  @result{} [1, 2, 2, 3, 4]
1003 @end group
1004 @end example
1005 
1006 @end deftypefn */)
1007 {
1008  int nargin = args.length ();
1009 
1010  if (nargin != 1)
1011  print_usage ();
1012 
1013  charNDArray str = args(0).xchar_array_value ("STR must be a string");
1014  Array<octave_idx_type> p (dim_vector (str.ndims (), 1));
1015  charNDArray str_p;
1016  if (str.ndims () > 1)
1017  {
1018  for (octave_idx_type i=0; i < str.ndims (); i++)
1019  p(i) = i;
1020  p(0) = 1;
1021  p(1) = 0;
1022  str_p = str.permute (p);
1023  }
1024 
1025  const uint8_t *src = reinterpret_cast<const uint8_t *> (str_p.data ());
1026  octave_idx_type srclen = str.numel ();
1027 
1028  NDArray idx (str_p.dims ());
1029 
1030  octave_idx_type u8_char_num = 1;
1031  for (octave_idx_type i = 0; i < srclen; u8_char_num++)
1032  {
1033  int mblen = octave_u8_strmblen_wrapper (src + i);
1034  if (mblen < 1)
1035  mblen = 1;
1036  for (octave_idx_type j = 0; j < mblen; j++)
1037  idx (i+j) = u8_char_num;
1038  i += mblen;
1039  }
1040 
1041  return ovl(str.ndims () > 1 ? idx.permute (p, true) : idx);
1042 }
1043 
1044 /*
1045 %!assert (unicode_idx (["aäou"; "Ä∞"]), [1 2 2 3 4; 5 5 6 6 6]);
1046 */
1047 
1048 DEFUN (__u8_validate__, args, ,
1049  doc: /* -*- texinfo -*-
1050 @deftypefn {} {@var{out_str} =} __u8_validate__ (in_str, mode)
1051 Return string with valid UTF-8.
1052 
1053 On encountering invalid UTF-8 in @var{in_str}, the bytes are either replaced by
1054 the replacement character "�" (if @var{mode} is omitted or the string
1055 "replace") or interpreted as the Unicode code points U+0080–U+00FF with the
1056 same value as the byte (if @var{mode} is the string "unicode"), thus
1057 interpreting the bytes according to ISO-8859-1.
1058 
1059 @end deftypefn */)
1060 {
1061  if (args.length () < 1 || args.length () > 2)
1062  print_usage ();
1063 
1064  // Input check
1065  std::string in_str =
1066  args(0).xstring_value ("__u8_validate__: IN_STR must be a string.");
1067 
1068  std::string mode = "replace";
1069  if (args.length () > 1)
1070  mode = args(1).xstring_value ("__u8_validate__: MODE must be a string.");
1071 
1073  if (mode == "replace")
1075  else if (mode == "unicode")
1077  else
1078  error ("__u8_validate__: MODE must either be \"replace\" or \"unicode\".");
1079 
1080  octave::string::u8_validate ("__u8_validate__", in_str, fb_type);
1081 
1082  return ovl (in_str);
1083 }
1084 
1085 DEFUN (newline, args, ,
1086  doc: /* -*- texinfo -*-
1087 @deftypefn {} {} newline
1088 Return the character corresponding to a newline.
1089 
1090 This is equivalent to @qcode{"@xbackslashchar{}n"}.
1091 
1092 Example Code
1093 
1094 @example
1095 @group
1096 joined_string = [newline "line1" newline "line2"]
1097 @result{}
1098 line1
1099 line2
1100 @end group
1101 @end example
1102 
1103 @seealso{strcat, strjoin, strsplit}
1104 @end deftypefn */)
1105 {
1106  if (args.length () != 0)
1107  print_usage ();
1108 
1109  static octave_value_list retval = ovl ("\n");
1110 
1111  return retval;
1112 }
1113 
1114 /*
1115 %!assert (newline (), "\n")
1116 
1117 %!error newline (1)
1118 %!error [a, b] = newline ();
1119 */
1120 
1121 DEFUN (list_in_columns, args, ,
1122  doc: /* -*- texinfo -*-
1123 @deftypefn {} {} list_in_columns (@var{arg}, @var{width}, @var{prefix})
1124 Return a string containing the elements of @var{arg} listed in columns with
1125 an overall maximum width of @var{width} and optional prefix @var{prefix}.
1126 
1127 The argument @var{arg} must be a cell array of character strings or a
1128 character array.
1129 
1130 If @var{width} is not specified or is an empty matrix, or less than or equal
1131 to zero, the width of the terminal screen is used. Newline characters are
1132 used to break the lines in the output string. For example:
1133 @c Set example in small font to prevent overfull line
1134 
1135 @smallexample
1136 @group
1137 list_in_columns (@{"abc", "def", "ghijkl", "mnop", "qrs", "tuv"@}, 20)
1138  @result{} abc mnop
1139  def qrs
1140  ghijkl tuv
1141 
1142 whos ans
1143  @result{}
1144  Variables in the current scope:
1145 
1146  Attr Name Size Bytes Class
1147  ==== ==== ==== ===== =====
1148  ans 1x37 37 char
1149 
1150  Total is 37 elements using 37 bytes
1151 @end group
1152 @end smallexample
1153 
1154 @seealso{terminal_size}
1155 @end deftypefn */)
1156 {
1157  int nargin = args.length ();
1158 
1159  if (nargin < 1 || nargin > 3)
1160  print_usage ();
1161 
1162  string_vector s = args(0).xstring_vector_value ("list_in_columns: ARG must be a cellstr or char array");
1163 
1164  int width = -1;
1165 
1166  if (nargin > 1 && ! args(1).isempty ())
1167  width = args(1).xint_value ("list_in_columns: WIDTH must be an integer");
1168 
1169  std::string prefix;
1170 
1171  if (nargin > 2)
1172  prefix = args(2).xstring_value ("list_in_columns: PREFIX must be a string");
1173 
1174  std::ostringstream buf;
1175 
1176  s.list_in_columns (buf, width, prefix);
1177 
1178  return ovl (buf.str ());
1179 }
1180 
1181 /*
1182 %!test
1183 %! input = {"abc", "def", "ghijkl", "mnop", "qrs", "tuv"};
1184 %! result = "abc mnop\ndef qrs\nghijkl tuv\n";
1185 %! assert (list_in_columns (input, 20), result);
1186 %!test
1187 %! input = char ("abc", "def", "ghijkl", "mnop", "qrs", "tuv");
1188 %! result = "abc mnop \ndef qrs \nghijkl tuv \n";
1189 %! assert (list_in_columns (input, 20), result);
1190 %!test
1191 %! input = char ("abc", "def", "ghijkl", "mnop", "qrs", "tuv");
1192 %! result = " abc mnop \n def qrs \n ghijkl tuv \n";
1193 %! assert (list_in_columns (input, 20, " "), result);
1194 
1195 %!error list_in_columns ()
1196 %!error list_in_columns (["abc", "def"], 20, 2)
1197 %!error list_in_columns (["abc", "def"], 20, " ", 3)
1198 %!error <list_in_columns: WIDTH must be an integer> list_in_columns (["abc", "def"], "a")
1199 */
#define NaN
Definition: Faddeeva.cc:248
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:469
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:581
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:453
int ndims(void) const
Size of the specified dimension.
Definition: Array.h:589
Array< T > permute(const Array< octave_idx_type > &vec, bool inv=false) const
Size of the specified dimension.
Definition: Array.cc:431
Definition: Cell.h:43
bool iscellstr(void) const
Definition: Cell.cc:126
MArray< T > permute(const Array< octave_idx_type > &vec, bool inv=false) const
Definition: MArray.h:96
Definition: dMatrix.h:42
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
void add_fcn(void(*fcn)(Params...), Args &&... args)
bool iscellstr(void) const
Definition: ov.h:563
bool iscell(void) const
Definition: ov.h:560
octave_idx_type numel(void) const
Definition: ov.h:518
bool is_string(void) const
Definition: ov.h:593
charNDArray char_array_value(bool frc_str_conv=false) const
Definition: ov.h:850
Cell cell_value(void) const
string_vector string_vector_value(bool pad=false) const
Definition: ov.h:930
Array< std::string > cellstr_value(void) const
Definition: ov.h:935
dim_vector dims(void) const
Definition: ov.h:500
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
Definition: str-vec.cc:201
octave_idx_type max_length(void) const
Definition: str-vec.h:79
octave_idx_type numel(void) const
Definition: str-vec.h:100
Array< U > map(F fcn) const
Definition: str-vec.h:145
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
#define DEFUNX(name, fname, args_name, nargout_name, doc)
Macro to define a builtin function with certain internal name.
Definition: defun.h:85
void error(const char *fmt,...)
Definition: error.cc:968
const char * octave_locale_charset_wrapper(void)
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
bool strncmp(const T &str_a, const T &str_b, const typename T::size_type n)
True if the first N characters are the same.
Definition: oct-string.cc:156
bool strncmpi(const T &str_a, const T &str_b, const typename T::size_type n)
True if the first N characters are the same, ignoring case.
Definition: oct-string.cc:185
bool strcmp(const T &str_a, const T &str_b)
True if strings are the same.
Definition: oct-string.cc:122
bool strcmpi(const T &str_a, const T &str_b)
True if strings are the same, ignoring case.
Definition: oct-string.cc:139
OCTAVE_API Complex str2double(const std::string &str_arg)
Definition: oct-string.cc:460
OCTAVE_API unsigned int u8_validate(const std::string &who, std::string &in_string, const u8_fallback_type type=U8_REPLACEMENT_CHAR)
Definition: oct-string.cc:559
std::complex< double > Complex
Definition: oct-cmplx.h:33
void free(void *)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
OCTAVE_EXPORT octave_value_list Fstrncmpi(const octave_value_list &args, int)
Definition: strfns.cc:724
static bool strcmpi_ignore_n(const T &s1, const T &s2, T_size_type)
Definition: strfns.cc:536
OCTAVE_EXPORT octave_value_list Fstrcmpi(const octave_value_list &args, int)
Definition: strfns.cc:693
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 Array< char > &, const Array< char > &, octave_idx_type), bool(*str_op)(const std::string &, const std::string &, std::string::size_type))
Definition: strfns.cc:320
static bool strcmp_ignore_n(const T &s1, const T &s2, T_size_type)
Definition: strfns.cc:531
uint8_t * octave_u8_conv_from_encoding(const char *fromcode, const char *src, size_t srclen, size_t *lengthp)
char * octave_u8_conv_to_encoding(const char *tocode, const uint8_t *src, size_t srclen, size_t *lengthp)
int octave_u8_strmblen_wrapper(const uint8_t *src)
F77_RET_T len
Definition: xerbla.cc:61