7#ifndef OCL_TPROC_ROPE_FWD_INL
8#define OCL_TPROC_ROPE_FWD_INL
10#include <boost/system/error_code.hpp>
16 template <
class CharT,
class Traits,
class Allocator>
19 using char_type = CharT;
20 using value_type = char_type;
21 using size_type =
typename std::allocator_traits<Allocator>::size_type;
22 using error_type = boost::system::error_code;
23 using allocator_type = Allocator;
27 rope_ptr left_{
nullptr};
28 rope_ptr right_{
nullptr};
31 value_type* blob_{
nullptr};
32 allocator_type alloc_;
33 size_type capacity_{0};
43 return blob_ !=
nullptr;
46 tree_impl(
const boost::core::basic_string_view<CharT>& str,
47 Allocator alloc = Allocator())
48 : weight_(str.size()), alloc_(alloc), capacity_(str.size())
52 blob_ = alloc_.allocate(capacity_);
55 detail::throw_bad_alloc();
57 ::memset(blob_, 0, capacity_);
58 Traits::copy(blob_, str.data(), weight_);
64 Allocator alloc = Allocator())
65 : left_(left), right_(right), alloc_(alloc)
67 weight_ = left ? left->impl_->total_size() : 0;
72 if (blob_ && capacity_ > 0)
74 alloc_.deallocate(blob_, capacity_);
78 size_type total_size()
const
85 return weight_ + (right_ ? right_->impl_->total_size() : 0);
88 size_type size()
const
93 CharT at(size_type pos)
const
99 throw std::out_of_range(
"rope index out of range");
109 throw std::out_of_range(
"null left child");
110 return left_->impl_->at(pos);
115 throw std::out_of_range(
"null right child");
116 return right_->impl_->at(pos - weight_);
121 rope_ptr concat(rope_ptr left,
130 right->impl_->left_ = left;
131 left->impl_->right_ = right;
136 std::pair<rope_ptr, rope_ptr> split(size_type pos, rope_ptr this_rope, Allocator alloc = Allocator())
142 return {
nullptr, this_rope};
145 return {this_rope,
nullptr};
147 auto left_view = boost::core::basic_string_view<CharT>(blob_, pos);
148 auto right_view = boost::core::basic_string_view<CharT>(blob_ + pos, weight_ - pos);
153 detail::throw_bad_alloc();
162 detail::throw_bad_alloc();
165 return {left_rope, right_rope};
171 auto [ll, lr] = left_->impl_->split(pos, left_, alloc);
172 return {ll, concat(lr, right_, alloc)};
174 else if (pos > weight_)
176 auto [rl, rr] = right_->impl_->split(pos - weight_, right_, alloc);
177 return {concat(left_, rl, alloc), rr};
181 return {left_, right_};
185 rope_ptr insert(size_type pos,
const boost::core::basic_string_view<CharT>& str, rope_ptr this_rope, Allocator alloc = Allocator())
187 auto [left, right] = split(pos, this_rope, alloc);
189 return concat(concat(left, middle, alloc), right, alloc);
192 rope_ptr substr(size_type pos, size_type len, rope_ptr this_rope, Allocator alloc = Allocator())
194 auto [_, right] = split(pos, this_rope, alloc);
202 auto [result, __] = right->impl_->split(len, right, alloc);
207 bool starts_with(
const boost::core::basic_string_view<CharT>& prefix)
const
209 if (prefix.size() > total_size())
213 return check_prefix(prefix, checked);
216 bool ends_with(
const boost::core::basic_string_view<CharT>& suffix)
const
218 size_type total = total_size();
220 if (suffix.size() > total)
223 size_type start_pos = total - suffix.size();
224 return check_suffix(suffix, start_pos, 0);
227 bool equals(
const tree_impl* other)
const
231 if (total_size() != other->total_size())
235 size_type sz = total_size();
236 for (size_type i = 0; i < sz; ++i)
238 if (at(i) != other->at(i))
244 bool equals(
const boost::core::basic_string_view<CharT>& str)
const
246 if (total_size() != str.size())
249 for (size_type i = 0; i < str.size(); ++i)
258 bool check_prefix(
const boost::core::basic_string_view<CharT>& prefix, size_type& checked)
const
262 size_type to_check = std::min(weight_, prefix.size() - checked);
264 if (Traits::compare(blob_, prefix.c_str() + checked, to_check) != 0)
268 return checked >= prefix.size();
272 if (left_ && !left_->impl_->check_prefix(prefix, checked))
274 if (checked >= prefix.size())
277 return right_->impl_->check_prefix(prefix, checked);
278 return checked >= prefix.size();
281 bool check_suffix(
const boost::core::basic_string_view<CharT>& suffix, size_type rope_pos, size_type suffix_pos)
const
285 if (rope_pos >= weight_)
286 return suffix_pos >= suffix.size();
288 size_type to_check = std::min(weight_ - rope_pos, suffix.size() - suffix_pos);
290 if (Traits::compare(blob_ + rope_pos, suffix.to_string() + suffix_pos, to_check) != 0)
293 return suffix_pos + to_check >= suffix.size();
297 if (rope_pos < weight_)
302 size_type left_check = std::min(weight_ - rope_pos, suffix.size() - suffix_pos);
304 if (!left_->impl_->check_suffix(suffix, rope_pos, suffix_pos))
307 suffix_pos += left_check;
309 if (suffix_pos >= suffix.size())
320 return right_->impl_->check_suffix(suffix, rope_pos, suffix_pos);
322 return suffix_pos >= suffix.size();
326 template <
class CharT,
class Traits,
class Allocator>
333 template <
class CharT,
class Traits,
class Allocator>
338 impl_ = std::exchange(other.impl_,
nullptr);
342 template <
class CharT,
class Traits,
class Allocator>
343 basic_rope<CharT, Traits, Allocator>::basic_rope(
344 basic_rope<CharT, Traits, Allocator>&& other)
346 impl_ = std::exchange(other.impl_,
nullptr);
349 template <
class CharT,
class Traits,
class Allocator>
350 basic_rope<CharT, Traits, Allocator>::basic_rope(
351 const boost::core::basic_string_view<CharT>& in)
352 : impl_(new tree_impl(in, Allocator()))
356 template <
class CharT,
class Traits,
class Allocator>
357 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::begin()
359 if (impl_->is_leaf())
362 return impl_->left_ ? impl_->left_ : impl_->right_;
365 template <
class CharT,
class Traits,
class Allocator>
366 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::end()
372 template <
class CharT,
class Traits,
class Allocator>
373 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::rbegin()
375 if (impl_->is_leaf())
378 auto last = impl_->right_;
390 template <
class CharT,
class Traits,
class Allocator>
391 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::rend()
396 template <
class CharT,
class Traits,
class Allocator>
397 const basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::cbegin()
const
399 if (impl_->is_leaf())
402 return impl_->left_ ? impl_->left_ : impl_->right_;
405 template <
class CharT,
class Traits,
class Allocator>
406 const basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::cend()
const
411 template <
class CharT,
class Traits,
class Allocator>
412 basic_rope<CharT, Traits, Allocator>::size_type
413 basic_rope<CharT, Traits, Allocator>::size()
const
415 return impl_->size();
418 template <
class CharT,
class Traits,
class Allocator>
419 bool basic_rope<CharT, Traits, Allocator>::empty()
const
421 return impl_->size() < 1UL;
424 template <
class CharT,
class Traits,
class Allocator>
425 basic_rope<CharT, Traits, Allocator>&
426 basic_rope<CharT, Traits, Allocator>::substr(size_type pos,
const size_type n)
429 detail::throw_bad_alloc();
431 auto* result = impl_->substr(pos, n,
this, Allocator());
434 detail::throw_bad_alloc();
439 template <
class CharT,
class Traits,
class Allocator>
440 basic_rope<CharT, Traits, Allocator>::size_type
441 basic_rope<CharT, Traits, Allocator>::at(
const boost::core::basic_string_view<CharT>& needle)
443 if (!impl_ || needle.empty())
446 size_type rope_size = impl_->size();
448 if (needle.size() > rope_size)
451 for (size_type i{}; i <= (rope_size - needle.size()); ++i)
455 for (size_type j{}; j < needle.size(); ++j)
457 if (impl_->at(i + j) != needle[j])
471 template <
class CharT,
class Traits,
class Allocator>
472 bool basic_rope<CharT, Traits, Allocator>::starts_with(
const basic_rope<CharT>& other)
474 if (!impl_ || !other.impl_)
477 size_type other_size = other.impl_->size();
479 if (other_size > impl_->size())
482 for (size_type i = 0; i < other_size; ++i)
484 if (impl_->at(i) != other.impl_->at(i))
491 template <
class CharT,
class Traits,
class Allocator>
492 bool basic_rope<CharT, Traits, Allocator>::ends_with(
const basic_rope<CharT>& other)
494 if (!impl_ || !other.impl_)
497 size_type this_size = impl_->size();
498 size_type other_size = other.impl_->size();
500 if (other_size > this_size)
503 size_type offset = this_size - other_size;
505 for (size_type i = 0; i < other_size; ++i)
507 if (impl_->at(offset + i) != other.impl_->at(i))
514 template <
class CharT,
class Traits,
class Allocator>
515 bool basic_rope<CharT, Traits, Allocator>::starts_with(
const boost::core::basic_string_view<CharT>& prefix)
517 return impl_->starts_with(prefix);
520 template <
class CharT,
class Traits,
class Allocator>
521 bool basic_rope<CharT, Traits, Allocator>::ends_with(
const boost::core::basic_string_view<CharT>& suffix)
523 return impl_->ends_with(suffix);
526 template <
class CharT,
class Traits,
class Allocator>
527 bool basic_rope<CharT, Traits, Allocator>::operator==(
const basic_rope& other)
529 if (!impl_ && !other.impl_)
532 if (!impl_ || !other.impl_)
535 return impl_->equals(other.impl_);
538 template <
class CharT,
class Traits,
class Allocator>
539 bool basic_rope<CharT, Traits, Allocator>::operator!=(
const basic_rope& other)
544 return !(*
this == other);
547 template <
class CharT,
class Traits,
class Allocator>
548 bool basic_rope<CharT, Traits, Allocator>::operator==(
const boost::core::basic_string_view<CharT>& str)
553 return impl_->equals(str);
556 template <
class CharT,
class Traits,
class Allocator>
557 std::basic_string<typename basic_rope<CharT, Traits, Allocator>::value_type>
558 basic_rope<CharT, Traits, Allocator>::to_string()
561 detail::throw_bad_alloc();
563 std::basic_string<typename basic_rope<CharT, Traits, Allocator>::value_type> out{};
567 for (
auto p = impl_; p; p = p->right_ ? p->right_->impl_ :
nullptr)
568 total += p->capacity_;
576 out.append(start->blob_, start->capacity_);
579 start = start->right_->impl_;
584 return std::move(out);
587 template <
class CharT,
class Traits,
class Allocator>
588 std::basic_string<typename basic_rope<CharT, Traits, Allocator>::value_type>
589 basic_rope<CharT, Traits, Allocator>::to_string()
const
591 return this->to_string();
594 template <
class CharT,
class Traits,
class Allocator>
595 bool basic_rope<CharT, Traits, Allocator>::operator!=(
const boost::core::basic_string_view<CharT>& str)
597 return !(*
this == str);
600 template <
class CharT,
class Traits,
class Allocator>
601 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::concat(rope_ptr right)
604 detail::throw_bad_alloc();
606 return impl_->concat(
this, right);
609 template <
class CharT,
class Traits,
class Allocator>
610 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::insert(size_type pos,
611 const boost::core::basic_string_view<CharT>& text,
615 detail::throw_bad_alloc();
617 return impl_->insert(pos, text, left);
619 template <
class CharT,
class Traits,
class Allocator>
621 basic_rope<CharT, Traits, Allocator>::pointer basic_rope<CharT, Traits, Allocator>::operator*()
const
623 return this->to_string();
626 template <
class CharT,
class Traits,
class Allocator>
627 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::operator++()
629 return impl_->right_;
632 template <
class CharT,
class Traits,
class Allocator>
633 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::operator++(
int n)
638 ret = ret->operator++();
645 template <
class CharT,
class Traits,
class Allocator>
646 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::operator--()
651 template <
class CharT,
class Traits,
class Allocator>
652 basic_rope<CharT, Traits, Allocator>::rope_ptr basic_rope<CharT, Traits, Allocator>::operator--(
int n)
657 ret = ret->operator--();
This class implements a rope type for any CharT type.
Definition rope_fwd.hpp:23
AMLALE: SourcePair desrves documentation by themselves.
Definition bfs.hpp:13
PImpl of the rope algorithm.
Definition rope_fwd.inl:18