26 #if defined (HAVE_CONFIG_H)
37 #include <unordered_set>
50 str_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)
61 str_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]))
88 strlen (
const typename T::value_type *str)
97 return str_a.size () == str_b.size ();
104 return str_a.
dims () == str_b.
dims ();
107 template <
typename T>
109 sizes_cmp (
const T& str_a,
const typename T::value_type *str_b)
111 return str_a.size () == strlen<T> (str_b);
128 && str_data_cmp<T> (str_a.data (), str_b.data (),
numel (str_a)));
136 && str_data_cmp<T> (str_a.data (), str_b,
numel (str_a)));
145 && str_data_cmpi<T> (str_a.data (), str_b.data (),
numel (str_a)));
153 && str_data_cmpi<T> (str_a.data (), str_b,
numel (str_a)));
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);
167 return (len_a >= neff && len_b >= neff
168 && str_data_cmp<T> (str_a.data (), str_b.data (), neff));
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);
181 return (len_a >= neff && len_b >= neff
182 && str_data_cmp<T> (str_a.data (), str_b, neff));
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);
196 return (len_a >= neff && len_b >= neff
197 && str_data_cmpi<T> (str_a.data (), str_b.data (), neff));
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);
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'; }
248 single_num (std::istringstream& is)
261 if (std::toupper (c) ==
'I')
267 if (std::tolower (c1) ==
'n' && std::tolower (c2) ==
'f')
273 is.setstate (std::ios::failbit);
288 if (c1 ==
'a' && c2 ==
'N')
294 is.setstate (std::ios::failbit);
303 static std::istringstream&
304 extract_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)
469 std::string str = str_arg;
473 str.erase (std::remove (str.begin (), str.end(),
','), str.end ());
474 std::istringstream is (str);
481 else if (! extract_num (is, num, i1, s1))
485 set_component (val, num, i1);
489 if (! extract_num (is, num, i2, s2) || i1 == i2 || ! s2)
492 set_component (val, num, i2);
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 ([=] () {
::free (native_str); });
526 std::string retval = std::string (native_str, length);
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 ([=] () {
::free (utf8_str); });
556 std::string retval = std::string (
reinterpret_cast<char *
> (utf8_str), length);
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
601 ([=] () {
::free (val_utf8); });
603 out_str.append (
reinterpret_cast<const char *
> (val_utf8),
610 return num_replacements;
615 const std::u16string& u16_string,
616 const std::string& encoding)
618 const uint16_t *src =
reinterpret_cast<const uint16_t *
>
619 (u16_string.c_str ());
620 std::size_t srclen = u16_string.length ();
629 (*current_liboctave_error_handler)
630 (
"%s: iconv() is not supported. Installing GNU libiconv and then "
631 "re-compiling Octave could fix this.", who.c_str ());
634 (
"%s: converting from UTF-16 to codepage '%s' failed: %s",
635 who.c_str (), encoding.c_str (), std::strerror (errno));
638 octave::unwind_action free_native_str ([=] () {
::free (native_str); });
640 std::string retval = std::string (native_str, length);
645 std::vector<std::string>
648 static std::vector<std::string> encoding_list;
650 if (encoding_list.empty ())
652 #if defined (HAVE_ICONVLIST)
654 std::size_t count = 0;
656 [] (
unsigned int num,
const char *
const *,
void *data) ->
int
658 std::size_t *count_ptr =
static_cast<std::size_t *
> (data);
664 if (count ==
static_cast<size_t> (-1))
666 encoding_list.push_back (
"UTF-8");
667 return encoding_list;
670 # if defined (HAVE_ICONV_CANONICALIZE)
672 std::unordered_set<std::string> encoding_set;
673 encoding_set.reserve (count);
677 [] (
unsigned int num,
const char *
const *names,
void *data) ->
int
679 std::unordered_set<std::string> *encoding_set_ptr
680 =
static_cast<std::unordered_set<std::string> *
> (data);
681 for (std::size_t i = 0; i < num; i++)
683 const char *canonicalized_enc
685 encoding_set_ptr->insert (canonicalized_enc);
691 encoding_list.assign (encoding_set.begin (), encoding_set.end ());
775 std::sort (encoding_list.begin (), encoding_list.end ());
778 return encoding_list;
785 typename std::codecvt<InternT, ExternT, StateT>::result
786 octave::string::codecvt_u8::do_out
792 if (from_end <= from)
794 from_next = from_end;
795 return std::codecvt<InternT, ExternT, StateT>::noconv;
802 std::size_t pop_end = 0;
803 if ((*(from_end-1) & 0b10000000) == 0b10000000)
808 std::size_t num_bytes_in_buf = 1;
810 while (((*(from_end-num_bytes_in_buf) & 0b11000000) != 0b11000000)
811 && (num_bytes_in_buf < 4)
812 && (from_end-num_bytes_in_buf > from))
819 if ((((*(from_end-num_bytes_in_buf) & 0b11100000) == 0b11000000)
820 && (num_bytes_in_buf < 2))
821 || (((*(from_end-num_bytes_in_buf) & 0b11110000) == 0b11100000)
822 && (num_bytes_in_buf < 3))
823 || (((*(from_end-num_bytes_in_buf) & 0b11111000) == 0b11110000)
824 && (num_bytes_in_buf < 4)))
825 pop_end = num_bytes_in_buf;
827 from_next = from_end - pop_end;
829 std::size_t srclen = (from_end-from-pop_end) *
sizeof (
InternT);
830 std::size_t length = (to_end-to) *
sizeof (
ExternT);
831 if (srclen < 1 || length < 1)
832 return std::codecvt<InternT, ExternT, StateT>::partial;
835 const uint8_t *u8_str =
reinterpret_cast<const uint8_t *
> (from);
840 return std::codecvt<InternT, ExternT, StateT>::partial;
842 size_t max = (to_end - to) *
sizeof (
ExternT);
851 std::copy_n (enc_str,
max, to);
854 from_next = from + srclen;
857 return ((pop_end > 0 ||
max < length)
858 ? std::codecvt<InternT, ExternT, StateT>::partial
859 : std::codecvt<InternT, ExternT, StateT>::ok);
862 typename std::codecvt<InternT, ExternT, StateT>::result
863 octave::string::codecvt_u8::do_in
869 std::size_t srclen = (from_end-from) *
sizeof (
ExternT);
870 std::size_t lengthp = (to_end-to) *
sizeof (
InternT);
871 const char *enc_str =
reinterpret_cast<const char *
> (from);
873 enc_str, srclen, &lengthp);
875 std::size_t
max = to_end - to;
880 std::copy_n (u8_str,
max, to);
883 from_next = from + srclen;
886 return std::codecvt<InternT, ExternT, StateT>::ok;
889 int octave::string::codecvt_u8::do_length
891 std::size_t
max)
const
894 std::size_t srclen = end-src;
896 std::size_t lengthp =
max;
899 std::size_t ext_char;
900 for (ext_char = 0; ext_char < srclen; ext_char++)
902 if (offsets[ext_char] !=
static_cast<size_t> (-1)
903 && offsets[ext_char] >=
max)
911 template <
typename T>
920 static const T out_of_range_top
922 static const T out_of_range_bottom
933 else if (val <= out_of_range_bottom || val >= out_of_range_top
936 std::ostringstream buf;
937 buf.flags (std::ios::fixed);
949 std::ostringstream init_buf;
950 init_buf.flags (std::ios::fixed);
951 init_buf << std::setprecision (0) << static_cast<int> (
n);
962 if (std::abs (flip) > out_of_range_top)
970 n = step *
n + lastn;
971 d = step *
d + lastd;
975 std::ostringstream buf;
976 buf.flags (std::ios::fixed);
977 buf << std::setprecision (0) << static_cast<int> (
n)
978 <<
'/' <<
static_cast<int> (
d);
983 if (buf.str ().length () >
static_cast<unsigned int> (
len + 2))
988 if (buf.str ().length () >
static_cast<unsigned int> (
len))
992 if (std::abs (
n) >= out_of_range_top
993 || std::abs (
d) >= out_of_range_top)
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)
charNDArray min(char d, const charNDArray &m)
bool isvector() const
Size of the specified dimension.
octave_idx_type rows() const
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
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)
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.
std::string u8_to_encoding(const std::string &who, const std::string &u8_string, const std::string &encoding)
bool strcmp(const T &str_a, const T &str_b)
Octave string utility functions.
std::vector< std::string > get_encoding_list()
Complex str2double(const std::string &str_arg)
bool strcmpi(const T &str_a, const T &str_b)
True if strings are the same, ignoring case.
std::string u16_to_encoding(const std::string &who, const std::u16string &u16_string, const std::string &encoding)
unsigned int u8_validate(const std::string &who, std::string &in_string, const u8_fallback_type type=U8_REPLACEMENT_CHAR)
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.
std::string u8_from_encoding(const std::string &who, const std::string &native_string, const std::string &encoding)
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)
char * octave_u16_conv_to_encoding(const char *tocode, const uint16_t *src, size_t srclen, size_t *lengthp)
const uint8_t * octave_u8_check_wrapper(const uint8_t *src, size_t n)