133#include <string_view>
134#include <type_traits>
152 std::is_same_v<T, char8_t>
or std::is_same_v<T, char16_t>
or std::is_same_v<T, char32_t>;
174template <
typename Char =
char,
size_t LeafSize = 256>
177 static_assert(
LeafSize > 0,
"Rope requires a positive LeafSize");
181 using View = std::basic_string_view<Char>;
196 std::unique_ptr<const SmallVector<Char, LeafSize>>
leaf_data;
197 std::shared_ptr<const Node>
left;
219 auto node = std::make_shared<Node>();
220 node->length = data.
size();
223 std::make_unique<const SmallVector<Char, LeafSize>>(std::move(data));
244 <<
"Rope: concatenated length would overflow size_t";
245 auto node = std::make_shared<Node>();
246 node->length = left->length + right->length;
247 node->depth = 1 + std::max(left->depth, right->depth);
248 node->left = std::move(left);
249 node->right = std::move(right);
290 merged.
append_range(node->leaf_data->data(), node->leaf_data->size());
301 <<
"Rope: concatenated length would overflow size_t";
302 auto result = std::make_shared<Node>();
303 result->length = node->length +
extra.size();
304 result->depth = node->depth;
305 result->left = node->left;
325 merged.
append_range(node->leaf_data->data(), node->leaf_data->size());
333 <<
"Rope: concatenated length would overflow size_t";
334 auto result = std::make_shared<Node>();
335 result->length = node->length +
extra.size();
336 result->depth = node->depth;
338 result->right = node->right;
347 if (right ==
nullptr)
358 if (right->is_leaf())
377 const unsigned bits = std::bit_width(node->length);
378 return node->depth <= 2 *
static_cast<size_t>(bits) + 8;
415 const size_t lo,
const size_t hi)
419 const size_t mid = lo + (hi - lo) / 2;
475 const size_t mid = v.size() / 2;
483 while (
not node->is_leaf())
485 node = node->left.get();
489 node = node->right.get();
497 return (*node->leaf_data)(pos);
518 if (pos == 0
and len == node->length)
533 const size_t left_len = node->left->length;
539 return slice(node->left, pos, len);
583 out.append(node->leaf_data->data(), node->leaf_data->size());
603 return node->leaf_data !=
nullptr and node->leaf_data->size() == node->length
and
604 node->length >= 1
and node->length <=
LeafSize and node->depth == 0;
605 if (node->leaf_data !=
nullptr)
607 if (node->left ==
nullptr or node->right ==
nullptr)
609 if (node->length != node->left->length + node->right->length)
611 if (node->depth != 1 + std::max(node->left->depth, node->right->depth))
672 return root_ ==
nullptr;
733 <<
"Rope::substr(): range out of bounds";
756 if (
other.is_empty())
778 <<
"Rope::erase(): range out of bounds";
816 std::basic_string<Char> result;
818 <<
"Rope::to_string(): result exceeds std::basic_string<Char>::max_size()";
819 result.reserve(
size());
861 while (i <
mine.size())
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
size_t size_t int32_t * out
Simple dynamic array with automatic resizing and functional operations.
void reserve(size_t cap)
Reserves cap cells into the array.
Immutable, structurally-shared rope over a sequence of Char.
Rope erase(const size_t pos, const size_t len) const
Return a new rope with [pos, pos+len) removed.
static NodePtr slice(const NodePtr &node, size_t pos, size_t len)
Extract [pos, pos+len) from node (whose own length is assumed to be >= pos+len) as a new,...
bool is_empty() const noexcept
Check whether this rope holds no characters.
Rope & operator=(const Rope &other)=default
Copy assignment operator: O(1), shares the entire tree.
~Rope()=default
Destructor: releases this rope's reference to its tree; nodes are only actually freed once no rope sh...
Rope(NodePtr root) noexcept
Rope insert(const size_t pos, const Rope &other) const
Return a new rope with other inserted at pos.
static NodePtr build_from_view(const View v)
Build a balanced tree of leaves directly from a flat view, splitting at the midpoint recursively.
static void collect_leaf_pointers(const Node *node, Array< const Node * > &out)
Read-only counterpart of collect_leaves: collects raw, non-owning const Node * instead of NodePtr (sh...
static NodePtr make_internal_node(NodePtr left, NodePtr right)
Raw construction of an internal node from two already-built, non-null subtrees: no rebalancing,...
static NodePtr maybe_rebalance(NodePtr node)
Rope() noexcept=default
Construct the empty rope.
std::basic_string_view< Char > View
View type accepted by the constructor and compared against.
static void string_append_into(const Node *node, std::basic_string< Char > &out)
Like flatten_into, but appends directly into a std::basic_string (one bulk append per leaf) instead o...
Array< Char > flatten() const
Return every character of this rope as an independent Array.
static bool is_balanced(const Node *node) noexcept
Generous upper bound on the depth a subtree of the given length should have if reasonably balanced – ...
Rope concat(const Rope &other) const
Return a new rope that is *this followed by other.
static NodePtr try_absorb_right(const NodePtr &node, const SmallVector< Char, LeafSize > &extra)
Try to merge extra into the rightmost leaf of node, sharing every other node unchanged.
bool operator==(const Rope &other) const
Equality: true iff both ropes have the same length and the same characters in the same order (structu...
std::basic_string< Char > to_string() const
Return every character of this rope as a std::basic_string.
std::shared_ptr< const Node > NodePtr
static NodePtr concat_nodes(NodePtr left, NodePtr right)
Concatenate two (possibly null/empty) subtrees.
static NodePtr make_internal(NodePtr left, NodePtr right)
Wrap two non-null subtrees in a new internal node, then rebalance if the result is deeper than is_bal...
static void flatten_into(const Node *node, Array< Char > &out)
size_t size() const noexcept
Return the number of characters in this rope.
Rope(const Rope &other)=default
Copy constructor: O(1), shares the entire tree (immutable, so sharing is always safe).
static const Char & char_at(const Node *node, size_t pos) noexcept
bool verify() const noexcept
Check this rope's internal structural invariants.
Rope(Rope &&other) noexcept=default
Move constructor.
static void collect_leaves(const NodePtr &node, Array< NodePtr > &out)
Rope substr(const size_t pos, const size_t len) const
Return a new rope holding [pos, pos+len) of *this.
static NodePtr make_leaf(SmallVector< Char, LeafSize > data)
static NodePtr try_absorb_left(const NodePtr &node, const SmallVector< Char, LeafSize > &extra)
Mirror of try_absorb_right: merge extra into the leftmost leaf of node, for the "prepend one small pi...
static bool verify_rec(const Node *node) noexcept
Recursive structural-invariant check backing the public verify().
static NodePtr build_balanced_from_leaves(const Array< NodePtr > &leaves, const size_t lo, const size_t hi)
Char at(const size_t pos) const
Return the character at pos.
Contiguous dynamic array with N elements of inline storage.
size_t size() const noexcept
Return the number of stored elements. O(1).
void append_range(const T *first, const size_t count)
Append count copies from [first, first + count), in order.
size_t length() const noexcept
Count the number of elements of a container.
True exactly for the character types std::char_traits is specialized for by the standard (char,...
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
std::unique_ptr< const SmallVector< Char, LeafSize > > leaf_data
std::shared_ptr< const Node > left
std::shared_ptr< const Node > right
bool is_leaf() const noexcept
Dynamic array container with automatic resizing.
Dynamic array with inline storage (Aleph::SmallVector).