GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-string.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2016-2023 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 "oct-string.h"
31 
32 #include <algorithm>
33 #include <cctype>
34 #include <cstring>
35 #include <iomanip>
36 #include <string>
37 
38 #include "Array.h"
39 #include "lo-ieee.h"
40 #include "lo-mappers.h"
41 #include "uniconv-wrappers.h"
42 #include "unistr-wrappers.h"
43 #include "unwind-prot.h"
44 
45 template <typename T>
46 static bool
47 str_data_cmp (const typename T::value_type *a, const typename T::value_type *b,
48  const typename T::size_type n)
49 {
50  for (typename T::size_type i = 0; i < n; ++i)
51  if (a[i] != b[i])
52  return false;
53  return true;
54 }
55 
56 template <typename T>
57 static bool
58 str_data_cmpi (const typename T::value_type *a, const typename T::value_type *b,
59  const typename T::size_type n)
60 {
61  for (typename T::size_type i = 0; i < n; ++i)
62  if (std::tolower (a[i]) != std::tolower (b[i]))
63  return false;
64  return true;
65 }
66 
67 
68 // Templates to handle std::basic_string, std::vector, Array, and char*.
69 template <typename T>
70 typename T::size_type
71 numel (const T& str)
72 {
73  return str.size ();
74 }
75 
76 template <>
78 numel (const Array<char>& str)
79 {
80  return str.numel ();
81 }
82 
83 template <typename T>
84 typename T::size_type
85 strlen (const typename T::value_type *str)
86 {
87  return std::strlen (str);
88 }
89 
90 template <typename T>
91 bool
92 sizes_cmp (const T& str_a, const T& str_b)
93 {
94  return str_a.size () == str_b.size ();
95 }
96 
97 template <>
98 bool
99 sizes_cmp (const Array<char>& str_a, const Array<char>& str_b)
100 {
101  return str_a.dims () == str_b.dims ();
102 }
103 
104 template <typename T>
105 bool
106 sizes_cmp (const T& str_a, const typename T::value_type *str_b)
107 {
108  return str_a.size () == strlen<T> (str_b);
109 }
110 
111 template <>
112 bool
113 sizes_cmp (const Array<char>& str_a, const char *str_b)
114 {
115  return (str_a.isvector () && str_a.rows () == 1
116  && str_a.numel () == strlen<Array<char>> (str_b));
117 }
118 
119 
120 template<typename T>
121 bool
122 octave::string::strcmp (const T& str_a, const T& str_b)
123 {
124  return (sizes_cmp (str_a, str_b)
125  && str_data_cmp<T> (str_a.data (), str_b.data (), numel (str_a)));
126 }
127 
128 template<typename T>
129 bool
130 octave::string::strcmp (const T& str_a, const typename T::value_type *str_b)
131 {
132  return (sizes_cmp (str_a, str_b)
133  && str_data_cmp<T> (str_a.data (), str_b, numel (str_a)));
134 }
135 
136 
137 template<typename T>
138 bool
139 octave::string::strcmpi (const T& str_a, const T& str_b)
140 {
141  return (sizes_cmp (str_a, str_b)
142  && str_data_cmpi<T> (str_a.data (), str_b.data (), numel (str_a)));
143 }
144 
145 template<typename T>
146 bool
147 octave::string::strcmpi (const T& str_a, const typename T::value_type *str_b)
148 {
149  return (sizes_cmp (str_a, str_b)
150  && str_data_cmpi<T> (str_a.data (), str_b, numel (str_a)));
151 }
152 
153 
154 template<typename T>
155 bool
156 octave::string::strncmp (const T& str_a, const T& str_b,
157  const typename T::size_type n)
158 {
159  typename T::size_type neff;
160  auto len_a = numel (str_a);
161  auto len_b = numel (str_b);
162  neff = std::min (std::max (len_a, len_b), n);
163 
164  return (len_a >= neff && len_b >= neff
165  && str_data_cmp<T> (str_a.data (), str_b.data (), neff));
166 }
167 
168 template<typename T>
169 bool
170 octave::string::strncmp (const T& str_a, const typename T::value_type *str_b,
171  const typename T::size_type n)
172 {
173  typename T::size_type neff;
174  auto len_a = numel (str_a);
175  auto len_b = strlen<T> (str_b);
176  neff = std::min (std::max (len_a, len_b), n);
177 
178  return (len_a >= neff && len_b >= neff
179  && str_data_cmp<T> (str_a.data (), str_b, neff));
180 }
181 
182 
183 template<typename T>
184 bool
185 octave::string::strncmpi (const T& str_a, const T& str_b,
186  const typename T::size_type n)
187 {
188  typename T::size_type neff;
189  auto len_a = numel (str_a);
190  auto len_b = numel (str_b);
191  neff = std::min (std::max (len_a, len_b), n);
192 
193  return (len_a >= neff && len_b >= neff
194  && str_data_cmpi<T> (str_a.data (), str_b.data (), neff));
195 }
196 
197 template<typename T>
198 bool
199 octave::string::strncmpi (const T& str_a, const typename T::value_type *str_b,
200  const typename T::size_type n)
201 {
202  typename T::size_type neff;
203  auto len_a = numel (str_a);
204  auto len_b = strlen<T> (str_b);
205  neff = std::min (std::max (len_a, len_b), n);
206 
207  return (len_a >= neff && len_b >= neff
208  && str_data_cmpi<T> (str_a.data (), str_b, neff));
209 }
210 
211 
212 // Instantiations we need
213 #define INSTANTIATE_OCTAVE_STRING(T, API) \
214  template API bool octave::string::strcmp<T> (const T&, const T&); \
215  template API bool \
216  octave::string::strcmp<T> (const T&, const typename T::value_type*); \
217  template API bool octave::string::strcmpi<T> (const T&, const T&); \
218  template API bool \
219  octave::string::strcmpi<T> (const T&, const typename T::value_type*); \
220  template API bool \
221  octave::string::strncmp<T> (const T&, const T&, \
222  const typename T::size_type); \
223  template API bool \
224  octave::string::strncmp<T> (const T&, const typename T::value_type*, \
225  const typename T::size_type); \
226  template API bool \
227  octave::string::strncmpi<T> (const T&, const T&, \
228  const typename T::size_type n); \
229  template API bool \
230  octave::string::strncmpi<T> (const T&, const typename T::value_type*, \
231  const typename T::size_type);
232 
233 // We could also instantiate std::vector<char> but would it be
234 // useful for anyone?
237 
238 #undef INSTANTIATE_OCTAVE_STRING
239 
240 static inline bool
242 { return c == 'i' || c == 'j'; }
243 
244 static double
245 single_num (std::istringstream& is)
246 {
247  double num = 0.0;
248 
249  char c = is.peek ();
250 
251  // Skip spaces.
252  while (isspace (c))
253  {
254  is.get ();
255  c = is.peek ();
256  }
257 
258  if (std::toupper (c) == 'I')
259  {
260  // It's infinity.
261  is.get ();
262  char c1 = is.get ();
263  char c2 = is.get ();
264  if (std::tolower (c1) == 'n' && std::tolower (c2) == 'f')
265  {
267  is.peek (); // May set EOF bit.
268  }
269  else
270  is.setstate (std::ios::failbit); // indicate that read has failed.
271  }
272  else if (c == 'N')
273  {
274  // It's NA or NaN
275  is.get ();
276  char c1 = is.get ();
277  if (c1 == 'A')
278  {
279  num = octave_NA;
280  is.peek (); // May set EOF bit.
281  }
282  else
283  {
284  char c2 = is.get ();
285  if (c1 == 'a' && c2 == 'N')
286  {
288  is.peek (); // May set EOF bit.
289  }
290  else
291  is.setstate (std::ios::failbit); // indicate that read has failed.
292  }
293  }
294  else
295  is >> num;
296 
297  return num;
298 }
299 
300 static std::istringstream&
301 extract_num (std::istringstream& is, double& num, bool& imag, bool& have_sign)
302 {
303  have_sign = imag = false;
304 
305  char c = is.peek ();
306 
307  // Skip leading spaces.
308  while (isspace (c))
309  {
310  is.get ();
311  c = is.peek ();
312  }
313 
314  bool negative = false;
315 
316  // Accept leading sign.
317  if (c == '+' || c == '-')
318  {
319  have_sign = true;
320  negative = c == '-';
321  is.get ();
322  c = is.peek ();
323  }
324 
325  // Skip spaces after sign.
326  while (isspace (c))
327  {
328  is.get ();
329  c = is.peek ();
330  }
331 
332  // Imaginary number (i*num or just i), or maybe 'inf'.
333  if (c == 'i')
334  {
335  // possible infinity.
336  is.get ();
337  c = is.peek ();
338 
339  if (is.eof ())
340  {
341  // just 'i' and string is finished. Return immediately.
342  imag = true;
343  num = (negative ? -1.0 : 1.0);
344  return is;
345  }
346  else
347  {
348  if (std::tolower (c) != 'n')
349  imag = true;
350  is.unget ();
351  }
352  }
353  else if (c == 'j')
354  imag = true;
355 
356  // It's i*num or just i
357  if (imag)
358  {
359  is.get ();
360  c = is.peek ();
361  // Skip spaces after imaginary unit.
362  while (isspace (c))
363  {
364  is.get ();
365  c = is.peek ();
366  }
367 
368  if (c == '*')
369  {
370  // Multiplier follows, we extract it as a number.
371  is.get ();
372  num = single_num (is);
373  if (is.good ())
374  c = is.peek ();
375  }
376  else
377  num = 1.0;
378  }
379  else
380  {
381  // It's num, num*i, or numi.
382  num = single_num (is);
383  if (is.good ())
384  {
385  c = is.peek ();
386 
387  // Skip spaces after number.
388  while (isspace (c))
389  {
390  is.get ();
391  c = is.peek ();
392  }
393 
394  if (c == '*')
395  {
396  is.get ();
397  c = is.peek ();
398 
399  // Skip spaces after operator.
400  while (isspace (c))
401  {
402  is.get ();
403  c = is.peek ();
404  }
405 
406  if (is_imag_unit (c))
407  {
408  imag = true;
409  is.get ();
410  c = is.peek ();
411  }
412  else
413  is.setstate (std::ios::failbit); // indicate read has failed.
414  }
415  else if (is_imag_unit (c))
416  {
417  imag = true;
418  is.get ();
419  c = is.peek ();
420  }
421  }
422  }
423 
424  if (is.good ())
425  {
426  // Skip trailing spaces.
427  while (isspace (c))
428  {
429  is.get ();
430  c = is.peek ();
431  }
432  }
433 
434  if (negative)
435  num = -num;
436 
437  return is;
438 }
439 
440 static inline void
441 set_component (Complex& c, double num, bool imag)
442 {
443 #if defined (HAVE_CXX_COMPLEX_SETTERS)
444  if (imag)
445  c.imag (num);
446  else
447  c.real (num);
448 #elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)
449  if (imag)
450  c.imag () = num;
451  else
452  c.real () = num;
453 #else
454  if (imag)
455  c = Complex (c.real (), num);
456  else
457  c = Complex (num, c.imag ());
458 #endif
459 }
460 
461 Complex
462 octave::string::str2double (const std::string& str_arg)
463 {
464  Complex val (0.0, 0.0);
465 
466  std::string str = str_arg;
467 
468  // FIXME: removing all commas doesn't allow actual parsing.
469  // Example: "1,23.45" is wrong, but passes Octave.
470  str.erase (std::remove (str.begin (), str.end(), ','), str.end ());
471  std::istringstream is (str);
472 
473  double num;
474  bool i1, i2, s1, s2;
475 
476  if (is.eof ())
478  else if (! extract_num (is, num, i1, s1))
480  else
481  {
482  set_component (val, num, i1);
483 
484  if (! is.eof ())
485  {
486  if (! extract_num (is, num, i2, s2) || i1 == i2 || ! s2)
488  else
489  set_component (val, num, i2);
490  }
491  }
492 
493  return val;
494 }
495 
496 std::string
497 octave::string::u8_to_encoding (const std::string& who,
498  const std::string& u8_string,
499  const std::string& encoding)
500 {
501  const uint8_t *src = reinterpret_cast<const uint8_t *>
502  (u8_string.c_str ());
503  std::size_t srclen = u8_string.length ();
504 
505  std::size_t length;
506  char *native_str = octave_u8_conv_to_encoding (encoding.c_str (), src,
507  srclen, &length);
508 
509  if (! native_str)
510  {
511  if (errno == ENOSYS)
512  (*current_liboctave_error_handler)
513  ("%s: iconv() is not supported. Installing GNU libiconv and then "
514  "re-compiling Octave could fix this.", who.c_str ());
515  else
517  ("%s: converting from UTF-8 to codepage '%s' failed: %s",
518  who.c_str (), encoding.c_str (), std::strerror (errno));
519  }
520 
521  octave::unwind_action free_native_str ([=] () { ::free (native_str); });
522 
523  std::string retval = std::string (native_str, length);
524 
525  return retval;
526 }
527 
528 std::string
529 octave::string::u8_from_encoding (const std::string& who,
530  const std::string& native_string,
531  const std::string& encoding)
532 {
533  const char *src = native_string.c_str ();
534  std::size_t srclen = native_string.length ();
535 
536  std::size_t length;
537  uint8_t *utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src,
538  srclen, &length);
539  if (! utf8_str)
540  {
541  if (errno == ENOSYS)
542  (*current_liboctave_error_handler)
543  ("%s: iconv() is not supported. Installing GNU libiconv and then "
544  "re-compiling Octave could fix this.", who.c_str ());
545  else
547  ("%s: converting from codepage '%s' to UTF-8 failed: %s",
548  who.c_str (), encoding.c_str (), std::strerror (errno));
549  }
550 
551  octave::unwind_action free_utf8_str ([=] () { ::free (utf8_str); });
552 
553  std::string retval = std::string (reinterpret_cast<char *> (utf8_str), length);
554 
555  return retval;
556 }
557 
558 unsigned int
559 octave::string::u8_validate (const std::string& who,
560  std::string& in_str,
562 {
563  std::string out_str;
564 
565  unsigned int num_replacements = 0;
566  const char *in_chr = in_str.c_str ();
567  const char *inv_utf8 = in_chr;
568  const char *const in_end = in_chr + in_str.length ();
569  while (inv_utf8 && in_chr < in_end)
570  {
571  inv_utf8 = reinterpret_cast<const char *>
572  (octave_u8_check_wrapper (reinterpret_cast<const uint8_t *> (in_chr),
573  in_end - in_chr));
574 
575  if (inv_utf8 == nullptr)
576  out_str.append (in_chr, in_end - in_chr);
577  else
578  {
579  num_replacements++;
580  out_str.append (in_chr, inv_utf8 - in_chr);
581  in_chr = inv_utf8 + 1;
582 
583  if (type == U8_REPLACEMENT_CHAR)
584  out_str.append ("\xef\xbf\xbd");
585  else if (type == U8_ISO_8859_1)
586  {
587  std::string fallback = "iso-8859-1";
588  std::size_t lengthp;
589  uint8_t *val_utf8 = octave_u8_conv_from_encoding
590  (fallback.c_str (), inv_utf8, 1, &lengthp);
591 
592  if (! val_utf8)
593  (*current_liboctave_error_handler)
594  ("%s: converting from codepage '%s' to UTF-8 failed: %s",
595  who.c_str (), fallback.c_str (), std::strerror (errno));
596 
597  octave::unwind_action free_val_utf8
598  ([=] () { ::free (val_utf8); });
599 
600  out_str.append (reinterpret_cast<const char *> (val_utf8),
601  lengthp);
602  }
603  }
604  }
605 
606  in_str = out_str;
607  return num_replacements;
608 }
609 
613 
614 typename std::codecvt<InternT, ExternT, StateT>::result
615 octave::string::codecvt_u8::do_out
616  (StateT& /* state */,
617  const InternT* from, const InternT* from_end, const InternT*& from_next,
618  ExternT* to, ExternT* to_end, ExternT*& to_next) const
619 {
620  if (from_end < from)
621  return std::codecvt<InternT, ExternT, StateT>::noconv;
622 
623  // Convert from UTF-8 to output encoding
624  std::size_t srclen = (from_end-from) * sizeof (InternT);
625  std::size_t lengthp = (to_end-to) * sizeof (ExternT);
626  const uint8_t *u8_str = reinterpret_cast<const uint8_t *> (from);
627  char *enc_str = octave_u8_conv_to_encoding (m_enc.c_str (), u8_str, srclen,
628  &lengthp);
629 
630  size_t max = to_end - to;
631  if (lengthp < max)
632  max = lengthp;
633 
634  // copy conversion result to output
635  // FIXME: Handle incomplete UTF-8 characters at end of buffer.
636  std::copy_n (enc_str, max, to);
637  ::free (enc_str);
638 
639  from_next = from + srclen;
640  to_next = to + max;
641 
642  return std::codecvt<InternT, ExternT, StateT>::ok;
643 }
644 
645 typename std::codecvt<InternT, ExternT, StateT>::result
646 octave::string::codecvt_u8::do_in
647  (StateT& /* state */,
648  const ExternT* from, const ExternT* from_end, const ExternT*& from_next,
649  InternT* to, InternT* to_end, InternT*& to_next) const
650 {
651  // Convert from input encoding to UTF-8
652  std::size_t srclen = (from_end-from) * sizeof (ExternT);
653  std::size_t lengthp = (to_end-to) * sizeof (InternT);
654  const char *enc_str = reinterpret_cast<const char *> (from);
655  uint8_t *u8_str = octave_u8_conv_from_encoding (m_enc.c_str (),
656  enc_str, srclen, &lengthp);
657 
658  std::size_t max = to_end - to;
659  if (lengthp < max)
660  max = lengthp;
661 
662  // copy conversion result to output
663  std::copy_n (u8_str, max, to);
664  ::free (u8_str);
665 
666  from_next = from + srclen;
667  to_next = to + max;
668 
669  return std::codecvt<InternT, ExternT, StateT>::ok;
670 }
671 
672 int octave::string::codecvt_u8::do_length
673  (StateT& /* state */, const ExternT *src, const ExternT *end,
674  std::size_t max) const
675 {
676  // return number of external characters that produce MAX internal ones
677  std::size_t srclen = end-src;
678  std::size_t offsets[srclen];
679  std::size_t lengthp = max;
680  octave_u8_conv_from_encoding_offsets (m_enc.c_str (), src, srclen, offsets,
681  &lengthp);
682  std::size_t ext_char;
683  for (ext_char = 0; ext_char < srclen; ext_char++)
684  {
685  if (offsets[ext_char] != static_cast<size_t> (-1)
686  && offsets[ext_char] >= max)
687  break;
688  }
689 
690  return ext_char;
691 }
692 
693 
694 template <typename T>
695 std::string
696 rational_approx (T val, int len)
697 {
698  std::string s;
699 
700  if (len <= 0)
701  len = 10;
702 
703  static const T out_of_range_top
704  = static_cast<T>(std::numeric_limits<int>::max ()) + 1.;
705  static const T out_of_range_bottom
706  = static_cast<T>(std::numeric_limits<int>::min ()) - 1.;
707  if (octave::math::isinf (val))
708  {
709  if (val > 0)
710  s = "1/0";
711  else
712  s = "-1/0";
713  }
714  else if (octave::math::isnan (val))
715  s = "0/0";
716  else if (val <= out_of_range_bottom || val >= out_of_range_top
717  || octave::math::x_nint (val) == val)
718  {
719  std::ostringstream buf;
720  buf.flags (std::ios::fixed);
721  buf << std::setprecision (0) << octave::math::round (val);
722  s = buf.str ();
723  }
724  else
725  {
726  T lastn = 1;
727  T lastd = 0;
728  T n = octave::math::round (val);
729  T d = 1;
730  T frac = val - n;
731 
732  std::ostringstream init_buf;
733  init_buf.flags (std::ios::fixed);
734  init_buf << std::setprecision (0) << static_cast<int> (n);
735  s = init_buf.str ();
736 
737  while (true)
738  {
739  T flip = 1 / frac;
740  T step = octave::math::round (flip);
741  T nextn = n;
742  T nextd = d;
743 
744  // Have we converged to 1/intmax ?
745  if (std::abs (flip) > out_of_range_top)
746  {
747  lastn = n;
748  lastd = d;
749  break;
750  }
751 
752  frac = flip - step;
753  n = step * n + lastn;
754  d = step * d + lastd;
755  lastn = nextn;
756  lastd = nextd;
757 
758  std::ostringstream buf;
759  buf.flags (std::ios::fixed);
760  buf << std::setprecision (0) << static_cast<int> (n)
761  << '/' << static_cast<int> (d);
762 
763  if (n < 0 && d < 0)
764  {
765  // Double negative, string can be two characters longer.
766  if (buf.str ().length () > static_cast<unsigned int> (len + 2))
767  break;
768  }
769  else
770  {
771  if (buf.str ().length () > static_cast<unsigned int> (len))
772  break;
773  }
774 
775  if (std::abs (n) >= out_of_range_top
776  || std::abs (d) >= out_of_range_top)
777  break;
778 
779  s = buf.str ();
780  }
781 
782  if (lastd < 0)
783  {
784  // Move negative sign from denominator to numerator
785  lastd = - lastd;
786  lastn = - lastn;
787  std::ostringstream buf;
788  buf.flags (std::ios::fixed);
789  buf << std::setprecision (0) << static_cast<int> (lastn)
790  << '/' << static_cast<int> (lastd);
791  s = buf.str ();
792  }
793  }
794 
795  return s;
796 }
797 
798 // instantiate the template for float and double
799 template OCTAVE_API std::string rational_approx <float> (float val, int len);
800 template OCTAVE_API std::string rational_approx <double> (double val, int len);
#define Inf
Definition: Faddeeva.cc:260
#define NaN
Definition: Faddeeva.cc:261
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
OCTARRAY_OVERRIDABLE_FUNC_API bool isvector(void) const
Size of the specified dimension.
Definition: Array.h:654
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:414
OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:503
OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type rows(void) const
Definition: Array.h:459
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:143
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:41
#define octave_NA
Definition: lo-ieee.h:41
bool isinf(double x)
Definition: lo-mappers.h:203
double round(double x)
Definition: lo-mappers.h:136
bool isnan(bool)
Definition: lo-mappers.h:178
T x_nint(T x)
Definition: lo-mappers.h:269
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
#define OCTAVE_API
Definition: main.in.cc:55
octave_idx_type n
Definition: mx-inlines.cc:753
std::complex< double > Complex
Definition: oct-cmplx.h:33
static void set_component(Complex &c, double num, bool imag)
Definition: oct-string.cc:441
octave::string::codecvt_u8::ExternT ExternT
Definition: oct-string.cc:611
static double single_num(std::istringstream &is)
Definition: oct-string.cc:245
static bool str_data_cmp(const typename T::value_type *a, const typename T::value_type *b, const typename T::size_type n)
Definition: oct-string.cc:47
static bool is_imag_unit(int c)
Definition: oct-string.cc:241
#define INSTANTIATE_OCTAVE_STRING(T, API)
Definition: oct-string.cc:213
static std::istringstream & extract_num(std::istringstream &is, double &num, bool &imag, bool &have_sign)
Definition: oct-string.cc:301
octave::string::codecvt_u8::InternT InternT
Definition: oct-string.cc:610
static bool str_data_cmpi(const typename T::value_type *a, const typename T::value_type *b, const typename T::size_type n)
Definition: oct-string.cc:58
octave::string::codecvt_u8::StateT StateT
Definition: oct-string.cc:612
template OCTAVE_API std::string rational_approx< float >(float val, int len)
T::size_type numel(const T &str)
Definition: oct-string.cc:71
bool sizes_cmp(const T &str_a, const T &str_b)
Definition: oct-string.cc:92
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
template OCTAVE_API std::string rational_approx< double >(double val, int len)
std::string rational_approx(T val, int len)
Definition: oct-string.cc:696
OCTAVE_API unsigned int u8_validate(const std::string &who, std::string &in_string, const u8_fallback_type type=U8_REPLACEMENT_CHAR)
OCTAVE_API std::string u8_to_encoding(const std::string &who, const std::string &u8_string, const std::string &encoding)
OCTAVE_API bool strcmpi(const T &str_a, const T &str_b)
True if strings are the same, ignoring case.
OCTAVE_API bool strcmp(const T &str_a, const T &str_b)
Octave string utility functions.
u8_fallback_type
Definition: oct-string.h:152
@ U8_ISO_8859_1
Definition: oct-string.h:154
@ U8_REPLACEMENT_CHAR
Definition: oct-string.h:153
OCTAVE_API Complex str2double(const std::string &str_arg)
OCTAVE_API std::string u8_from_encoding(const std::string &who, const std::string &native_string, const std::string &encoding)
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 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.
void free(void *)
static T abs(T x)
Definition: pr-output.cc:1678
uint8_t * octave_u8_conv_from_encoding_offsets(const char *fromcode, const char *src, size_t srclen, size_t *offsets, size_t *lengthp)
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)
const uint8_t * octave_u8_check_wrapper(const uint8_t *src, size_t n)
F77_RET_T len
Definition: xerbla.cc:61