di 0.1.0
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 auto clone() const { return di::create<Self>(*this); }
120
121 constexpr void clear() { return string::clear(self()); }
122
123 constexpr auto operator[](usize index) -> CodePoint&
125 {
126 DI_ASSERT(index < self().size());
127 return vector::data(self())[index];
128 }
129
130 constexpr auto at(usize index) {
131 return lift_bool(index < self().size()) % [&] {
132 return self()[index];
133 };
134 }
135
136 constexpr auto c_str() const
137 requires(encoding::NullTerminated<Enc>)
138 {
139 if (self().empty()) {
140 return detail::empty_null_terminated_array<CodeUnit>;
141 }
142 DI_ASSERT(self().size() < self().capacity());
143 DI_ASSERT(string::data(self())[self().size()] == CodeUnit(0));
144 return string::data(self());
145 }
146
147 constexpr auto push_back(CodePoint code_point) { return string::push_back(self(), code_point); }
148
149 constexpr auto erase(Iterator first) {
150 DI_ASSERT(first != this->end());
151 return this->erase(first, next(first));
152 }
153 constexpr auto erase(Iterator first, Iterator last) -> Iterator {
154 if (first == last) {
155 return first;
156 }
157
158 if constexpr (encoding::NullTerminated<Enc>) {
159 self().assume_size(vector::size(self()) + 1);
160 }
161 auto result = encoding::make_iterator(self().encoding(), as_const(self()).span(),
163 string::string_to_vector_iterator(self(), last)) -
164 vector::begin(self()));
165 if constexpr (encoding::NullTerminated<Enc>) {
166 self().assume_size(vector::size(self()) - 1);
167 }
168 return result;
169 }
170 constexpr auto erase(usize offset, Optional<usize> count = {})
172 {
173 auto first = this->iterator_at_offset(offset);
174 auto last = [&] -> Iterator {
175 if (count) {
176 return this->iterator_at_offset(offset + *count).value_or(this->end());
177 }
178 return this->end();
179 }();
180 if (!first.has_value()) {
181 return this->end();
182 }
183 return erase(*first, last);
184 }
185
186 template<concepts::ContainerOf<CodePoint> Con>
187 constexpr auto append(Con&& container) -> decltype(auto) {
188 return invoke_as_fallible([&] {
189 return string::append(self(), di::forward<Con>(container));
190 }) % [&] {
191 return ref(self());
192 } | try_infallible;
193 }
194
195 template<concepts::ContainerOf<CodePoint> Con>
196 constexpr auto operator+=(Con&& container) -> decltype(auto) {
197 return this->append(di::forward<Con>(container));
198 }
199
200 constexpr auto pop_back() {
201 return this->back() % [&](auto value) {
202 this->erase(prev(this->end()));
203 return value;
204 };
205 }
206
207 constexpr auto insert(Iterator it, CodePoint code_point) { return this->insert(it, view::single(code_point)); }
208 constexpr auto insert(usize offset, CodePoint code_point)
210 {
211 auto it = this->iterator_at_offset(offset);
212 DI_ASSERT(it.has_value());
213 return this->insert(*it, view::single(code_point));
214 }
215
216 template<concepts::ContainerOf<CodePoint> Con>
217 constexpr auto insert(Iterator it, Con&& container) {
218 if constexpr (encoding::NullTerminated<Enc>) {
219 return ((invoke_as_fallible([&] {
221 di::forward<Con>(container) |
224 view::join);
225 }) %
226 [&](auto result) {
227 auto [first, last] = result;
228 return Tuple { first - vector::begin(self()), last - vector::begin(self()) };
229 }) >>
230 [&](auto result) {
231 return as_fallible(vector::emplace_back(self())) % [&](auto&&) {
232 vector::pop_back(self());
233 return result;
234 };
235 }) %
236 [&](auto result) {
237 auto [first, last] = result;
238 return View {
239 encoding::make_iterator(self().encoding(), as_const(self()).span(), first),
240 encoding::make_iterator(self().encoding(), as_const(self()).span(), last),
241 };
242 } |
244 } else {
245 return invoke_as_fallible([&] {
247 di::forward<Con>(container) |
250 view::join);
251 }) % [&](auto result) {
252 auto [first, last] = result;
253 return View {
254 encoding::make_iterator(self().encoding(), as_const(self()).span(), first - vector::begin(self())),
255 encoding::make_iterator(self().encoding(), as_const(self()).span(), last - vector::begin(self())),
256 };
257 } | try_infallible;
258 }
259 }
260
261 template<concepts::ContainerOf<CodePoint> Con>
263 constexpr auto insert(usize offset, Con&& container) {
264 auto first = this->iterator_at_offset(offset);
265 DI_ASSERT(first.has_value());
266 return this->insert(*first, di::forward<Con>(container));
267 }
268
269 constexpr auto replace(Iterator first, Iterator last, CodePoint code_point) {
270 return this->replace(first, last, view::single(code_point));
271 }
272 constexpr auto replace(usize offset, usize length, CodePoint code_point)
274 {
275 return this->replace(offset, length, view::single(code_point));
276 }
277
278 template<concepts::ContainerOf<CodePoint> Con>
279 constexpr auto replace(Iterator first, Iterator last, Con&& container) {
280 auto it = this->erase(first, last);
281 return this->insert(it, di::forward<Con>(container));
282 }
283
284 template<concepts::ContainerOf<CodePoint> Con>
286 constexpr auto replace(usize offset, usize length, Con&& container) {
287 auto first = this->iterator_at_offset(offset);
288 auto last = [&] -> Iterator {
289 if (length) {
290 return this->iterator_at_offset(offset + length).value_or(this->end());
291 }
292 return this->end();
293 }();
294 DI_ASSERT(first.has_value());
295 return this->replace(*first, last, di::forward<Con>(container));
296 }
297
298private:
299 template<typename F, SameAs<Tag<erase_if>> T = Tag<erase_if>>
301 constexpr friend auto tag_invoke(T, Self& self, F&& function) {
302 auto last = self.end();
303 auto fast = di::find_if(self.begin(), last, di::ref(function));
304 if (fast == last) {
305 return usize(0);
306 }
307
308 auto count = usize(1);
309 auto slow = string::string_to_vector_iterator(self, fast++);
310 while (fast != last) {
311 if (invoke(function, *fast)) {
312 ++count;
313 ++fast;
314 } else {
315 auto fast_start = string::string_to_vector_iterator(self, fast);
316 auto fast_end = string::string_to_vector_iterator(self, ++fast);
317 slow = copy(fast_start, fast_end, slow).out;
318 }
319 }
320
321 self.assume_size(vector::size(self) - (string::string_to_vector_iterator(self, last) - slow));
322 return count;
323 }
324};
325}
#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:200
constexpr auto push_back(CodePoint code_point)
Definition mutable_string_interface.h:147
constexpr friend auto tag_invoke(T, Self &self, F &&function)
Definition mutable_string_interface.h:301
constexpr auto at(usize index)
Definition mutable_string_interface.h:130
constexpr auto replace(Iterator first, Iterator last, Con &&container)
Definition mutable_string_interface.h:279
constexpr auto insert(Iterator it, Con &&container)
Definition mutable_string_interface.h:217
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:170
constexpr auto replace(usize offset, usize length, CodePoint code_point)
Definition mutable_string_interface.h:272
constexpr auto insert(usize offset, CodePoint code_point)
Definition mutable_string_interface.h:208
constexpr auto replace(usize offset, usize length, Con &&container)
Definition mutable_string_interface.h:286
constexpr auto insert(usize offset, Con &&container)
Definition mutable_string_interface.h:263
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:121
constexpr auto c_str() const
Definition mutable_string_interface.h:136
constexpr auto operator[](usize index) -> CodePoint &requires(encoding::Contiguous< Enc >)
Definition mutable_string_interface.h:123
constexpr auto insert(Iterator it, CodePoint code_point)
Definition mutable_string_interface.h:207
constexpr auto erase(Iterator first)
Definition mutable_string_interface.h:149
constexpr auto operator+=(Con &&container) -> decltype(auto)
Definition mutable_string_interface.h:196
constexpr auto append(Con &&container) -> decltype(auto)
Definition mutable_string_interface.h:187
constexpr auto clone() const
Definition mutable_string_interface.h:119
constexpr auto replace(Iterator first, Iterator last, CodePoint code_point)
Definition mutable_string_interface.h:269
constexpr auto erase(Iterator first, Iterator last) -> Iterator
Definition mutable_string_interface.h:153
Definition expected_forward_declaration.h:8
Definition optional_forward_declaration.h:5
Definition tuple.h:27
Definition unexpected.h:14
Definition operations.h:11
Definition container_of.h:9
Definition input_container.h:8
Definition relation.h:7
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
constexpr auto create(Args &&... args)
Definition create.h:21
Definition in_place_type.h:5