| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228 |
- // Copyright (C) 2020 T. Zachary Laine
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PARSER_DETAIL_TEXT_TRIE_MAP_HPP
- #define BOOST_PARSER_DETAIL_TEXT_TRIE_MAP_HPP
- #include <boost/parser/detail/text/trie.hpp>
- #include <boost/parser/detail/stl_interfaces/reverse_iterator.hpp>
- namespace boost::parser::detail { namespace text {
- template<typename Key, typename Value>
- struct trie_map_iterator;
- template<typename Key, typename Value>
- struct const_trie_map_iterator;
- template<typename Key, typename Value>
- using reverse_trie_map_iterator =
- stl_interfaces::reverse_iterator<trie_map_iterator<Key, Value>>;
- template<typename Key, typename Value>
- using const_reverse_trie_map_iterator =
- stl_interfaces::reverse_iterator<const_trie_map_iterator<Key, Value>>;
- /** A range type returned by certain operations on a trie_map or
- trie_set. */
- template<typename Iter>
- struct trie_range
- {
- using iterator = Iter;
- iterator first;
- iterator last;
- iterator begin() const { return first; }
- iterator end() const { return last; }
- friend bool operator==(trie_range const & lhs, trie_range const & rhs)
- {
- return lhs.first == rhs.first && lhs.last == rhs.last;
- }
- friend bool operator!=(trie_range const & lhs, trie_range const & rhs)
- {
- return !(lhs == rhs);
- }
- };
- /** A constant range type returned by certain operations on a trie_map or
- trie_set. */
- template<typename Iter>
- struct const_trie_range
- {
- using const_iterator = Iter;
- const_iterator first;
- const_iterator last;
- const_iterator begin() const { return first; }
- const_iterator end() const { return last; }
- friend bool
- operator==(const_trie_range const & lhs, const_trie_range const & rhs)
- {
- return lhs.first == rhs.first && lhs.last == rhs.last;
- }
- friend bool
- operator!=(const_trie_range const & lhs, const_trie_range const & rhs)
- {
- return !(lhs == rhs);
- }
- };
- /** The result type of insert() operations on a trie_map or trie_set. */
- template<typename Iter>
- struct trie_insert_result
- {
- using iterator = Iter;
- trie_insert_result() : iter(), inserted(false) {}
- trie_insert_result(iterator it, bool ins) : iter(it), inserted(ins) {}
- iterator iter;
- bool inserted;
- friend bool operator==(
- trie_insert_result const & lhs, trie_insert_result const & rhs)
- {
- return lhs.iter == rhs.iter && lhs.inserted == rhs.inserted;
- }
- friend bool operator!=(
- trie_insert_result const & lhs, trie_insert_result const & rhs)
- {
- return !(lhs == rhs);
- }
- };
- namespace detail {
- struct index_within_parent_t
- {
- index_within_parent_t() : value_(-1) {}
- std::size_t value() const { return value_; }
- template<
- typename Key,
- typename Value,
- typename Iter,
- std::size_t KeySize>
- void insert_at(
- std::unique_ptr<trie_node_t<
- index_within_parent_t,
- Key,
- Value,
- KeySize>> const & child,
- std::ptrdiff_t offset,
- Iter it,
- Iter end)
- {
- child->index_within_parent_.value_ = offset;
- for (; it != end; ++it) {
- ++(*it)->index_within_parent_.value_;
- }
- }
- template<typename Key, typename Value, std::size_t KeySize>
- void insert_ptr(std::unique_ptr<trie_node_t<
- index_within_parent_t,
- Key,
- Value,
- KeySize>> const & child)
- {
- child->index_within_parent_.value_ = 0;
- }
- template<typename Iter>
- void erase(Iter it, Iter end)
- {
- for (; it != end; ++it) {
- --(*it)->index_within_parent_.value_;
- }
- }
- private:
- std::size_t value_;
- };
- template<typename Key, typename Value, std::size_t KeySize = 0>
- struct trie_iterator_state_t
- {
- trie_node_t<index_within_parent_t, Key, Value, KeySize> const *
- parent_;
- std::size_t index_;
- };
- template<typename Key, typename Value, std::size_t KeySize>
- trie_iterator_state_t<Key, Value, KeySize>
- parent_state(trie_iterator_state_t<Key, Value, KeySize> state)
- {
- return {state.parent_->parent(),
- state.parent_->index_within_parent()};
- }
- template<typename Key, typename Value, std::size_t KeySize>
- Key reconstruct_key(trie_iterator_state_t<Key, Value, KeySize> state)
- {
- Key retval;
- while (state.parent_->parent()) {
- retval.insert(retval.end(), state.parent_->key(state.index_));
- state = parent_state(state);
- }
- std::reverse(retval.begin(), retval.end());
- return retval;
- }
- template<typename Key, typename Value, std::size_t KeySize>
- trie_node_t<index_within_parent_t, Key, Value, KeySize> const *
- to_node(trie_iterator_state_t<Key, Value, KeySize> state)
- {
- if (state.index_ < state.parent_->size())
- return state.parent_->child(state.index_);
- return nullptr;
- }
- }
- /** An associative container similar to std::map, built upon a trie, or
- prefix-tree. A trie_map contains a set of keys, each of which is a
- sequence, and a set of values, each associated with some key. Each
- node in the trie_map represents some prefix found in at least one
- member of the set of values contained in the trie_map. If a certain
- node represents the end of one of the keys, it has an associated
- value. Such a node may or may not have children.
- Complexity of lookups is always O(M), where M is the size of the Key
- being lookep up. Note that this implies that lookup complexity is
- independent of the size of the trie_map.
- \param Key The key-type; must be a sequence of values comparable via
- Compare()(x, y).
- \param Value The value-type.
- \param Compare The type of the comparison object used to compare
- elements of the key-type.
- */
- template<typename Key, typename Value, typename Compare>
- struct trie_map
- {
- private:
- using node_t =
- detail::trie_node_t<detail::index_within_parent_t, Key, Value>;
- using iter_state_t = detail::trie_iterator_state_t<Key, Value>;
- public:
- using key_type = Key;
- using mapped_type = Value;
- using value_type = trie_element<Key, Value>;
- using key_compare = Compare;
- using key_element_type = typename Key::value_type;
- using reference = value_type &;
- using const_reference = value_type const &;
- using iterator = trie_map_iterator<key_type, mapped_type>;
- using const_iterator = const_trie_map_iterator<key_type, mapped_type>;
- using reverse_iterator =
- reverse_trie_map_iterator<key_type, mapped_type>;
- using const_reverse_iterator =
- const_reverse_trie_map_iterator<key_type, mapped_type>;
- using size_type = std::ptrdiff_t;
- using difference_type = std::ptrdiff_t;
- using range = trie_range<iterator>;
- using const_range = const_trie_range<const_iterator>;
- using insert_result = trie_insert_result<iterator>;
- using match_result = trie_match_result;
- trie_map() : size_(0) {}
- trie_map(Compare const & comp) : size_(0), comp_(comp) {}
- template<typename Iter, typename Sentinel>
- trie_map(Iter first, Sentinel last, Compare const & comp = Compare()) :
- size_(0),
- comp_(comp)
- {
- insert(first, last);
- }
- template<typename Range>
- explicit trie_map(Range r, Compare const & comp = Compare()) :
- size_(0),
- comp_(comp)
- {
- insert(detail::begin(r), detail::end(r));
- }
- template<std::size_t KeySize>
- explicit trie_map(
- parser::detail::text::trie<Key, Value, Compare, KeySize> const &
- trie) :
- size_(0)
- {
- Key key;
- from_trie_impl(trie.header_, key);
- }
- trie_map(std::initializer_list<value_type> il) : size_(0)
- {
- insert(il);
- }
- trie_map & operator=(std::initializer_list<value_type> il)
- {
- clear();
- for (auto const & x : il) {
- insert(x);
- }
- return *this;
- }
- bool empty() const { return size_ == 0; }
- size_type size() const { return size_; }
- size_type max_size() const { return PTRDIFF_MAX; }
- const_iterator begin() const
- {
- iter_state_t state{&header_, 0};
- if (size_) {
- while (!state.parent_->min_value()) {
- state.parent_ = state.parent_->min_child();
- }
- }
- return const_iterator(state);
- }
- const_iterator end() const
- {
- iter_state_t state{&header_, 0};
- if (size_) {
- node_t const * node = nullptr;
- while ((node = to_node(state))) {
- state.parent_ = node;
- state.index_ = state.parent_->size() - 1;
- }
- state.parent_ = state.parent_->parent();
- state.index_ = state.parent_->size();
- }
- return const_iterator(state);
- }
- const_iterator cbegin() const { return begin(); }
- const_iterator cend() const { return end(); }
- const_reverse_iterator rbegin() const
- {
- return const_reverse_iterator{end()};
- }
- const_reverse_iterator rend() const
- {
- return const_reverse_iterator{begin()};
- }
- const_reverse_iterator crbegin() const { return rbegin(); }
- const_reverse_iterator crend() const { return rend(); }
- #ifndef BOOST_PARSER_DOXYGEN
- #define BOOST_TRIE_MAP_C_STR_OVERLOAD(rtype, func) \
- template<typename Char, std::size_t N> \
- rtype func(Char const(&chars)[N]) \
- { \
- static_assert( \
- std::is_same<Char, key_element_type>::value, \
- "Only well-formed when Char is Key::value_type."); \
- return func(detail::char_range<Char const>{chars, chars + N - 1}); \
- }
- #define BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(rtype, func, quals) \
- template<typename Char, std::size_t N> \
- rtype func(Char const(&chars)[N]) quals \
- { \
- static_assert( \
- std::is_same<Char, key_element_type>::value, \
- "Only well-formed when Char is Key::value_type."); \
- return func(detail::char_range<Char const>{chars, chars + N - 1}); \
- }
- #endif
- /** Returns true if `key` is found in *this. */
- template<typename KeyRange>
- bool contains(KeyRange const & key) const
- {
- return find(key) != end();
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(bool, contains, const)
- #endif
- /** Returns the iterator pointing to the key/value pair associated
- with `key`, if `key` is found in *this. Returns end()
- otherwise. */
- template<typename KeyRange>
- const_iterator find(KeyRange const & key) const
- {
- auto first = detail::begin(key);
- auto const last = detail::end(key);
- auto match = longest_match_impl(first, last);
- if (first == last && match.match) {
- return const_iterator(iter_state_t{
- to_node_ptr(match.node)->parent(),
- to_node_ptr(match.node)->index_within_parent()});
- }
- return this->end();
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, find, const)
- #endif
- /** Returns the iterator pointing to the first key/value pair whose
- key is not less than `key`. Returns end() if no such key can be
- found. */
- template<typename KeyRange>
- const_iterator lower_bound(KeyRange const & key) const
- {
- return bound_impl<true>(key);
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, lower_bound, const)
- #endif
- /** Returns the iterator pointing to the first key/value pair whose
- key is not greater than `key`. Returns end() if no such key can
- be found. */
- template<typename KeyRange>
- const_iterator upper_bound(KeyRange const & key) const
- {
- return bound_impl<false>(key);
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, upper_bound, const)
- #endif
- /** Returns the `const_range(lower_bound(key), upper_bound(key))`.*/
- template<typename KeyRange>
- const_range equal_range(KeyRange const & key) const
- {
- return {lower_bound(key), upper_bound(key)};
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_range, equal_range, const)
- #endif
- /** Returns the longest subsequence of `[first, last)` found in *this,
- whether or not it is a match. */
- template<typename KeyIter, typename Sentinel>
- match_result longest_subsequence(KeyIter first, Sentinel last) const
-
- {
- return longest_match_impl(first, last);
- }
- /** Returns the longest subsequence of `key` found in *this, whether
- or not it is a match. */
- template<typename KeyRange>
- match_result longest_subsequence(KeyRange const & key) const
- {
- return longest_subsequence(detail::begin(key), detail::end(key));
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(
- match_result, longest_subsequence, const)
- #endif
- /** Returns the longest matching subsequence of `[first, last)` found
- in *this. */
- template<typename KeyIter, typename Sentinel>
- match_result longest_match(KeyIter first, Sentinel last) const
- {
- auto const retval = longest_match_impl(first, last);
- return back_up_to_match(retval);
- }
- /** Returns the longest matching subsequence of `key` found in
- *this. */
- template<typename KeyRange>
- match_result longest_match(KeyRange const & key) const
- {
- return longest_match(detail::begin(key), detail::end(key));
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(match_result, longest_match, const)
- #endif
- /** Returns the result of extending `prev` by one element, `e`. */
- template<typename KeyElementT>
- match_result extend_subsequence(match_result prev, KeyElementT e) const
- {
- auto e_ptr = &e;
- return extend_subsequence_impl(prev, e_ptr, e_ptr + 1);
- }
- /** Returns the result of extending `prev` by the longest subsequence
- of `[first, last)` found in *this. */
- template<typename KeyIter, typename Sentinel>
- match_result extend_subsequence(
- match_result prev, KeyIter first, Sentinel last) const
- {
- return extend_subsequence_impl(prev, first, last);
- }
- /** Returns the result of extending `prev` by one element, `e`, if
- that would form a match, and `prev` otherwise. `prev` must be a
- match. */
- template<typename KeyElementT>
- match_result extend_match(match_result prev, KeyElementT e) const
- {
- BOOST_PARSER_ASSERT(prev.match);
- auto e_ptr = &e;
- auto const retval = extend_subsequence_impl(prev, e_ptr, e_ptr + 1);
- return back_up_to_match(retval);
- }
- /** Returns the result of extending `prev` by the longest subsequence
- of `[first, last)` found in *this, if that would form a match, and
- `prev` otherwise. `prev` must be a match. */
- template<typename KeyIter, typename Sentinel>
- match_result
- extend_match(match_result prev, KeyIter first, Sentinel last) const
- {
- BOOST_PARSER_ASSERT(prev.match);
- auto const retval = extend_subsequence_impl(prev, first, last);
- return back_up_to_match(retval);
- }
- /** Writes the sequence of elements that would advance `prev` by one
- element to `out`, and returns the final value of `out` after the
- writes. */
- template<typename OutIter>
- OutIter copy_next_key_elements(match_result prev, OutIter out) const
- {
- auto node = to_node_ptr(prev.node);
- return std::copy(node->key_begin(), node->key_end(), out);
- }
- /** Returns an optional reference to the const value associated with
- `key` in *this (if any). */
- template<typename KeyRange>
- optional_ref<mapped_type const> operator[](KeyRange const & key) const
- {
- auto it = find(key);
- if (it == end())
- return {};
- return it->value;
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(
- optional_ref<mapped_type const>, operator[], const)
- #endif
- /** Returns an optional reference to the const value associated with
- `match` in *this (if any). */
- optional_ref<mapped_type const> operator[](match_result match) const
- {
- if (!match.match)
- return {};
- return *to_node_ptr(match.node)->value();
- }
- iterator begin() { return iterator(const_this()->begin()); }
- iterator end() { return iterator(const_this()->end()); }
- reverse_iterator rbegin() { return reverse_iterator{end()}; }
- reverse_iterator rend() { return reverse_iterator{begin()}; }
- void clear()
- {
- header_ = node_t();
- size_ = 0;
- }
- /** Returns the iterator pointing to the key/value pair associated
- with `key`, if `key` is found in *this. Returns end()
- otherwise. */
- template<typename KeyRange>
- iterator find(KeyRange const & key)
- {
- return iterator(const_this()->find(key));
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, find)
- #endif
- /** Returns the iterator pointing to the first key/value pair whose
- key is not less than `key`. Returns end() if no such key can be
- found. */
- template<typename KeyRange>
- iterator lower_bound(KeyRange const & key)
- {
- return iterator(const_this()->lower_bound(key));
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, lower_bound)
- #endif
- /** Returns the iterator pointing to the first key/value pair whose
- key is not greater than `key`. Returns end() if no such key can
- be found. */
- template<typename KeyRange>
- iterator upper_bound(KeyRange const & key)
- {
- return iterator(const_this()->upper_bound(key));
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, upper_bound)
- #endif
- /** Returns the `const_range(lower_bound(key), upper_bound(key))`.*/
- template<typename KeyRange>
- range equal_range(KeyRange const & key)
- {
- return {lower_bound(key), upper_bound(key)};
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(range, equal_range)
- #endif
- /** Returns an optional reference to the value associated with `key`
- in *this (if any). */
- template<typename KeyRange>
- optional_ref<mapped_type> operator[](KeyRange const & key)
- {
- auto it = find(key);
- if (it == end())
- return {};
- return it->value;
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(
- optional_ref<mapped_type>, operator[])
- #endif
- /** Returns an optional reference to the value associated with `match`
- in *this (if any). */
- optional_ref<mapped_type> operator[](match_result match)
- {
- if (!match.match)
- return {};
- return *const_cast<node_t *>(to_node_ptr(match.node))->value();
- }
- /** Inserts the key/value pair `[first, last)`, `value` into *this.
- The `inserted` field of the result will be true if the operation
- resulted in a new insertion, or false otherwise. */
- template<typename KeyIter, typename Sentinel>
- insert_result insert(KeyIter first, Sentinel last, Value value)
- {
- if (empty()) {
- std::unique_ptr<node_t> new_node(new node_t(&header_));
- header_.insert(std::move(new_node));
- }
- auto match = longest_match_impl(first, last);
- if (first == last && match.match) {
- return {iterator(iter_state_t{
- to_node_ptr(match.node)->parent(),
- to_node_ptr(match.node)->index_within_parent()}),
- false};
- }
- auto node = create_children(
- const_cast<node_t *>(to_node_ptr(match.node)), first, last);
- node->value() = std::move(value);
- ++size_;
- return {iterator(iter_state_t{node->parent(), 0}), true};
- }
- /** Inserts the key/value pair `key`, `value` into *this. The
- `inserted` field of the result will be true if the operation
- resulted in a new insertion, or false otherwise. */
- template<typename KeyRange>
- insert_result insert(KeyRange const & key, Value value)
- {
- return insert(detail::begin(key), detail::end(key), std::move(value));
- }
- template<typename Char, std::size_t N>
- insert_result insert(Char const (&chars)[N], Value value)
- {
- static_assert(
- std::is_same<Char, key_element_type>::value,
- "Only well-formed when Char is Key::value_type.");
- return insert(
- detail::char_range<Char const>{chars, chars + N - 1},
- std::move(value));
- }
- /** Inserts the key/value pair `e` into *this. The `inserted` field
- of the result will be true if the operation resulted in a new
- insertion, or false otherwise. */
- insert_result insert(value_type e)
- {
- return insert(
- detail::begin(e.key), detail::end(e.key), std::move(e.value));
- }
- /** Inserts the sequence of key/value pairs `[first, last)` into
- *this. The `inserted` field of the result will be true if the
- operation resulted in a new insertion, or false otherwise. */
- template<typename Iter, typename Sentinel>
- void insert(Iter first, Sentinel last)
- {
- for (; first != last; ++first) {
- insert(first->key, first->value);
- }
- }
- /** Inserts the sequence of key/value pairs `r` into *this. The
- `inserted` field of the result will be true if the operation
- resulted in a new insertion, or false otherwise. */
- template<typename Range>
- insert_result insert(Range const & r)
- {
- return insert(detail::begin(r), detail::end(r));
- }
- /** Inserts the sequence of key/value pairs `il` into this. The
- `inserted` field of the result will be true if the operation
- resulted in a new insertion, or false otherwise. */
- void insert(std::initializer_list<value_type> il)
- {
- for (auto const & x : il) {
- insert(x);
- }
- }
- /** Inserts the key/value pair `[first, last)`, `value` into *this, or
- assigns `value` over the existing value associated with `[first,
- last)`, if this key is already found in *this. The `inserted`
- field of the result will be true if the operation resulted in a
- new insertion, or false otherwise. */
- template<typename KeyIter, typename Sentinel>
- insert_result
- insert_or_assign(KeyIter first, Sentinel last, Value value)
- {
- auto it = first;
- auto match = longest_match_impl(it, last);
- if (it == last && match.match) {
- const_cast<Value &>(*to_node_ptr(match.node)->value()) =
- std::move(value);
- return insert_result{
- iterator(iter_state_t{
- to_node_ptr(match.node)->parent(),
- to_node_ptr(match.node)->index_within_parent()}),
- false};
- }
- return insert(first, last, std::move(value));
- }
- /** Inserts the key/value pair `key`, `value` into *this, or assigns
- `value` over the existing value associated with `key`, if `key` is
- already found in *this. The `inserted` field of the result will
- be true if the operation resulted in a new insertion, or false
- otherwise. */
- template<typename KeyRange>
- insert_result insert_or_assign(KeyRange const & key, Value value)
- {
- return insert_or_assign(
- detail::begin(key), detail::end(key), std::move(value));
- }
- template<typename Char, std::size_t N>
- insert_result insert_or_assign(Char const (&chars)[N], Value value)
- {
- static_assert(
- std::is_same<Char, key_element_type>::value,
- "Only well-formed when Char is Key::value_type.");
- return insert_or_assign(
- detail::char_range<Char const>{chars, chars + N - 1},
- std::move(value));
- }
- /** Erases the key/value pair associated with `key` from
- *this. Returns true if the key is found in *this, false
- otherwise. */
- template<typename KeyRange>
- bool erase(KeyRange const & key)
- {
- auto it = find(key);
- if (it == end())
- return false;
- erase(it);
- return true;
- }
- #ifndef BOOST_PARSER_DOXYGEN
- BOOST_TRIE_MAP_C_STR_OVERLOAD(bool, erase)
- #endif
- /** Erases the key/value pair pointed to by `it` from *this. Returns
- an iterator to the next key/value pair in this. */
- iterator erase(iterator it)
- {
- auto state = it.it_.state_;
- --size_;
- auto node =
- const_cast<node_t *>(state.parent_->child(state.index_));
- if (!node->empty()) {
- // node has a value, but also children. Remove the value and
- // return the next-iterator.
- ++it;
- node->value() = std::optional<Value>();
- return it;
- }
- // node has a value, *and* no children. Remove it and all its
- // singular predecessors.
- const_cast<node_t *>(state.parent_)->erase(state.index_);
- while (state.parent_->parent() && state.parent_->empty() &&
- !state.parent_->value()) {
- state = parent_state(state);
- const_cast<node_t *>(state.parent_)->erase(state.index_);
- }
- if (state.parent_->parent())
- state = parent_state(state);
- auto retval = iterator(state);
- if (!empty())
- ++retval;
- return retval;
- }
- /** Erases the sequence of key/value pairs pointed to by `[first,
- last)` from *this. Returns an iterator to the next key/value pair
- in *this. */
- iterator erase(iterator first, iterator last)
- {
- auto retval = last;
- if (first == last)
- return retval;
- --last;
- while (last != first) {
- erase(last--);
- }
- erase(last);
- return retval;
- }
- void swap(trie_map & other)
- {
- header_.swap(other.header_);
- std::swap(size_, other.size_);
- std::swap(comp_, other.comp_);
- }
- friend bool operator==(trie_map const & lhs, trie_map const & rhs)
- {
- return lhs.size() == rhs.size() &&
- std::equal(lhs.begin(), lhs.end(), rhs.begin());
- }
- friend bool operator!=(trie_map const & lhs, trie_map const & rhs)
- {
- return !(lhs == rhs);
- }
- #ifndef BOOST_PARSER_DOXYGEN
- private:
- trie_map const * const_this()
- {
- return const_cast<trie_map const *>(this);
- }
- static node_t const * to_node_ptr(void const * ptr)
- {
- return static_cast<node_t const *>(ptr);
- }
- template<std::size_t KeySize>
- void from_trie_impl(
- detail::trie_node_t<
- detail::no_index_within_parent_t,
- Key,
- Value,
- KeySize> const & node,
- Key & key,
- bool root = true)
- {
- // TODO: Use an iterative approach instead?
- if (!!node.value()) {
- insert(key, *node.value());
- }
- std::vector<key_element_type> next_elements;
- node.copy_next_key_elements(std::back_inserter(next_elements));
- for (auto const & e : next_elements) {
- auto const * n = node.child(e, comp_);
- if (!root)
- key.insert(key.end(), e);
- from_trie_impl(*n, key, false);
- if (!root)
- key.erase(std::prev(key.end()));
- }
- }
- template<typename KeyIter, typename Sentinel>
- match_result longest_match_impl(KeyIter & first, Sentinel last) const
- {
- return extend_subsequence_impl(
- match_result{&header_, 0, false, true}, first, last);
- }
- template<typename KeyIter, typename Sentinel>
- match_result extend_subsequence_impl(
- match_result prev, KeyIter & first, Sentinel last) const
- {
- if (to_node_ptr(prev.node) == &header_) {
- if (header_.empty())
- return prev;
- prev.node = header_.child(0);
- }
- if (first == last) {
- prev.match = !!to_node_ptr(prev.node)->value();
- prev.leaf = to_node_ptr(prev.node)->empty();
- return prev;
- }
- node_t const * node = to_node_ptr(prev.node);
- size_type size = prev.size;
- while (first != last) {
- auto const it = node->find(*first, comp_);
- if (it == node->end())
- break;
- ++first;
- ++size;
- node = it->get();
- }
- return match_result{node, size, !!node->value(), node->empty()};
- }
- static match_result back_up_to_match(match_result retval)
- {
- auto node = to_node_ptr(retval.node);
- while (node->parent() && !node->value()) {
- retval.node = node = node->parent();
- --retval.size;
- }
- if (!!node->value())
- retval.match = true;
- return retval;
- }
- template<typename KeyIter, typename Sentinel>
- node_t * create_children(node_t * node, KeyIter first, Sentinel last)
- {
- auto retval = node;
- for (; first != last; ++first) {
- std::unique_ptr<node_t> new_node(new node_t(retval));
- retval =
- retval->insert(*first, comp_, std::move(new_node))->get();
- }
- return retval;
- }
- template<bool LowerBound, typename KeyRange>
- const_iterator bound_impl(KeyRange const & key) const
- {
- auto first = detail::begin(key);
- auto const last = detail::end(key);
- auto match = longest_match_impl(first, last);
- if (first == last && match.match) {
- auto retval = const_iterator(iter_state_t{
- to_node_ptr(match.node)->parent(),
- to_node_ptr(match.node)->index_within_parent()});
- if (!LowerBound)
- ++retval;
- return retval;
- }
- auto node = to_node_ptr(match.node);
- if (node->before_child_subtree(*first)) {
- // If the next element of the key would be before this node's
- // children, use the successor of this node; let
- // const_iterator::operator++() figure out for us which node
- // that is.
- return ++const_iterator(
- iter_state_t{node->parent(), node->index_within_parent()});
- }
- auto const it = node->lower_bound(*first, comp_);
- if (it == node->end()) {
- // Find the max value in this subtree, and go one past that.
- do {
- node = to_node_ptr(node->max_child());
- } while (!node->value());
- return ++const_iterator(
- iter_state_t{node->parent(), node->parent()->size() - 1});
- }
- // Otherwise, find the min value within the child found above.
- std::size_t parent_index = it - node->begin();
- node = to_node_ptr(it->get());
- while (!node->value()) {
- node = to_node_ptr(node->min_child());
- parent_index = 0;
- }
- return const_iterator(iter_state_t{node->parent(), parent_index});
- }
- node_t header_;
- size_type size_;
- key_compare comp_;
- #endif
- };
- template<typename Key, typename Compare>
- struct trie_set;
- template<typename Key>
- struct const_trie_set_iterator;
- template<typename Key, typename Value>
- struct const_trie_map_iterator : stl_interfaces::iterator_interface<
- const_trie_map_iterator<Key, Value>,
- std::bidirectional_iterator_tag,
- trie_element<Key, Value>,
- trie_element<Key, Value const &>>
- {
- private:
- using state_t = detail::trie_iterator_state_t<Key, Value>;
- state_t state_;
- using ref_type = trie_element<Key, Value const &>;
- using ptr_type = stl_interfaces::proxy_arrow_result<ref_type>;
- public:
- const_trie_map_iterator() : state_{nullptr, 0} {}
- const_trie_map_iterator(trie_match_result match_result)
- {
- BOOST_PARSER_ASSERT(match_result.node);
- BOOST_PARSER_ASSERT(match_result.match);
- auto node = static_cast<detail::trie_node_t<
- detail::index_within_parent_t,
- Key,
- Value> const *>(match_result.node);
- state_.parent_ = node->parent();
- state_.index_ = node->index_within_parent();
- }
- ref_type operator*() const
- {
- return ref_type{detail::reconstruct_key(state_),
- state_.parent_->child_value(state_.index_)};
- }
- ptr_type operator->() const
- {
- ref_type && deref_result = **this;
- return ptr_type(
- ref_type{std::move(deref_result.key), deref_result.value});
- }
- const_trie_map_iterator & operator++()
- {
- auto node = to_node(state_);
- if (node && !node->empty()) {
- state_.parent_ = node;
- state_.index_ = 0;
- } else {
- // Try the next sibling node.
- ++state_.index_;
- auto const first_state = state_;
- while (state_.parent_->parent() &&
- state_.parent_->parent()->parent() &&
- state_.parent_->size() <= state_.index_) {
- state_ = parent_state(state_);
- ++state_.index_;
- }
- // If we went all the way up, incrementing indices, and they
- // were all at size() for each node, the first increment above
- // must have taken us to the end; use that.
- if ((!state_.parent_->parent() ||
- !state_.parent_->parent()->parent()) &&
- state_.parent_->size() <= state_.index_) {
- state_ = first_state;
- return *this;
- }
- }
- node = state_.parent_->child(state_.index_);
- while (!node->value()) {
- auto i = 0u;
- node = node->child(i);
- state_ = state_t{node->parent(), i};
- }
- return *this;
- }
- const_trie_map_iterator & operator--()
- {
- // Decrement-from-end case.
- if (state_.index_ == state_.parent_->size()) {
- --state_.index_;
- return *this;
- }
- // Back up one node at a time until we find an ancestor with a
- // value or a previous sibling.
- while (state_.parent_->parent() && state_.index_ == 0) {
- state_ = parent_state(state_);
- if (state_.parent_->child(state_.index_)->value())
- return *this;
- }
- // If we get found no value above, go down the maximum subtree of
- // the previous sibling.
- if (state_.index_)
- --state_.index_;
- auto node = state_.parent_->child(state_.index_);
- while (!node->empty()) {
- auto i = node->size() - 1;
- node = node->child(i);
- state_ = state_t{node->parent(), i};
- }
- return *this;
- }
- friend bool operator==(
- const_trie_map_iterator lhs, const_trie_map_iterator rhs)
- {
- return lhs.state_.parent_ == rhs.state_.parent_ &&
- lhs.state_.index_ == rhs.state_.index_;
- }
- using base_type = stl_interfaces::iterator_interface<
- const_trie_map_iterator<Key, Value>,
- std::bidirectional_iterator_tag,
- trie_element<Key, Value>,
- trie_element<Key, Value const &>>;
- using base_type::operator++;
- using base_type::operator--;
- #ifndef BOOST_PARSER_DOXYGEN
- private:
- explicit const_trie_map_iterator(state_t state) : state_(state) {}
- template<typename KeyT, typename ValueT, typename Compare>
- friend struct trie_map;
- template<typename KeyT, typename Compare>
- friend struct trie_set;
- template<typename KeyT, typename ValueT>
- friend struct trie_map_iterator;
- template<typename KeyT>
- friend struct const_trie_set_iterator;
- #endif
- };
- template<typename Key, typename Value>
- struct trie_map_iterator : stl_interfaces::iterator_interface<
- trie_map_iterator<Key, Value>,
- std::bidirectional_iterator_tag,
- trie_element<Key, Value>,
- trie_element<Key, Value &>>
- {
- private:
- const_trie_map_iterator<Key, Value> it_;
- using ref_type = trie_element<Key, Value &>;
- using ptr_type = stl_interfaces::proxy_arrow_result<ref_type>;
- public:
- trie_map_iterator() {}
- trie_map_iterator(trie_match_result match_result) :
- trie_map_iterator(const_trie_map_iterator<Key, Value>(match_result))
- {}
- ref_type operator*() const
- {
- return ref_type{detail::reconstruct_key(it_.state_),
- it_.state_.parent_->child_value(it_.state_.index_)};
- };
- ptr_type operator->() const
- {
- ref_type && deref_result = **this;
- return ptr_type(
- ref_type{std::move(deref_result.key), deref_result.value});
- }
- trie_map_iterator & operator++()
- {
- ++it_;
- return *this;
- }
- trie_map_iterator & operator--()
- {
- --it_;
- return *this;
- }
- friend bool
- operator==(trie_map_iterator lhs, trie_map_iterator rhs)
- {
- return lhs.it_ == rhs.it_;
- }
- using base_type = stl_interfaces::iterator_interface<
- trie_map_iterator<Key, Value>,
- std::bidirectional_iterator_tag,
- trie_element<Key, Value>,
- trie_element<Key, Value &>>;
- using base_type::operator++;
- using base_type::operator--;
- #ifndef BOOST_PARSER_DOXYGEN
- private:
- explicit trie_map_iterator(
- detail::trie_iterator_state_t<Key, Value> state) :
- it_(state)
- {}
- explicit trie_map_iterator(const_trie_map_iterator<Key, Value> it) :
- it_(it)
- {}
- template<typename KeyT, typename ValueT, typename Compare>
- friend struct trie_map;
- template<typename KeyT, typename Compare>
- friend struct trie_set;
- #endif
- };
- }}
- #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
- namespace std::ranges {
- template<typename Iter>
- inline constexpr bool
- enable_borrowed_range<boost::parser::detail::text::trie_range<Iter>> =
- true;
- template<typename Iter>
- inline constexpr bool enable_borrowed_range<
- boost::parser::detail::text::const_trie_range<Iter>> = true;
- }
- #endif
- #endif
|