| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229 |
- // 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
|