4#include "_const_string_range_impl.h"
5#include "_impl_const_string_range.h"
6#include "_impl_string_base.h"
7#include "_impl_string_base_allocation.h"
8#include "_impl_string_meta_data.h"
9#include "_impl_string_range.h"
14#include "unicode_impl.h"
22CLASS_DECL_ACME ::i64 strtoi(const ::scoped_string & scopedstr);
23CLASS_DECL_ACME ::i64 strtoi(const ::wide_character * psz);
67inline ::hash32 as_hash32 < const ansi_string & >(
const ansi_string & ansistr)
70 return as_hash32(ansistr.c_str());
76inline ::hash32 as_hash32 < const wide_string & >(
const wide_string & widestr)
79 return as_hash32(widestr.c_str());
125template <
typename CHAR_TYPE1,
typename CHAR_TYPE2 >
126void copy(::string_base < CHAR_TYPE1 >& str1, const ::string_base < CHAR_TYPE2 >& str2)
134template <
typename CHAR_TYPE1, prototype_
character CHARACTER, std::
size_t N >
135void copy(::string_base < CHAR_TYPE1 >& str1,
const CHARACTER sz[N])
143template <
typename CHAR_TYPE1, prototype_
character CHARACTER >
144void copy(::string_base < CHAR_TYPE1 >& str1,
const CHARACTER* psz)
155template < prototype_
string STRING, prototype_
integral INTEGRAL >
156inline STRING& copy(STRING&
string,
const INTEGRAL& number)
159 string.append_formatf(
"%lld", (::i64)number);
166template < prototype_
signed SIGNED, prototype_
string STRING >
167inline void copy(SIGNED& s,
const STRING&
string)
170 s = (SIGNED)string_to_signed(
string);
175template < prototype_natural NATURAL, prototype_
string STRING >
176inline void copy(NATURAL& n,
const STRING&
string)
179 n = (NATURAL)as_u64(
string);
184template < prototype_
floating FLOATING, prototype_
string STRING >
185inline void copy(FLOATING& f,
const STRING&
string)
188 f = (FLOATING)string_to_floating(
string);
193template < prototype_
string STRING, prototype_
floating FLOATING >
194inline STRING& copy(STRING&
string,
const FLOATING& number)
197 string.formatf(
"%f", (::f64)number);
224template < prototype_number NUMBER >
225inline string as_string(NUMBER number, const_char_pointer pszFormat)
230 str.formatf(pszFormat, number);
232 return ::transfer(str);
237template < prototype_
integral INTEGRAL >
238inline inline_number_string as_string(INTEGRAL i, ::i32 radix, enum_digit_case edigitcase)
241 inline_number_string numberstring;
243 __tosz(i, numberstring.m_end, radix, edigitcase);
272template < prototype_
floating FLOATING >
273inline ::string as_string(FLOATING f, const_char_pointer pszFormat)
278 str.formatf(pszFormat, f);
287inline ::hash32 as_hash32 < scoped_ansi_string >(
const scoped_ansi_string & scopedstr) {
289 return _scoped_string_u32_hash((const ::scoped_string_base<const_char_pointer >&) scopedstr);
295inline ::hash32 as_hash32 < scoped_wd16_string >(
const scoped_wd16_string & scopedstr) {
297 return _scoped_string_u32_hash((const ::scoped_string_base<const ::wd16_character *> &) scopedstr);
303inline ::hash32 as_hash32 < scoped_wd32_string >(
const scoped_wd32_string & scopedstr) {
305 return _scoped_string_u32_hash((const ::scoped_string_base<const ::wd32_character *> &) scopedstr);
325 inline path& path::operator /= (const ::scoped_string & scopedstr)
328 return *
this = (*
this / scopedstr);
333 inline path path::operator * (const ::scoped_string & scopedstr)
const
336 return ::transfer(this->sibling(scopedstr));
342 inline path& path::operator *= (const ::scoped_string & scopedstr)
345 this->operator = (::transfer(this->sibling(scopedstr)));
352 inline bool path::operator == (const ::string & str)
const
355 return ::string::operator == (str);
360 inline bool path::operator != (const ::scoped_string & scopedstr)
const
363 return operator != (
string(scopedstr));
377template <
typename TYPE, enum_type t_etypeContainer >
378inline void implode(
const numeric_array_base < TYPE, t_etypeContainer > & a,
string & str, const ::scoped_string & scopedstrSeparator, ::collection::index start, ::collection::count count)
383 start += a.get_size();
385 ::collection::index last;
388 last = a.get_size() + count;
392 last = start + count - 1;
397 ::collection::index i = start;
399 ::copy(str, a.element_at(i));
402 for(; i <= last; i++)
404 str += scopedstrSeparator + as_string(a.element_at(i));
418template <
typename TYPE, enum_type t_etypeContainer >
419inline string implode(
const numeric_array_base < TYPE, t_etypeContainer > & a,const ::scoped_string & scopedstrSeparator, ::collection::index start, ::collection::count count)
424 implode(a, str, scopedstrSeparator, start, count);
431template <
typename TYPE, ::enum_type t_etypeContainer >
432string surround_and_implode(
const numeric_array_base < TYPE, t_etypeContainer > & a, const ::scoped_string & scopedstrSeparator, const ::scoped_string & pszPrefix, const ::scoped_string & scopedstrSuffix, ::collection::index iStart, ::collection::count iCount)
435 string strSeparator(scopedstrSeparator);
436 string strPrefix(pszPrefix);
437 string strSuffix(scopedstrSuffix);
438 ::collection::index iEnd;
440 iStart = a.get_size() + iStart;
442 iEnd = a.get_size() + iCount;
444 iEnd = iStart + iCount - 1;
447 ::collection::index i = iStart;
448 str = strPrefix + as_string(a.element_at(i)) + strSuffix;
450 for(; i <= iEnd; i++)
452 str += strSeparator + strPrefix + as_string(a.element_at(i)) + strSuffix;
461template <
typename ITERATOR_TYPE >
462inline bool const_string_range < ITERATOR_TYPE > ::operator==(const ::character_range < const CHARACTER* >&
range)
const
465 return this->equals(
range);
470template <
typename ITERATOR_TYPE >
471template <
typename OTHER_CHARACTER >
472inline bool const_string_range < ITERATOR_TYPE > ::operator==(const ::character_range < const OTHER_CHARACTER* >&
range)
const
473requires other_primitive_character < OTHER_CHARACTER, CHARACTER >
484template<
typename BASE_TYPE>
485::collection::count string_range < BASE_TYPE>::consume(bool(*character_is_function)(
CHARACTER character), character_count minimum_count)
488 auto c = this->begins_count(character_is_function);
490 if (c < minimum_count)
493 throw_parsing_exception(
"didn't reached minimum count of characters meet character_is_function requirements");
505template <
typename ITERATOR_TYPE >
506string_base < ITERATOR_TYPE > const_string_range < ITERATOR_TYPE > ::lowered()
const
509 string_base < ITERATOR_TYPE > str(*
this);
519template <
typename ITERATOR_TYPE >
520string_base < ITERATOR_TYPE > const_string_range < ITERATOR_TYPE > ::uppered()
const
523 string_base < ITERATOR_TYPE > str(*
this);
532template <
typename ITERATOR_TYPE >
533string_base < ITERATOR_TYPE > string_range < ITERATOR_TYPE > ::consume_quoted_value()
536 auto pszStart = this->m_begin;
538 if (*pszStart !=
'\"' && *pszStart !=
'\'')
541 throw_parsing_exception(
"Quote character is required here");
547 string_base <ITERATOR_TYPE> str;
549 if (!defer_consume_quoted_value(str))
552 throw_parsing_exception(
"Quote character is required here, premature end");
561template <
typename ITERATOR_TYPE >
562bool string_range < ITERATOR_TYPE > ::defer_consume_quoted_value(string_base <ITERATOR_TYPE> & str)
567 auto pszStart = this->m_begin;
569 if (*pszStart !=
'\"' && *pszStart !=
'\'')
576 ::i8 quoting_character = *this->m_begin;
580 const typename ::string_range < ITERATOR_TYPE>::CHARACTER * pszValueStart = this->m_begin;
582 while (*this->m_begin != quoting_character)
587 this->m_begin = unicode_next(this->m_begin);
589 if (this->is_empty() || *this->m_begin ==
'\0')
596 if (*this->m_begin ==
'\\')
599 this->m_begin = unicode_next(this->m_begin);
601 if (this->is_empty())
614 str.assign(pszValueStart, this->m_begin - pszValueStart);
618 auto p = str.get_buffer();
620 auto pend = p + str.length();
631 memory_transfer(p, p + 1, pend - p);
633 else if (p[1] ==
'\"')
636 memory_transfer(p, p + 1, pend - p);
656inline ::hash32 as_hash32 < ansi_string >(
const ansi_string & ansistr)
659 return as_hash32 < const ansi_string & >(ansistr);
665inline ::hash32 as_hash32 < wide_string >(
const wide_string & widestr)
668 return as_hash32 < const wide_string & >(widestr);
673template <
typename ITERATOR_TYPE >
674void string_range < ITERATOR_TYPE >::consume(const_char_pointer pszToConsume)
680 if (*this->m_begin != *pszToConsume)
683 throw_parsing_exception(
"Name does not match expected");
696template <
typename ITERATOR_TYPE >
697bool string_range < ITERATOR_TYPE >::begins_consume(const ::scoped_string & scopedstr)
700 if(scopedstr.size() > 0)
703 if (!this->begins(scopedstr))
717 this->m_begin += scopedstr.size();
726template <
typename ITERATOR_TYPE >
727bool string_range < ITERATOR_TYPE >::begins_eat(const ::scoped_string & scopedstr)
730 if(scopedstr.size() > 0)
733 if (!this->begins(scopedstr))
747 this->m_begin += scopedstr.size();
756template <
typename ITERATOR_TYPE >
757bool string_range < ITERATOR_TYPE >::ends_eat(const ::scoped_string & scopedstr)
760 if(scopedstr.size() > 0)
763 if (!this->ends(scopedstr))
777 this->m_end -= scopedstr.size();
787template <
typename ITERATOR_TYPE >
788bool string_range < ITERATOR_TYPE >::case_insensitive_begins_eat(const ::scoped_string & scopedstr)
791 if(scopedstr.size() > 0)
794 if (!this->case_insensitive_begins(scopedstr))
808 this->m_begin += scopedstr.size();
817template <
typename ITERATOR_TYPE >
818bool string_range < ITERATOR_TYPE >::case_insensitive_ends_eat(const ::scoped_string & scopedstr)
821 if(scopedstr.size() > 0)
824 if (!this->case_insensitive_ends(scopedstr))
838 this->m_end -= scopedstr.size();
847template <
typename ITERATOR_TYPE >
848void string_range < ITERATOR_TYPE >::consume(const ::scoped_string & scopedstr)
851 auto rangeToConsume = scopedstr();
853 while(rangeToConsume.has_character())
856 if(this->is_empty() || (*this->m_begin != *rangeToConsume.m_begin))
859 throw_parsing_exception(
"Name does not match expected");
865 rangeToConsume.m_begin++;
909template <
typename ITERATOR_TYPE >
910::u64 string_range < ITERATOR_TYPE >::consume_natural(::u64 uMax, ::u64 uMin)
916 throw ::exception(error_bad_argument,
"maximum should be greater than minimum");
920 auto pszStart = this->m_begin;
926 while (unicode_is_digit(this->m_begin))
929 this->m_begin = unicode_next(this->m_begin);
935 if (this->m_begin == pszStart)
938 throw_parsing_exception(
"empty natural found");
942 u = ::as_u32({ pszStart, this->m_begin - pszStart });
947 throw_parsing_exception(
"natural less than minimum");
953 throw_parsing_exception(
"natural greater than maximum");
1006template <
typename ITERATOR_TYPE >
1007string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::consume_non_spaces()
1010 auto pszStart = this->m_begin;
1012 while (!unicode_is_whitespace(this->m_begin))
1015 this->m_begin = unicode_next(this->m_begin);
1017 if (this->is_empty())
1026 return { pszStart, this->m_begin - pszStart };
1031template <
typename ITERATOR_TYPE >
1032string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::consume_hex()
1035 auto pszStart = this->m_begin;
1037 while (this->is_empty())
1042 ::i64 i = unicode_index_length(this->m_begin, len);
1044 if ((i >=
'0' && i <=
'9') || (i >=
'a' && i <=
'f') || (i >=
'A' && i <=
'F'))
1047 this->m_begin += len;
1059 if (this->m_begin == pszStart)
1062 throw_parsing_exception(
"no hex consumed");
1068 return { pszStart, this->m_begin - pszStart };
1073template <
typename ITERATOR_TYPE >
1074string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::consume_nc_name()
1077 auto pszStart = this->m_begin;
1079 if (this->is_empty() || !unicode_is_letter(this->m_begin))
1082 throw_parsing_exception(
"NCName required here");
1091 this->m_begin = unicode_next(this->m_begin);
1093 }
while(this->has_character() &&
1094 (unicode_is_letter_or_digit(this->m_begin)
1095 || *this->m_begin ==
'_' || *this->m_begin ==
'-'));
1097 return { pszStart, this->m_begin - pszStart };
1200template <
typename ITERATOR_TYPE >
1204 const_char_pointer pszStart = this->m_begin;
1206 no_escape_skip_quoted_value();
1208 return { pszStart + 1, this->m_begin - pszStart - 2 };
1213template <
typename ITERATOR_TYPE >
1214void string_range < ITERATOR_TYPE >::no_escape_skip_quoted_value()
1217 if (*this->m_begin !=
'\"' && *this->m_begin !=
'\\')
1220 throw_parsing_exception(
"Quote character is required here");
1226 ::i8 quoting_character = *this->m_begin;
1230 while (*this->m_begin != quoting_character)
1233 this->m_begin = unicode_next(this->m_begin);
1235 if (this->is_empty())
1238 throw_parsing_exception(
"Quote character is required here, premature end");
1251template <
typename ITERATOR_TYPE >
1257 this->_consume_quoted_value_ex<true>(&str);
1264template <
typename ITERATOR_TYPE >
1265void string_range < ITERATOR_TYPE >::skip_quoted_value_ex()
1268 this->_consume_quoted_value_ex<false>(
nullptr);
1273template <
typename ITERATOR_TYPE >
1274string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::consume_spaced_value()
1277 this->consume_spaces(0);
1279 if (this->is_empty())
1286 auto pszStart = this->m_begin;
1288 while (this->has_character() && !ansi_char_isspace(*this->m_begin))
1295 if (this->m_begin == pszStart)
1298 throw_parsing_exception(
"No spaced value to consumer");
1302 return { pszStart, this->m_begin - pszStart };
1340template <
typename ITERATOR_TYPE >
1344 this->consume_spaces(0);
1346 if (*this->m_begin ==
'\"' || *this->m_begin ==
'\'')
1349 return this->consume_quoted_value();
1355 return this->consume_spaced_value();
1362template <
typename ITERATOR_TYPE >
1363void string_range < ITERATOR_TYPE >::consume_until_any_character_in(const ::scoped_string & scopedstr)
1366 this->m_begin = this->find_first_character_in(scopedstr);
1368 if (not_found(this->m_begin))
1371 throw_parsing_exception(
"Not found any character in \"" + scopedstr +
"\"");
1411template <
typename ITERATOR_TYPE >
1417 if (*this->m_begin !=
'\"' && *this->m_begin !=
'\\')
1420 throw_parsing_exception(
"Quote character is required here");
1426 auto quoting_character = this->consume_utf8_char();
1428 STRING_RANGE rangeCurrentChar;
1432 STRING_RANGE rangePreviousChar;
1434 while (this->has_character())
1439 rangePreviousChar = rangeCurrentChar;
1441 rangeCurrentChar = this->consume_utf8_char();
1445 if (rangeCurrentChar.is_empty())
1448 throw_parsing_exception(
"Quote character is required here, premature end");
1454 if (rangePreviousChar ==
"\\")
1457 str += rangeCurrentChar;
1459 rangeCurrentChar.m_begin =
nullptr;
1460 rangeCurrentChar.m_end =
nullptr;
1463 else if (rangeCurrentChar ==
"\\")
1470 if (rangeCurrentChar == quoting_character)
1477 str += rangeCurrentChar;
1483 this->consume_utf8_char();
1491template <
typename ITERATOR_TYPE >
1492template <
bool bWriteOutput >
1496 ::i8 quoting_character = *this->m_begin;
1498 if (quoting_character !=
'\"' && quoting_character !=
'\'')
1501 throw_parsing_exception(
"Quote character is required here, premature end");
1509 const_char_pointer pszNext = this->m_begin;
1514 pszNext = unicode_next(this->m_begin);
1516 if (pszNext > this->m_end)
1519 throw_parsing_exception(
"Quote character is required here, premature end");
1530 if (*this->m_begin ==
'\0')
1533 throw_parsing_exception(
"Quote character is required here, premature end");
1543 else if (*this->m_begin == quoting_character)
1551 else if (*this->m_begin ==
'\\')
1554 this->m_begin = pszNext;
1556 pszNext = unicode_next(this->m_begin);
1558 if (pszNext > this->m_end)
1561 throw_parsing_exception(
"Quote character is required here, premature end");
1572 if (*this->m_begin ==
'n')
1578 pstrOut->append_character(
'\n');
1583 else if (*this->m_begin ==
't')
1589 pstrOut->append_character(
'\t');
1594 else if (*this->m_begin ==
'r')
1600 pstrOut->append_character(
'\r');
1605 else if (*this->m_begin ==
'u')
1612 u16a[0] = ::hex::parse_u16_exc(*
this);
1614 if (utf16_is_1st_surrogate(u16a[0]))
1617 if (*this->m_begin !=
'\\')
1620 throw_parsing_exception(
"expect back slash here (for low surrogate)");
1626 if (*this->m_begin !=
'u' && *this->m_begin !=
'U')
1629 throw_parsing_exception(
"expect 'u' character here (for low surrogate)");
1635 u16a[1] = ::hex::parse_u16_exc(*
this);
1637 if (!utf16_is_2nd_surrogate(u16a[1]))
1640 throw_parsing_exception(
"expect low surrogate");
1649 ::wd32_character uni = (::wd32_character)decode_utf16_pair(u16a);
1651 string strUtf8 = wd32_to_ansi_str(&uni, 1);
1653 pstrOut->append(strUtf8);
1666 ::wd32_character uni = u16a[0];
1668 string strUtf8 = wd32_to_ansi_str(&uni, 1);
1670 pstrOut->append(strUtf8);
1676 pszNext = this->m_begin;
1679 else if (*this->m_begin ==
'\"')
1685 pstrOut->append_character(
'\"');
1696 pstrOut->append(this->m_begin, pszNext - this->m_begin);
1709 pstrOut->append(this->m_begin, pszNext - this->m_begin);
1715 this->m_begin = pszNext;
1724template <
typename ITERATOR_TYPE >
1725string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::xml_consume_comment()
1728 this->consume(
"<!--");
1730 auto pszStart = this->m_begin;
1732 while (this->m_begin[0] !=
'-' || this->m_begin[1] !=
'-' || this->m_begin[2] !=
'>')
1735 if (this->is_empty() || *this->m_begin ==
'\0')
1742 this->m_begin = unicode_next(this->m_begin);
1748 return { pszStart, this->m_begin - pszStart - 3 };
1763template <
typename ITERATOR_TYPE >
1767 while (this->has_character() && *this->m_begin)
1770 if (escape != 0 && *this->m_begin == escape)
1773 if (*this->m_begin == ch)
1799template <
typename ITERATOR_TYPE >
1803 const_char_pointer prev_escape =
nullptr;
1805 while (this->has_character() && *this->m_begin)
1808 if (escape != 0 && *this->m_begin == escape && prev_escape ==
nullptr)
1811 prev_escape = this->m_begin;
1817 prev_escape =
nullptr;
1819 if (ansi_chr(chset, *this->m_begin))
1842template <
typename ITERATOR_TYPE >
1846 const_char_pointer prev_escape =
nullptr;
1848 while (this->has_character() && *this->m_begin)
1851 if (escape != 0 && *this->m_begin == escape && prev_escape ==
nullptr)
1854 prev_escape = this->m_begin;
1860 prev_escape =
nullptr;
1889template <
typename ITERATOR_TYPE >
1893 auto pTarget = this->m_begin;
1895 auto pSource = rangeSource.m_begin;
1897 bool bEscaping =
false;
1899 while(pSource < rangeSource.m_end && pTarget < this->m_end)
1907 *pTarget++ = *pSource;
1910 else if(*pSource == escape)
1919 *pTarget++ = *pSource;
1929 this->m_end = pTarget;
1936template <
typename ITERATOR_TYPE >
1937string_range < ITERATOR_TYPE > string_range < ITERATOR_TYPE >::consume_utf8_char()
1940 auto pszStart = this->m_begin;
1942 this->m_begin = unicode_next(pszStart);
1944 return { pszStart, minimum(this->m_begin, this->m_end) };
1951template <
typename T >
1952inline void write_text_stream::print_string_copy(
const T & t)
1965template < prototype_
character CHARACTER2,
character_count sizeMaximumLength >
1966inline write_text_stream & write_text_stream::operator <<(const ::inline_string < CHARACTER2, sizeMaximumLength > & inlinestring)
1969 if (this->fmtflags() & ::file::network_payload)
1976 write(inlinestring.data(), inlinestring.size());
1978 if (this->fmtflags() & ::file::network_payload)
1985 if (this->fmtflags() & ::file::separated)
1988 print(m_chSeparator);
Definition aaa_character.h:10
::std::strong_ordering escape_case_insensitive_count_order(const ::scoped_string &scopedstr, ::i32 escape) const
Definition _impl_const_string_range.h:195
Definition fixed_alloc.h:125
void escape_copy(::i8 escape, const ::const_ansi_range &rangeSource)
Definition _impl.h:1890
Definition string_base.h:90
void escape_skip_to_character(::i32 ch, ::i32 escape)
Definition _impl.h:1764
void escape_case_insensitive_skip_to(const ::scoped_string &scopedstr, ::i32 escape)
Definition _impl.h:1843
void escape_skip_to_first_character_in(const_char_pointer chset, ::i32 escape)
Definition _impl.h:1800
Definition write_text_stream.h:43
Definition filesystem.h:16