26#if defined (HAVE_CONFIG_H)
37#include <unordered_set>
50str_data_cmp (
const typename T::value_type *a,
const typename T::value_type *b,
51 const typename T::size_type n)
53 for (
typename T::size_type i = 0; i < n; ++i)
61str_data_cmpi (
const typename T::value_type *a,
const typename T::value_type *b,
62 const typename T::size_type n)
64 for (
typename T::size_type i = 0; i < n; ++i)
65 if (std::tolower (a[i]) != std::tolower (b[i]))
88strlen (
const typename T::value_type *str)
90 return std::strlen (str);
97 return str_a.size () == str_b.size ();
104 return str_a.
dims () == str_b.
dims ();
109sizes_cmp (
const T& str_a,
const typename T::value_type *str_b)
111 return str_a.size () == strlen<T> (str_b);
125octave::string::strcmp (
const T& str_a,
const T& str_b)
128 && str_data_cmp<T> (str_a.data (), str_b.data (),
numel (str_a)));
133octave::string::strcmp (
const T& str_a,
const typename T::value_type *str_b)
136 && str_data_cmp<T> (str_a.data (), str_b,
numel (str_a)));
142octave::string::strcmpi (
const T& str_a,
const T& str_b)
145 && str_data_cmpi<T> (str_a.data (), str_b.data (),
numel (str_a)));
150octave::string::strcmpi (
const T& str_a,
const typename T::value_type *str_b)
153 && str_data_cmpi<T> (str_a.data (), str_b,
numel (str_a)));
159octave::string::strncmp (
const T& str_a,
const T& str_b,
160 const typename T::size_type n)
162 typename T::size_type neff;
163 auto len_a =
numel (str_a);
164 auto len_b =
numel (str_b);
165 neff = std::min (std::max (len_a, len_b), n);
167 return (len_a >= neff && len_b >= neff
168 && str_data_cmp<T> (str_a.data (), str_b.data (), neff));
173octave::string::strncmp (
const T& str_a,
const typename T::value_type *str_b,
174 const typename T::size_type n)
176 typename T::size_type neff;
177 auto len_a =
numel (str_a);
178 auto len_b = strlen<T> (str_b);
179 neff = std::min (std::max (len_a, len_b), n);
181 return (len_a >= neff && len_b >= neff
182 && str_data_cmp<T> (str_a.data (), str_b, neff));
188octave::string::strncmpi (
const T& str_a,
const T& str_b,
189 const typename T::size_type n)
191 typename T::size_type neff;
192 auto len_a =
numel (str_a);
193 auto len_b =
numel (str_b);
194 neff = std::min (std::max (len_a, len_b), n);
196 return (len_a >= neff && len_b >= neff
197 && str_data_cmpi<T> (str_a.data (), str_b.data (), neff));
202octave::string::strncmpi (
const T& str_a,
const typename T::value_type *str_b,
203 const typename T::size_type n)
205 typename T::size_type neff;
206 auto len_a =
numel (str_a);
207 auto len_b = strlen<T> (str_b);
208 neff = std::min (std::max (len_a, len_b), n);
210 return (len_a >= neff && len_b >= neff
211 && str_data_cmpi<T> (str_a.data (), str_b, neff));
216#define INSTANTIATE_OCTAVE_STRING(T, API) \
217 template API bool octave::string::strcmp<T> (const T&, const T&); \
219 octave::string::strcmp<T> (const T&, const typename T::value_type*); \
220 template API bool octave::string::strcmpi<T> (const T&, const T&); \
222 octave::string::strcmpi<T> (const T&, const typename T::value_type*); \
224 octave::string::strncmp<T> (const T&, const T&, \
225 const typename T::size_type); \
227 octave::string::strncmp<T> (const T&, const typename T::value_type*, \
228 const typename T::size_type); \
230 octave::string::strncmpi<T> (const T&, const T&, \
231 const typename T::size_type n); \
233 octave::string::strncmpi<T> (const T&, const typename T::value_type*, \
234 const typename T::size_type);
241#undef INSTANTIATE_OCTAVE_STRING
245{
return c ==
'i' || c ==
'j'; }
248single_num (std::istringstream& is)
261 if (std::toupper (c) ==
'I')
267 if (std::tolower (c1) ==
'n' && std::tolower (c2) ==
'f')
269 num = octave::numeric_limits<double>::Inf ();
273 is.setstate (std::ios::failbit);
288 if (c1 ==
'a' && c2 ==
'N')
290 num = octave::numeric_limits<double>::NaN ();
294 is.setstate (std::ios::failbit);
303static std::istringstream&
304extract_num (std::istringstream& is,
double& num,
bool&
imag,
bool& have_sign)
306 have_sign =
imag =
false;
317 bool negative =
false;
320 if (c ==
'+' || c ==
'-')
346 num = (negative ? -1.0 : 1.0);
351 if (std::tolower (c) !=
'n')
375 num = single_num (is);
385 num = single_num (is);
409 if (is_imag_unit (c))
416 is.setstate (std::ios::failbit);
418 else if (is_imag_unit (c))
446#if defined (HAVE_CXX_COMPLEX_SETTERS)
451#elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)
465octave::string::str2double (
const std::string& str_arg)
469 std::string str = str_arg;
473 str.erase (std::remove (str.begin (), str.end(),
','), str.end ());
474 std::istringstream is (str);
480 val = octave::numeric_limits<double>::NaN ();
481 else if (! extract_num (is, num, i1, s1))
482 val = octave::numeric_limits<double>::NaN ();
485 set_component (val, num, i1);
489 if (! extract_num (is, num, i2, s2) || i1 == i2 || ! s2)
490 val = octave::numeric_limits<double>::NaN ();
492 set_component (val, num, i2);
500octave::string::u8_to_encoding (
const std::string& who,
501 const std::string& u8_string,
502 const std::string& encoding)
504 const uint8_t *src =
reinterpret_cast<const uint8_t *
>
505 (u8_string.c_str ());
506 std::size_t srclen = u8_string.length ();
515 (*current_liboctave_error_handler)
516 (
"%s: iconv() is not supported. Installing GNU libiconv and then "
517 "re-compiling Octave could fix this.", who.c_str ());
520 (
"%s: converting from UTF-8 to codepage '%s' failed: %s",
521 who.c_str (), encoding.c_str (), std::strerror (errno));
524 octave::unwind_action free_native_str ([native_str] () {
::free (native_str); });
526 std::string retval = std::string (native_str, length);
532octave::string::u8_from_encoding (
const std::string& who,
533 const std::string& native_string,
534 const std::string& encoding)
536 const char *src = native_string.c_str ();
537 std::size_t srclen = native_string.length ();
545 (*current_liboctave_error_handler)
546 (
"%s: iconv() is not supported. Installing GNU libiconv and then "
547 "re-compiling Octave could fix this.", who.c_str ());
550 (
"%s: converting from codepage '%s' to UTF-8 failed: %s",
551 who.c_str (), encoding.c_str (), std::strerror (errno));
554 octave::unwind_action free_utf8_str ([utf8_str] () {
::free (utf8_str); });
556 std::string retval = std::string (
reinterpret_cast<char *
> (utf8_str), length);
562octave::string::u8_validate (
const std::string& who,
564 const octave::string::u8_fallback_type type)
568 unsigned int num_replacements = 0;
569 const char *in_chr = in_str.c_str ();
570 const char *inv_utf8 = in_chr;
571 const char *
const in_end = in_chr + in_str.length ();
572 while (inv_utf8 && in_chr < in_end)
574 inv_utf8 =
reinterpret_cast<const char *
>
578 if (inv_utf8 ==
nullptr)
579 out_str.append (in_chr, in_end - in_chr);
583 out_str.append (in_chr, inv_utf8 - in_chr);
584 in_chr = inv_utf8 + 1;
587 out_str.append (
"\xef\xbf\xbd");
590 std::string fallback =
"iso-8859-1";
593 (fallback.c_str (), inv_utf8, 1, &lengthp);
596 (*current_liboctave_error_handler)
597 (
"%s: converting from codepage '%s' to UTF-8 failed: %s",
598 who.c_str (), fallback.c_str (), std::strerror (errno));
600 octave::unwind_action free_val_utf8 ([val_utf8] () {
::free (val_utf8); });
602 out_str.append (
reinterpret_cast<const char *
> (val_utf8),
609 return num_replacements;
613octave::string::u16_to_encoding (
const std::string& who,
614 const std::u16string& u16_string,
615 const std::string& encoding)
617 const uint16_t *src =
reinterpret_cast<const uint16_t *
>
618 (u16_string.c_str ());
619 std::size_t srclen = u16_string.length ();
628 (*current_liboctave_error_handler)
629 (
"%s: iconv() is not supported. Installing GNU libiconv and then "
630 "re-compiling Octave could fix this.", who.c_str ());
633 (
"%s: converting from UTF-16 to codepage '%s' failed: %s",
634 who.c_str (), encoding.c_str (), std::strerror (errno));
637 octave::unwind_action free_native_str ([native_str] () {
::free (native_str); });
639 std::string retval = std::string (native_str, length);
644std::vector<std::string>
645octave::string::get_encoding_list ()
647 static std::vector<std::string> encoding_list;
649 if (encoding_list.empty ())
651#if defined (HAVE_ICONVLIST)
653 std::size_t count = 0;
655 [] (
unsigned int num,
const char *
const *,
void *data) ->
int
657 std::size_t *count_ptr =
static_cast<std::size_t *
> (data);
663 if (count ==
static_cast<size_t> (-1))
665 encoding_list.push_back (
"UTF-8");
666 return encoding_list;
669# if defined (HAVE_ICONV_CANONICALIZE)
671 std::unordered_set<std::string> encoding_set;
672 encoding_set.reserve (count);
676 [] (
unsigned int num,
const char *
const *names,
void *data) ->
int
678 std::unordered_set<std::string> *encoding_set_ptr
679 =
static_cast<std::unordered_set<std::string> *
> (data);
680 for (std::size_t i = 0; i < num; i++)
682 const char *canonicalized_enc
684 encoding_set_ptr->insert (canonicalized_enc);
690 encoding_list.assign (encoding_set.begin (), encoding_set.end ());
774 std::sort (encoding_list.begin (), encoding_list.end ());
777 return encoding_list;
780typedef octave::string::codecvt_u8::InternT
InternT;
781typedef octave::string::codecvt_u8::ExternT
ExternT;
782typedef octave::string::codecvt_u8::StateT
StateT;
784typename std::codecvt<InternT, ExternT, StateT>::result
785octave::string::codecvt_u8::do_out
791 if (from_end <= from)
793 from_next = from_end;
794 return std::codecvt<InternT, ExternT, StateT>::noconv;
801 std::size_t pop_end = 0;
802 if ((*(from_end-1) & 0b10000000) == 0b10000000)
807 std::size_t num_bytes_in_buf = 1;
809 while (((*(from_end-num_bytes_in_buf) & 0b11000000) != 0b11000000)
810 && (num_bytes_in_buf < 4)
811 && (from_end-num_bytes_in_buf > from))
818 if ((((*(from_end-num_bytes_in_buf) & 0b11100000) == 0b11000000)
819 && (num_bytes_in_buf < 2))
820 || (((*(from_end-num_bytes_in_buf) & 0b11110000) == 0b11100000)
821 && (num_bytes_in_buf < 3))
822 || (((*(from_end-num_bytes_in_buf) & 0b11111000) == 0b11110000)
823 && (num_bytes_in_buf < 4)))
824 pop_end = num_bytes_in_buf;
826 from_next = from_end - pop_end;
828 std::size_t srclen = (from_end-from-pop_end) *
sizeof (
InternT);
829 std::size_t length = (to_end-to) *
sizeof (
ExternT);
830 if (srclen < 1 || length < 1)
831 return std::codecvt<InternT, ExternT, StateT>::partial;
834 const uint8_t *u8_str =
reinterpret_cast<const uint8_t *
> (from);
839 return std::codecvt<InternT, ExternT, StateT>::partial;
841 size_t max = (to_end - to) *
sizeof (
ExternT);
850 std::copy_n (enc_str,
max, to);
853 from_next = from + srclen;
856 return ((pop_end > 0 ||
max < length)
857 ? std::codecvt<InternT, ExternT, StateT>::partial
858 : std::codecvt<InternT, ExternT, StateT>::ok);
861typename std::codecvt<InternT, ExternT, StateT>::result
862octave::string::codecvt_u8::do_in
868 std::size_t srclen = (from_end-from) *
sizeof (
ExternT);
869 std::size_t lengthp = (to_end-to) *
sizeof (
InternT);
870 const char *enc_str =
reinterpret_cast<const char *
> (from);
872 enc_str, srclen, &lengthp);
874 std::size_t
max = to_end - to;
879 std::copy_n (u8_str,
max, to);
882 from_next = from + srclen;
885 return std::codecvt<InternT, ExternT, StateT>::ok;
888int octave::string::codecvt_u8::do_length
890 std::size_t
max)
const
893 std::size_t srclen = end-src;
895 std::size_t lengthp =
max;
898 std::size_t ext_char;
899 for (ext_char = 0; ext_char < srclen; ext_char++)
901 if (offsets[ext_char] !=
static_cast<size_t> (-1)
902 && offsets[ext_char] >=
max)
919 static constexpr T out_of_range_top
920 =
static_cast<T
> (std::numeric_limits<int>::max ()) + 1.0;
921 static constexpr T out_of_range_bottom
922 =
static_cast<T
> (std::numeric_limits<int>::min ()) - 1.0;
924 if (octave::math::isinf (val))
931 else if (octave::math::isnan (val))
933 else if (val <= out_of_range_bottom || val >= out_of_range_top
934 || octave::math::x_nint (val) == val)
936 std::ostringstream buf;
937 buf.flags (std::ios::fixed);
938 buf << std::setprecision (0) << octave::math::round (val);
945 T n = octave::math::round (val);
949 std::ostringstream init_buf;
950 init_buf.flags (std::ios::fixed);
951 init_buf << std::setprecision (0) << static_cast<int> (n);
957 T step = octave::math::round (flip);
962 if (std::abs (flip) > out_of_range_top)
970 n = step * n + lastn;
971 d = step *
d + lastd;
975 if (std::abs (n) >= out_of_range_top
976 || std::abs (
d) >= out_of_range_top)
979 std::ostringstream buf;
980 buf.flags (std::ios::fixed);
981 buf << std::setprecision (0) << static_cast<int> (n)
982 <<
'/' <<
static_cast<int> (
d);
987 if (buf.str ().length () >
static_cast<unsigned int> (
len + 2))
992 if (buf.str ().length () >
static_cast<unsigned int> (
len))
1004 std::ostringstream buf;
1005 buf.flags (std::ios::fixed);
1006 buf << std::setprecision (0) << static_cast<int> (lastn)
1007 <<
'/' <<
static_cast<int> (lastd);
charNDArray max(char d, const charNDArray &m)
N Dimensional Array with copy-on-write semantics.
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
bool isvector() const
Size of the specified dimension.
octave_idx_type rows() const
octave_idx_type numel() const
Number of elements in the array.
ColumnVector imag(const ComplexColumnVector &a)
void octave_iconvlist_wrapper(int(*do_one)(unsigned int namescount, const char *const *names, void *data), void *data)
const char * octave_iconv_canonicalize_wrapper(const char *name)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
std::complex< double > Complex
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
template std::string rational_approx< double >(double val, int len)
template std::string rational_approx< float >(float val, int len)
octave::string::codecvt_u8::ExternT ExternT
#define INSTANTIATE_OCTAVE_STRING(T, API)
octave::string::codecvt_u8::InternT InternT
octave::string::codecvt_u8::StateT StateT
T::size_type numel(const T &str)
bool sizes_cmp(const T &str_a, const T &str_b)
T::size_type strlen(const typename T::value_type *str)
std::string rational_approx(T val, int len)
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)
char * octave_u16_conv_to_encoding(const char *tocode, const uint16_t *src, size_t srclen, size_t *lengthp)
uint8_t * octave_u8_conv_from_encoding_offsets(const char *fromcode, const char *src, size_t srclen, size_t *offsets, size_t *lengthp)
const uint8_t * octave_u8_check_wrapper(const uint8_t *src, size_t n)