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