Iros
 
Loading...
Searching...
No Matches
mutable_string_interface.h
Go to the documentation of this file.
1#pragma once
2
21#include "di/meta/core.h"
22#include "di/platform/prelude.h"
33
34namespace di::container::string {
35namespace detail {
36 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
37 template<typename U, typename R = U[1]>
38 constexpr inline R empty_null_terminated_array = { U(0) };
39}
40
41template<typename Self, concepts::Encoding Enc>
43private:
44 using Encoding = Enc;
45 using CodeUnit = meta::EncodingCodeUnit<Enc>;
46 using CodePoint = meta::EncodingCodePoint<Enc>;
47 using Iterator = meta::EncodingIterator<Enc>;
48
49 constexpr auto self() -> Self& { return static_cast<Self&>(*this); }
50 constexpr auto self() const -> Self const& { return static_cast<Self const&>(*this); }
51
52 template<concepts::InputContainer Con, typename... Args>
55 encoding::AssumeValid, Args&&... args) {
56 auto result = Self(di::forward<Args>(args)...);
57 auto view = [&] {
58 if constexpr (encoding::NullTerminated<Enc>) {
59 return view::concat(di::forward<Con>(container), view::single(CodeUnit(0)));
60 } else {
61 return view::all(di::forward<Con>(container));
62 }
63 }();
64 return invoke_as_fallible([&] {
65 return vector::append_container(result, util::move(view));
66 }) % [&](auto&&...) {
67 return util::move(result);
69 }
70
71 template<concepts::InputContainer Con, typename... Args>
72 requires(!SameAs<CodeUnit, CodePoint> && concepts::ContainerOf<Con, CodeUnit> &&
73 concepts::ConstructibleFrom<Self, Args...>)
75 Args&&... args) {
76 auto result = Self(di::forward<Args>(args)...);
77 auto view = [&] {
78 if constexpr (encoding::NullTerminated<Enc>) {
79 return view::concat(di::forward<Con>(container), view::single(CodeUnit(0)));
80 } else {
81 return view::all(di::forward<Con>(container));
82 }
83 }();
84 if constexpr (encoding::Universal<Enc>) {
85 return invoke_as_fallible([&] {
86 return vector::append_container(result, util::move(view));
87 }) % [&](auto&&...) {
88 return util::move(result);
90 } else {
91 return (invoke_as_fallible([&] {
92 return vector::append_container(result, util::move(view));
93 }) >>
95 auto is_valid = encoding::validate(Enc {}, result.span());
96 if (!is_valid) {
97 return Unexpected(BasicError::InvalidArgument);
98 }
99 return {};
100 }) % [&] {
101 return util::move(result);
102 } | try_infallible;
103 }
104 }
105
106 template<concepts::InputContainer Con, typename... Args>
109 Args&&... args) {
110 auto result = Self(di::forward<Args>(args)...);
111 return invoke_as_fallible([&] {
112 return string::append(result, di::forward<Con>(container));
113 }) % [&] {
114 return util::move(result);
115 } | try_infallible;
116 }
117
118public:
119 constexpr void clear() { return string::clear(self()); }
120
121 constexpr auto operator[](usize index) -> CodePoint& requires(encoding::Contiguous<Enc>) {
122 DI_ASSERT(index < self().size());
123 return vector::data(self())[index];
124 }
125
126 constexpr auto at(usize index) {
127 return lift_bool(index < self().size()) % [&] {
128 return self()[index];
129 };
130 }
131
132 constexpr auto c_str() const
133 requires(encoding::NullTerminated<Enc>)
134 {
135 if (self().empty()) {
137 }
138 DI_ASSERT(self().size() < self().capacity());
139 DI_ASSERT(string::data(self())[self().size()] == CodeUnit(0));
140 return string::data(self());
141 }
142
143 constexpr auto push_back(CodePoint code_point) { return string::push_back(self(), code_point); }
144
145 constexpr auto erase(Iterator first) {
146 DI_ASSERT(first != this->end());
147 return this->erase(first, next(first));
148 }
149 constexpr auto erase(Iterator first, Iterator last) -> Iterator {
150 if (first == last) {
151 return first;
152 }
153
154 if constexpr (encoding::NullTerminated<Enc>) {
155 self().assume_size(vector::size(self()) + 1);
156 }
157 auto result = encoding::make_iterator(self().encoding(), as_const(self()).span(),
159 string::string_to_vector_iterator(self(), last)) -
160 vector::begin(self()));
161 if constexpr (encoding::NullTerminated<Enc>) {
162 self().assume_size(vector::size(self()) - 1);
163 }
164 return result;
165 }
166 constexpr auto erase(usize offset, Optional<usize> count = {})
168 {
169 auto first = this->iterator_at_offset(offset);
170 auto last = [&] -> Iterator {
171 if (count) {
172 return this->iterator_at_offset(offset + *count).value_or(this->end());
173 }
174 return this->end();
175 }();
176 if (!first.has_value()) {
177 return this->end();
178 }
179 return erase(*first, last);
180 }
181
182 template<concepts::ContainerOf<CodePoint> Con>
183 constexpr auto append(Con&& container) -> decltype(auto) {
184 return invoke_as_fallible([&] {
185 return string::append(self(), di::forward<Con>(container));
186 }) % [&] {
187 return ref(self());
188 } | try_infallible;
189 }
190
191 template<concepts::ContainerOf<CodePoint> Con>
192 constexpr auto operator+=(Con&& container) -> decltype(auto) {
193 return this->append(di::forward<Con>(container));
194 }
195
196 constexpr auto pop_back() {
197 return this->back() % [&](auto value) {
198 this->erase(prev(this->end()));
199 return value;
200 };
201 }
202
203 constexpr auto insert(Iterator it, CodePoint code_point) { return this->insert(it, view::single(code_point)); }
204 constexpr auto insert(usize offset, CodePoint code_point)
206 {
207 auto it = this->iterator_at_offset(offset);
208 DI_ASSERT(it.has_value());
209 return this->insert(*it, view::single(code_point));
210 }
211
212 template<concepts::ContainerOf<CodePoint> Con>
213 constexpr auto insert(Iterator it, Con&& container) {
214 if constexpr (encoding::NullTerminated<Enc>) {
215 return ((invoke_as_fallible([&] {
217 di::forward<Con>(container) |
220 view::join);
221 }) %
222 [&](auto result) {
223 auto [first, last] = result;
224 return Tuple { first - vector::begin(self()), last - vector::begin(self()) };
225 }) >>
226 [&](auto result) {
227 return as_fallible(vector::emplace_back(self())) % [&](auto&&) {
228 vector::pop_back(self());
229 return result;
230 };
231 }) %
232 [&](auto result) {
233 auto [first, last] = result;
234 return View {
235 encoding::make_iterator(self().encoding(), as_const(self()).span(), first),
236 encoding::make_iterator(self().encoding(), as_const(self()).span(), last),
237 };
238 } |
240 } else {
241 return invoke_as_fallible([&] {
243 di::forward<Con>(container) |
246 view::join);
247 }) % [&](auto result) {
248 auto [first, last] = result;
249 return View {
250 encoding::make_iterator(self().encoding(), as_const(self()).span(), first - vector::begin(self())),
251 encoding::make_iterator(self().encoding(), as_const(self()).span(), last - vector::begin(self())),
252 };
253 } | try_infallible;
254 }
255 }
256
257 template<concepts::ContainerOf<CodePoint> Con>
259 constexpr auto insert(usize offset, Con&& container) {
260 auto first = this->iterator_at_offset(offset);
261 DI_ASSERT(first.has_value());
262 return this->insert(*first, di::forward<Con>(container));
263 }
264
265 constexpr auto replace(Iterator first, Iterator last, CodePoint code_point) {
266 return this->replace(first, last, view::single(code_point));
267 }
268 constexpr auto replace(usize offset, usize length, CodePoint code_point)
270 {
271 return this->replace(offset, length, view::single(code_point));
272 }
273
274 template<concepts::ContainerOf<CodePoint> Con>
275 constexpr auto replace(Iterator first, Iterator last, Con&& container) {
276 auto it = this->erase(first, last);
277 return this->insert(it, di::forward<Con>(container));
278 }
279
280 template<concepts::ContainerOf<CodePoint> Con>
282 constexpr auto replace(usize offset, usize length, Con&& container) {
283 auto first = this->iterator_at_offset(offset);
284 auto last = [&] -> Iterator {
285 if (length) {
286 return this->iterator_at_offset(offset + length).value_or(this->end());
287 }
288 return this->end();
289 }();
290 DI_ASSERT(first.has_value());
291 return this->replace(*first, last, di::forward<Con>(container));
292 }
293
294private:
295 template<typename F, SameAs<Tag<erase_if>> T = Tag<erase_if>>
297 constexpr friend auto tag_invoke(T, Self& self, F&& function) {
298 auto last = self.end();
299 auto fast = di::find_if(self.begin(), last, di::ref(function));
300 if (fast == last) {
301 return usize(0);
302 }
303
304 auto count = usize(1);
305 auto slow = string::string_to_vector_iterator(self, fast++);
306 while (fast != last) {
307 if (invoke(function, *fast)) {
308 ++count;
309 ++fast;
310 } else {
311 auto fast_start = string::string_to_vector_iterator(self, fast);
312 auto fast_end = string::string_to_vector_iterator(self, ++fast);
313 slow = copy(fast_start, fast_end, slow).out;
314 }
315 }
316
317 self.assume_size(vector::size(self) - (string::string_to_vector_iterator(self, last) - slow));
318 return count;
319 }
320};
321}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition view.h:35
Definition constant_string_interface.h:33
constexpr auto size() const -> usize requires(encoding::Contiguous< Enc >)
Definition constant_string_interface.h:42
constexpr auto iterator_at_offset(usize index) const
Definition constant_string_interface.h:170
constexpr auto back() const
Definition constant_string_interface.h:73
constexpr auto view() const
Definition constant_string_interface.h:168
constexpr auto end() const
Definition constant_string_interface.h:70
constexpr auto empty() const -> bool
Definition constant_string_interface.h:65
Definition mutable_string_interface.h:42
constexpr auto pop_back()
Definition mutable_string_interface.h:196
constexpr auto push_back(CodePoint code_point)
Definition mutable_string_interface.h:143
constexpr friend auto tag_invoke(T, Self &self, F &&function)
Definition mutable_string_interface.h:297
constexpr auto at(usize index)
Definition mutable_string_interface.h:126
constexpr auto replace(Iterator first, Iterator last, Con &&container)
Definition mutable_string_interface.h:275
constexpr auto insert(Iterator it, Con &&container)
Definition mutable_string_interface.h:213
constexpr friend auto tag_invoke(types::Tag< util::create_in_place >, InPlaceType< Self >, Con &&container, Args &&... args)
Definition mutable_string_interface.h:74
constexpr friend auto tag_invoke(types::Tag< util::create_in_place >, InPlaceType< Self >, Con &&container, Args &&... args)
Definition mutable_string_interface.h:108
constexpr auto erase(usize offset, Optional< usize > count={})
Definition mutable_string_interface.h:166
constexpr auto replace(usize offset, usize length, CodePoint code_point)
Definition mutable_string_interface.h:268
constexpr auto insert(usize offset, CodePoint code_point)
Definition mutable_string_interface.h:204
constexpr auto replace(usize offset, usize length, Con &&container)
Definition mutable_string_interface.h:282
constexpr auto insert(usize offset, Con &&container)
Definition mutable_string_interface.h:259
constexpr friend auto tag_invoke(types::Tag< util::create_in_place >, InPlaceType< Self >, Con &&container, encoding::AssumeValid, Args &&... args)
Definition mutable_string_interface.h:54
constexpr void clear()
Definition mutable_string_interface.h:119
constexpr auto c_str() const
Definition mutable_string_interface.h:132
constexpr auto operator[](usize index) -> CodePoint &requires(encoding::Contiguous< Enc >)
Definition mutable_string_interface.h:121
constexpr auto insert(Iterator it, CodePoint code_point)
Definition mutable_string_interface.h:203
constexpr auto erase(Iterator first)
Definition mutable_string_interface.h:145
constexpr auto operator+=(Con &&container) -> decltype(auto)
Definition mutable_string_interface.h:192
constexpr auto append(Con &&container) -> decltype(auto)
Definition mutable_string_interface.h:183
constexpr auto replace(Iterator first, Iterator last, CodePoint code_point)
Definition mutable_string_interface.h:265
constexpr auto erase(Iterator first, Iterator last) -> Iterator
Definition mutable_string_interface.h:149
Definition expected_forward_declaration.h:8
Definition optional_forward_declaration.h:5
Definition tuple_forward_declaration.h:5
Definition unexpected.h:14
Definition operations.h:11
Definition container_of.h:9
Definition input_container.h:8
Definition relation.h:7
Definition mutable_string_interface.h:35
constexpr R empty_null_terminated_array
Definition mutable_string_interface.h:38
Definition encoding.h:25
constexpr auto validate
Definition encoding.h:135
constexpr auto convert_to_code_units
Definition encoding.h:139
constexpr auto make_iterator
Definition encoding.h:137
Definition constant_string_interface.h:31
constexpr auto data(concepts::detail::ConstantString auto const &string)
Definition string_data.h:6
constexpr auto append(Str &string, Con &&container)
Definition string_append.h:13
constexpr auto push_back(Str &string, P code_point)
Definition string_push_back.h:11
constexpr auto string_to_vector_iterator(Str &string, It it)
Definition string_to_vector_iterator.h:9
constexpr void clear(Str &string)
Definition string_clear.h:8
constexpr auto append_container(Vec &vector, Con &&container) -> R
Definition vector_append_container.h:21
constexpr auto pop_back(concepts::detail::MutableVector auto &vector)
Definition vector_pop_back.h:11
constexpr auto size(concepts::detail::ConstantVector auto const &vector) -> size_t
Definition vector_size.h:7
constexpr auto erase(Vec &vector, CIter cstart, CIter cend) -> Iter
Definition vector_erase.h:14
constexpr auto emplace_back(Vec &vector, Args &&... args) -> decltype(auto)
Definition vector_emplace_back.h:17
constexpr auto insert_container(Vec &vector, Cit it, Con &&container) -> R
Definition vector_append_container.h:31
constexpr auto begin(concepts::detail::ConstantVector auto &vector)
Definition vector_begin.h:7
constexpr auto data(concepts::detail::ConstantVector auto &vector)
Definition vector_data.h:6
constexpr auto join
Definition join.h:30
constexpr auto transform
Definition transform.h:28
constexpr auto single
Definition single.h:23
constexpr auto concat
Definition concat.h:35
constexpr auto all
Definition all.h:35
Definition sequence.h:12
constexpr auto prev
Definition prev.h:28
constexpr auto next
Definition next.h:35
constexpr auto replace
Definition replace.h:36
constexpr auto erase
Definition erase.h:76
constexpr auto count
Definition count.h:37
constexpr auto copy
Definition copy.h:30
Definition as_bool.h:8
constexpr auto bind_front(F &&f, Args &&... args)
Definition bind_front.h:68
RemoveCVRef< T >::CodeUnit EncodingCodeUnit
Definition encoding.h:16
RemoveCVRef< T >::CodePoint EncodingCodePoint
Definition encoding.h:19
RemoveCVRef< T >::Iterator EncodingIterator
Definition encoding.h:22
size_t usize
Definition integers.h:33
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto invoke_as_fallible
Definition invoke_as_fallible.h:37
constexpr auto ref
Definition reference_wrapper.h:98
constexpr auto invoke
Definition invoke.h:100
constexpr auto as_fallible
Definition as_fallible.h:26
constexpr auto try_infallible
Definition try_infallible.h:31
constexpr auto find_if
Definition find_if.h:31
constexpr auto lift_bool
Definition lift_bool.h:13
Definition in_place_type.h:5