12 public ::const_string_range < ITERATOR_TYPE >
17 using BASE_RANGE = ::const_string_range < ITERATOR_TYPE >;
18 using RAW_CHARACTER_RANGE =
typename BASE_RANGE::RAW_CHARACTER_RANGE;
23 using THIS_RANGE = ::string_range < ITERATOR_TYPE >;
25 using STRING_RANGE = ::string_range < ITERATOR_TYPE >;
27 using STRING_BASE = ::string_base < ITERATOR_TYPE >;
29 using ITEM_POINTER = get_type_item_pointer<ITERATOR_TYPE>;
30 using ITEM = non_const<dereference<ITEM_POINTER> >;
31 using CHARACTER = ITEM;
34 using this_iterator =
typename BASE_RANGE::this_iterator;
35 using iterator =
typename BASE_RANGE::iterator;
36 using const_iterator =
typename BASE_RANGE::const_iterator;
39 using THIS_RAW_RANGE =
typename BASE_RANGE::THIS_RAW_RANGE;
40 using RAW_RANGE =
typename BASE_RANGE::RAW_RANGE;
41 using CONST_RAW_RANGE =
typename BASE_RANGE::CONST_RAW_RANGE;
50 using ARG_ITEM =
typename BASE_RANGE::ARG_ITEM;
53 template<::std::
size_t count>
54 constexpr string_range(
const ITEM(&array)[count]) : BASE_RANGE(array, array[count - 1] == 0 ? count - 1 : count) {}
56 template<prototype_
integral INTEGRAL>
57 constexpr string_range(const_iterator begin, INTEGRAL count) : BASE_RANGE((this_iterator)begin,
58 (this_iterator)(begin + count)) {}
62 string_range(nullptr_t) : BASE_RANGE(
nullptr) {}
66 template<typed_range<iterator> TYPED_RANGE>
67 constexpr string_range(
const TYPED_RANGE&
range)
68 requires(!::std::is_same_v < TYPED_RANGE, THIS_RANGE >) :
71 constexpr string_range(
const string_range &
range) :
74 constexpr string_range(string_range &&
range) :
75 BASE_RANGE(::transfer(
range)) { }
77 string_range(this_iterator begin, this_iterator end) : BASE_RANGE(begin, end) {}
78 string_range(this_iterator begin, this_iterator end, enum_range erange) : BASE_RANGE(begin, end, erange) {}
82 template <
character_count n >
83 string_range(
const CHARACTER(&s)[n]) : BASE_RANGE(s) {}
86 template < typed_character_pointer < typename ::string_range<ITERATOR_TYPE>::CHARACTER > CHARACTER_POINTER >
87 string_range(CHARACTER_POINTER start, CHARACTER_POINTER end, e_range erange) :
88 BASE_RANGE(start, end, erange) { }
91 template < prototype_block BLOCK >
92 string_range(
const BLOCK & block);
95 template <
character_po
inter CHARACTER_POINTER >
96 string_range(CHARACTER_POINTER start) : BASE_RANGE(start, start + string_safe_length(start)) {}
100 string_range(ITERATOR_TYPE psz, character_count len) : string_range(psz, 0, len) {}
104 string_range(ITERATOR_TYPE psz, character_count start, character_count count) : string_range(
105 ::_start_count_string_range(psz, start, count)) {}
112 using BASE_RANGE::last;
113 auto & last() { return ::get(this->end() - 1); }
164 using BASE_RANGE::data;
166 inline CHARACTER * data() {
return (CHARACTER *)this->begin(); }
171 this->m_begin =
nullptr;
172 this->m_end =
nullptr;
173 this->m_erange = e_range_none;
175 string_range& assign(const_iterator s, const_iterator e, enum_range erange)
179 this->m_erange = erange;
183 string_range& assign(const_iterator s, const_iterator e)
185 if (s != this->m_begin)
188 if (e != this->m_end)
191 this->m_erange = e_range_none;
210 template < prototype_
integral INTEGRAL >
211 string_range& assign(const_iterator s, INTEGRAL n)
214 return assign(s, s + n);
225 inline operator CHARACTER * () {
return this->data(); }
243 string_range &operator =(
const string_range &
range)
245 BASE_RANGE::operator=(
range);
249 template < prototype_range SOME_RANGE >
250 string_range &operator=(SOME_RANGE &&
range)
requires
251 (
sizeof(
typename SOME_RANGE::ITEM) ==
sizeof(ITEM))
254 auto pbasedataOld = this->m_pbasedata;
256 BASE_RANGE::operator=(
range);
261 ::base_data_defer_release(pbasedataOld);
272 range.m_begin =
nullptr;
274 range.m_end =
nullptr;
276 range.m_erange = e_range_none;
278 range.m_pbasedata =
nullptr;
1597 void shift_begin(::character_count size)
1603 this->m_begin += size;
1612 void shift_end(::character_count size)
1618 this->m_end += size;
1627 void set_begin(ITERATOR_TYPE p)
1630 if(this->m_begin != p)
1642 void set_end(ITERATOR_TYPE p)
1645 if(this->m_end != p)
1657 string_range & trim_left(
const SCOPED_STRING &
range) RELEASENOTHROW { shift_begin(this->count_left(
range));
1666 string_range & trim_right(
const SCOPED_STRING &
range) RELEASENOTHROW { shift_end(-this->count_right(
range));
return *
this; }
1670 string_range & trim(
const SCOPED_STRING &
range) RELEASENOTHROW { trim_left(
range); trim_right(
range);
return *
this; }
1672 bool paired_trim(CHARACTER character1, CHARACTER character2)
1675 if (this->size() < 2)
1682 if (this->first() != character1 || this->last() != character2)
1689 this->shift_begin(1);
1691 this->shift_end(-1);
1698 string_range& pair_trim_quotes()
1701 while (paired_trim(
'\"',
'\"') || paired_trim(
'\'',
'\''));
1711 if (this->size() <= 0)
1732 bool defer_consume_character(CHARACTER &
character)
1735 if (this->size() <= 0)
1751 ::i32 defer_consume_digit(::i32 iBase)
1756 if (!defer_consume_character(
character))
1795 ::collection::count consume(
bool(*character_is_function)(CHARACTER
character), character_count minimum_count);
1798 ::collection::count consume_spaces(character_count minimum_count = 0)
1801 return consume(&character_isspace, minimum_count);
1806 bool consume_line(string_range &
range)
1809 if (this->is_empty())
1816 auto p = this->find_first_character_in(
"\r\n");
1818 range.m_begin = this->m_begin;
1820 range.m_erange = e_range_none;
1827 if (*p ==
'\r' && *(p + 1) ==
'\n')
1846 range.m_end = this->m_end;
1848 this->m_begin = this->m_end;
1857 string_range consume_line()
1862 if (!consume_line(
range))
1878 bool defer_consume(
const SCOPED_STRING & scopedstr)
1881 if (!this->begins(scopedstr))
1888 this->begin() += scopedstr.size();
1894 string_range consume_word(
const SCOPED_STRING & scopedstrCharacters =
" ")
1897 return this->consume_token_until_any_character_in(scopedstrCharacters);
1904 if (this->is_empty())
1911 str = this->consume_token_until_any_character_in(scopedstrCharacters);
1918 bool begins_consume(const ::scoped_string & scopedstr);
1919 bool begins_consume(ansi_character ansich) {
return (*this->m_begin == ansich) ? (
static_cast<void>(this->m_begin++),
true) :
false; }
1920 bool begins_consume(::ansi_character & characterReturn, ansi_character ansich) {
return (
bool)(*this->m_begin == ansich) ? (
static_cast<void>(characterReturn = ansich),
static_cast<void>(this->m_begin++),
true) :
false; }
1921 bool begins_eat(const ::scoped_string & scopedstr);
1922 bool ends_eat(const ::scoped_string & scopedstr);
1923 bool case_insensitive_begins_eat(const ::scoped_string & scopedstr);
1924 bool case_insensitive_ends_eat(const ::scoped_string & scopedstr);
1925 void consume(const_char_pointer pszToConsume);
1927 void consume(const ::scoped_string & scopedstr);
1929 ::u64 consume_natural(::u64 uiMax = ((::u64)-1), ::u64 uiMin = 0);
1931 string_range consume_hex();
1933 string_range consume_non_spaces();
1935 string_range consume_nc_name();
1939 void no_escape_skip_quoted_value();
1946 void skip_quoted_value_ex();
1949 string_range consume_spaced_value();
1953 void consume_until_any_character_in(const ::scoped_string & scopedstr);
1956 string_range xml_consume_comment();
1958 string_base < ITERATOR_TYPE > consume_c_quoted_value();
1960 template <
bool bWriteOutput >
1963 string_range consume_utf8_char();
2004 THIS_RANGE& trim_left()
2007 return *
this = this->trimmed_left();
2012 THIS_RANGE& trim_right()
2015 return *
this = this->trimmed_right();
2023 return *
this = this->trimmed_right().trimmed_left();
2028 inline ::collection::count _count_parts_from_beginning(::collection::count cPathMaxPartCount, CHARACTER chPartSeparator)
2031 this->m_begin = this->__count_parts_from_beginning(cPathMaxPartCount, chPartSeparator);
2033 return cPathMaxPartCount;
2038 inline ::collection::count count_parts_from_beginning(::collection::count cPathPartCountToConsume, CHARACTER chSeparator)
2041 if (cPathPartCountToConsume <= 0)
2044 return cPathPartCountToConsume;
2048 return this->_count_parts_from_beginning(cPathPartCountToConsume, chSeparator);
2054 string_range consume_token_until_any_character_in(
const SCOPED_STRING& scopedstrCharacters,
bool bReturnSeparator =
false,
bool bSkipAnyCharactersIn =
true);