Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/parser/detail/text/trie_map.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2020 T. Zachary Laine
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_PARSER_DETAIL_TEXT_TRIE_MAP_HPP
0007 #define BOOST_PARSER_DETAIL_TEXT_TRIE_MAP_HPP
0008 
0009 #include <boost/parser/detail/text/trie.hpp>
0010 
0011 #include <boost/parser/detail/stl_interfaces/reverse_iterator.hpp>
0012 
0013 
0014 namespace boost::parser::detail { namespace text {
0015 
0016     template<typename Key, typename Value>
0017     struct trie_map_iterator;
0018 
0019     template<typename Key, typename Value>
0020     struct const_trie_map_iterator;
0021 
0022     template<typename Key, typename Value>
0023     using reverse_trie_map_iterator =
0024         stl_interfaces::reverse_iterator<trie_map_iterator<Key, Value>>;
0025 
0026     template<typename Key, typename Value>
0027     using const_reverse_trie_map_iterator =
0028         stl_interfaces::reverse_iterator<const_trie_map_iterator<Key, Value>>;
0029 
0030     /** A range type returned by certain operations on a trie_map or
0031         trie_set. */
0032     template<typename Iter>
0033     struct trie_range
0034     {
0035         using iterator = Iter;
0036 
0037         iterator first;
0038         iterator last;
0039 
0040         iterator begin() const { return first; }
0041         iterator end() const { return last; }
0042 
0043         friend bool operator==(trie_range const & lhs, trie_range const & rhs)
0044         {
0045             return lhs.first == rhs.first && lhs.last == rhs.last;
0046         }
0047         friend bool operator!=(trie_range const & lhs, trie_range const & rhs)
0048         {
0049             return !(lhs == rhs);
0050         }
0051     };
0052 
0053     /** A constant range type returned by certain operations on a trie_map or
0054         trie_set. */
0055     template<typename Iter>
0056     struct const_trie_range
0057     {
0058         using const_iterator = Iter;
0059 
0060         const_iterator first;
0061         const_iterator last;
0062 
0063         const_iterator begin() const { return first; }
0064         const_iterator end() const { return last; }
0065 
0066         friend bool
0067         operator==(const_trie_range const & lhs, const_trie_range const & rhs)
0068         {
0069             return lhs.first == rhs.first && lhs.last == rhs.last;
0070         }
0071         friend bool
0072         operator!=(const_trie_range const & lhs, const_trie_range const & rhs)
0073         {
0074             return !(lhs == rhs);
0075         }
0076     };
0077 
0078     /** The result type of insert() operations on a trie_map or trie_set. */
0079     template<typename Iter>
0080     struct trie_insert_result
0081     {
0082         using iterator = Iter;
0083 
0084         trie_insert_result() : iter(), inserted(false) {}
0085         trie_insert_result(iterator it, bool ins) : iter(it), inserted(ins) {}
0086 
0087         iterator iter;
0088         bool inserted;
0089 
0090         friend bool operator==(
0091             trie_insert_result const & lhs, trie_insert_result const & rhs)
0092         {
0093             return lhs.iter == rhs.iter && lhs.inserted == rhs.inserted;
0094         }
0095         friend bool operator!=(
0096             trie_insert_result const & lhs, trie_insert_result const & rhs)
0097         {
0098             return !(lhs == rhs);
0099         }
0100     };
0101 
0102     namespace detail {
0103 
0104         struct index_within_parent_t
0105         {
0106             index_within_parent_t() : value_(-1) {}
0107 
0108             std::size_t value() const { return value_; }
0109 
0110             template<
0111                 typename Key,
0112                 typename Value,
0113                 typename Iter,
0114                 std::size_t KeySize>
0115             void insert_at(
0116                 std::unique_ptr<trie_node_t<
0117                     index_within_parent_t,
0118                     Key,
0119                     Value,
0120                     KeySize>> const & child,
0121                 std::ptrdiff_t offset,
0122                 Iter it,
0123                 Iter end)
0124             {
0125                 child->index_within_parent_.value_ = offset;
0126                 for (; it != end; ++it) {
0127                     ++(*it)->index_within_parent_.value_;
0128                 }
0129             }
0130 
0131             template<typename Key, typename Value, std::size_t KeySize>
0132             void insert_ptr(std::unique_ptr<trie_node_t<
0133                                 index_within_parent_t,
0134                                 Key,
0135                                 Value,
0136                                 KeySize>> const & child)
0137             {
0138                 child->index_within_parent_.value_ = 0;
0139             }
0140 
0141             template<typename Iter>
0142             void erase(Iter it, Iter end)
0143             {
0144                 for (; it != end; ++it) {
0145                     --(*it)->index_within_parent_.value_;
0146                 }
0147             }
0148 
0149         private:
0150             std::size_t value_;
0151         };
0152 
0153         template<typename Key, typename Value, std::size_t KeySize = 0>
0154         struct trie_iterator_state_t
0155         {
0156             trie_node_t<index_within_parent_t, Key, Value, KeySize> const *
0157                 parent_;
0158             std::size_t index_;
0159         };
0160 
0161         template<typename Key, typename Value, std::size_t KeySize>
0162         trie_iterator_state_t<Key, Value, KeySize>
0163         parent_state(trie_iterator_state_t<Key, Value, KeySize> state)
0164         {
0165             return {state.parent_->parent(),
0166                     state.parent_->index_within_parent()};
0167         }
0168 
0169         template<typename Key, typename Value, std::size_t KeySize>
0170         Key reconstruct_key(trie_iterator_state_t<Key, Value, KeySize> state)
0171         {
0172             Key retval;
0173             while (state.parent_->parent()) {
0174                 retval.insert(retval.end(), state.parent_->key(state.index_));
0175                 state = parent_state(state);
0176             }
0177             std::reverse(retval.begin(), retval.end());
0178             return retval;
0179         }
0180 
0181         template<typename Key, typename Value, std::size_t KeySize>
0182         trie_node_t<index_within_parent_t, Key, Value, KeySize> const *
0183         to_node(trie_iterator_state_t<Key, Value, KeySize> state)
0184         {
0185             if (state.index_ < state.parent_->size())
0186                 return state.parent_->child(state.index_);
0187             return nullptr;
0188         }
0189     }
0190 
0191     /** An associative container similar to std::map, built upon a trie, or
0192         prefix-tree.  A trie_map contains a set of keys, each of which is a
0193         sequence, and a set of values, each associated with some key.  Each
0194         node in the trie_map represents some prefix found in at least one
0195         member of the set of values contained in the trie_map.  If a certain
0196         node represents the end of one of the keys, it has an associated
0197         value.  Such a node may or may not have children.
0198 
0199         Complexity of lookups is always O(M), where M is the size of the Key
0200         being lookep up.  Note that this implies that lookup complexity is
0201         independent of the size of the trie_map.
0202 
0203         \param Key The key-type; must be a sequence of values comparable via
0204         Compare()(x, y).
0205         \param Value The value-type.
0206         \param Compare The type of the comparison object used to compare
0207         elements of the key-type.
0208     */
0209     template<typename Key, typename Value, typename Compare>
0210     struct trie_map
0211     {
0212     private:
0213         using node_t =
0214             detail::trie_node_t<detail::index_within_parent_t, Key, Value>;
0215         using iter_state_t = detail::trie_iterator_state_t<Key, Value>;
0216 
0217     public:
0218         using key_type = Key;
0219         using mapped_type = Value;
0220         using value_type = trie_element<Key, Value>;
0221         using key_compare = Compare;
0222         using key_element_type = typename Key::value_type;
0223 
0224         using reference = value_type &;
0225         using const_reference = value_type const &;
0226         using iterator = trie_map_iterator<key_type, mapped_type>;
0227         using const_iterator = const_trie_map_iterator<key_type, mapped_type>;
0228         using reverse_iterator =
0229             reverse_trie_map_iterator<key_type, mapped_type>;
0230         using const_reverse_iterator =
0231             const_reverse_trie_map_iterator<key_type, mapped_type>;
0232         using size_type = std::ptrdiff_t;
0233         using difference_type = std::ptrdiff_t;
0234 
0235         using range = trie_range<iterator>;
0236         using const_range = const_trie_range<const_iterator>;
0237         using insert_result = trie_insert_result<iterator>;
0238         using match_result = trie_match_result;
0239 
0240         trie_map() : size_(0) {}
0241 
0242         trie_map(Compare const & comp) : size_(0), comp_(comp) {}
0243 
0244         template<typename Iter, typename Sentinel>
0245         trie_map(Iter first, Sentinel last, Compare const & comp = Compare()) :
0246             size_(0),
0247             comp_(comp)
0248         {
0249             insert(first, last);
0250         }
0251         template<typename Range>
0252         explicit trie_map(Range r, Compare const & comp = Compare()) :
0253             size_(0),
0254             comp_(comp)
0255         {
0256             insert(detail::begin(r), detail::end(r));
0257         }
0258         template<std::size_t KeySize>
0259         explicit trie_map(
0260             parser::detail::text::trie<Key, Value, Compare, KeySize> const &
0261                 trie) :
0262             size_(0)
0263         {
0264             Key key;
0265             from_trie_impl(trie.header_, key);
0266         }
0267         trie_map(std::initializer_list<value_type> il) : size_(0)
0268         {
0269             insert(il);
0270         }
0271 
0272         trie_map & operator=(std::initializer_list<value_type> il)
0273         {
0274             clear();
0275             for (auto const & x : il) {
0276                 insert(x);
0277             }
0278             return *this;
0279         }
0280 
0281         bool empty() const { return size_ == 0; }
0282         size_type size() const { return size_; }
0283         size_type max_size() const { return PTRDIFF_MAX; }
0284 
0285         const_iterator begin() const
0286         {
0287             iter_state_t state{&header_, 0};
0288             if (size_) {
0289                 while (!state.parent_->min_value()) {
0290                     state.parent_ = state.parent_->min_child();
0291                 }
0292             }
0293             return const_iterator(state);
0294         }
0295         const_iterator end() const
0296         {
0297             iter_state_t state{&header_, 0};
0298             if (size_) {
0299                 node_t const * node = nullptr;
0300                 while ((node = to_node(state))) {
0301                     state.parent_ = node;
0302                     state.index_ = state.parent_->size() - 1;
0303                 }
0304                 state.parent_ = state.parent_->parent();
0305                 state.index_ = state.parent_->size();
0306             }
0307             return const_iterator(state);
0308         }
0309         const_iterator cbegin() const { return begin(); }
0310         const_iterator cend() const { return end(); }
0311 
0312         const_reverse_iterator rbegin() const
0313         {
0314             return const_reverse_iterator{end()};
0315         }
0316         const_reverse_iterator rend() const
0317         {
0318             return const_reverse_iterator{begin()};
0319         }
0320         const_reverse_iterator crbegin() const { return rbegin(); }
0321         const_reverse_iterator crend() const { return rend(); }
0322 
0323 #ifndef BOOST_PARSER_DOXYGEN
0324 
0325 #define BOOST_TRIE_MAP_C_STR_OVERLOAD(rtype, func)                             \
0326     template<typename Char, std::size_t N>                                     \
0327     rtype func(Char const(&chars)[N])                                          \
0328     {                                                                          \
0329         static_assert(                                                         \
0330             std::is_same<Char, key_element_type>::value,                       \
0331             "Only well-formed when Char is Key::value_type.");                 \
0332         return func(detail::char_range<Char const>{chars, chars + N - 1});     \
0333     }
0334 
0335 #define BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(rtype, func, quals)                \
0336     template<typename Char, std::size_t N>                                     \
0337     rtype func(Char const(&chars)[N]) quals                                    \
0338     {                                                                          \
0339         static_assert(                                                         \
0340             std::is_same<Char, key_element_type>::value,                       \
0341             "Only well-formed when Char is Key::value_type.");                 \
0342         return func(detail::char_range<Char const>{chars, chars + N - 1});     \
0343     }
0344 
0345 #endif
0346 
0347         /** Returns true if `key` is found in *this. */
0348         template<typename KeyRange>
0349         bool contains(KeyRange const & key) const
0350         {
0351             return find(key) != end();
0352         }
0353 
0354 #ifndef BOOST_PARSER_DOXYGEN
0355         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(bool, contains, const)
0356 #endif
0357 
0358         /** Returns the iterator pointing to the key/value pair associated
0359             with `key`, if `key` is found in *this.  Returns end()
0360             otherwise. */
0361         template<typename KeyRange>
0362         const_iterator find(KeyRange const & key) const
0363         {
0364             auto first = detail::begin(key);
0365             auto const last = detail::end(key);
0366             auto match = longest_match_impl(first, last);
0367             if (first == last && match.match) {
0368                 return const_iterator(iter_state_t{
0369                     to_node_ptr(match.node)->parent(),
0370                     to_node_ptr(match.node)->index_within_parent()});
0371             }
0372             return this->end();
0373         }
0374 
0375 #ifndef BOOST_PARSER_DOXYGEN
0376         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, find, const)
0377 #endif
0378 
0379         /** Returns the iterator pointing to the first key/value pair whose
0380             key is not less than `key`.  Returns end() if no such key can be
0381             found. */
0382         template<typename KeyRange>
0383         const_iterator lower_bound(KeyRange const & key) const
0384         {
0385             return bound_impl<true>(key);
0386         }
0387 
0388 #ifndef BOOST_PARSER_DOXYGEN
0389         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, lower_bound, const)
0390 #endif
0391 
0392         /** Returns the iterator pointing to the first key/value pair whose
0393             key is not greater than `key`.  Returns end() if no such key can
0394             be found. */
0395         template<typename KeyRange>
0396         const_iterator upper_bound(KeyRange const & key) const
0397         {
0398             return bound_impl<false>(key);
0399         }
0400 
0401 #ifndef BOOST_PARSER_DOXYGEN
0402         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_iterator, upper_bound, const)
0403 #endif
0404 
0405         /** Returns the `const_range(lower_bound(key), upper_bound(key))`.*/
0406         template<typename KeyRange>
0407         const_range equal_range(KeyRange const & key) const
0408         {
0409             return {lower_bound(key), upper_bound(key)};
0410         }
0411 
0412 #ifndef BOOST_PARSER_DOXYGEN
0413         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(const_range, equal_range, const)
0414 #endif
0415 
0416         /** Returns the longest subsequence of `[first, last)` found in *this,
0417             whether or not it is a match. */
0418         template<typename KeyIter, typename Sentinel>
0419         match_result longest_subsequence(KeyIter first, Sentinel last) const
0420            
0421         {
0422             return longest_match_impl(first, last);
0423         }
0424 
0425         /** Returns the longest subsequence of `key` found in *this, whether
0426             or not it is a match. */
0427         template<typename KeyRange>
0428         match_result longest_subsequence(KeyRange const & key) const
0429         {
0430             return longest_subsequence(detail::begin(key), detail::end(key));
0431         }
0432 
0433 #ifndef BOOST_PARSER_DOXYGEN
0434         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(
0435             match_result, longest_subsequence, const)
0436 #endif
0437 
0438         /** Returns the longest matching subsequence of `[first, last)` found
0439             in *this. */
0440         template<typename KeyIter, typename Sentinel>
0441         match_result longest_match(KeyIter first, Sentinel last) const
0442         {
0443             auto const retval = longest_match_impl(first, last);
0444             return back_up_to_match(retval);
0445         }
0446 
0447         /** Returns the longest matching subsequence of `key` found in
0448             *this. */
0449         template<typename KeyRange>
0450         match_result longest_match(KeyRange const & key) const
0451         {
0452             return longest_match(detail::begin(key), detail::end(key));
0453         }
0454 
0455 #ifndef BOOST_PARSER_DOXYGEN
0456         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(match_result, longest_match, const)
0457 #endif
0458 
0459         /** Returns the result of extending `prev` by one element, `e`. */
0460         template<typename KeyElementT>
0461         match_result extend_subsequence(match_result prev, KeyElementT e) const
0462         {
0463             auto e_ptr = &e;
0464             return extend_subsequence_impl(prev, e_ptr, e_ptr + 1);
0465         }
0466 
0467         /** Returns the result of extending `prev` by the longest subsequence
0468             of `[first, last)` found in *this. */
0469         template<typename KeyIter, typename Sentinel>
0470         match_result extend_subsequence(
0471             match_result prev, KeyIter first, Sentinel last) const
0472         {
0473             return extend_subsequence_impl(prev, first, last);
0474         }
0475 
0476         /** Returns the result of extending `prev` by one element, `e`, if
0477            that would form a match, and `prev` otherwise.  `prev` must be a
0478            match. */
0479         template<typename KeyElementT>
0480         match_result extend_match(match_result prev, KeyElementT e) const
0481         {
0482             BOOST_PARSER_ASSERT(prev.match);
0483             auto e_ptr = &e;
0484             auto const retval = extend_subsequence_impl(prev, e_ptr, e_ptr + 1);
0485             return back_up_to_match(retval);
0486         }
0487 
0488         /** Returns the result of extending `prev` by the longest subsequence
0489             of `[first, last)` found in *this, if that would form a match, and
0490             `prev` otherwise.  `prev` must be a match. */
0491         template<typename KeyIter, typename Sentinel>
0492         match_result
0493         extend_match(match_result prev, KeyIter first, Sentinel last) const
0494         {
0495             BOOST_PARSER_ASSERT(prev.match);
0496             auto const retval = extend_subsequence_impl(prev, first, last);
0497             return back_up_to_match(retval);
0498         }
0499 
0500         /** Writes the sequence of elements that would advance `prev` by one
0501             element to `out`, and returns the final value of `out` after the
0502             writes. */
0503         template<typename OutIter>
0504         OutIter copy_next_key_elements(match_result prev, OutIter out) const
0505         {
0506             auto node = to_node_ptr(prev.node);
0507             return std::copy(node->key_begin(), node->key_end(), out);
0508         }
0509 
0510         /** Returns an optional reference to the const value associated with
0511             `key` in *this (if any). */
0512         template<typename KeyRange>
0513         optional_ref<mapped_type const> operator[](KeyRange const & key) const
0514         {
0515             auto it = find(key);
0516             if (it == end())
0517                 return {};
0518             return it->value;
0519         }
0520 
0521 #ifndef BOOST_PARSER_DOXYGEN
0522         BOOST_TRIE_MAP_C_STR_OVERLOAD_QUALS(
0523             optional_ref<mapped_type const>, operator[], const)
0524 #endif
0525 
0526         /** Returns an optional reference to the const value associated with
0527             `match` in *this (if any). */
0528         optional_ref<mapped_type const> operator[](match_result match) const
0529         {
0530             if (!match.match)
0531                 return {};
0532             return *to_node_ptr(match.node)->value();
0533         }
0534 
0535         iterator begin() { return iterator(const_this()->begin()); }
0536         iterator end() { return iterator(const_this()->end()); }
0537 
0538         reverse_iterator rbegin() { return reverse_iterator{end()}; }
0539         reverse_iterator rend() { return reverse_iterator{begin()}; }
0540 
0541         void clear()
0542         {
0543             header_ = node_t();
0544             size_ = 0;
0545         }
0546 
0547         /** Returns the iterator pointing to the key/value pair associated
0548             with `key`, if `key` is found in *this.  Returns end()
0549             otherwise. */
0550         template<typename KeyRange>
0551         iterator find(KeyRange const & key)
0552         {
0553             return iterator(const_this()->find(key));
0554         }
0555 
0556 #ifndef BOOST_PARSER_DOXYGEN
0557         BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, find)
0558 #endif
0559 
0560         /** Returns the iterator pointing to the first key/value pair whose
0561             key is not less than `key`.  Returns end() if no such key can be
0562             found. */
0563         template<typename KeyRange>
0564         iterator lower_bound(KeyRange const & key)
0565         {
0566             return iterator(const_this()->lower_bound(key));
0567         }
0568 
0569 #ifndef BOOST_PARSER_DOXYGEN
0570         BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, lower_bound)
0571 #endif
0572 
0573         /** Returns the iterator pointing to the first key/value pair whose
0574             key is not greater than `key`.  Returns end() if no such key can
0575             be found. */
0576         template<typename KeyRange>
0577         iterator upper_bound(KeyRange const & key)
0578         {
0579             return iterator(const_this()->upper_bound(key));
0580         }
0581 
0582 #ifndef BOOST_PARSER_DOXYGEN
0583         BOOST_TRIE_MAP_C_STR_OVERLOAD(iterator, upper_bound)
0584 #endif
0585 
0586         /** Returns the `const_range(lower_bound(key), upper_bound(key))`.*/
0587         template<typename KeyRange>
0588         range equal_range(KeyRange const & key)
0589         {
0590             return {lower_bound(key), upper_bound(key)};
0591         }
0592 
0593 #ifndef BOOST_PARSER_DOXYGEN
0594         BOOST_TRIE_MAP_C_STR_OVERLOAD(range, equal_range)
0595 #endif
0596 
0597         /** Returns an optional reference to the value associated with `key`
0598             in *this (if any). */
0599         template<typename KeyRange>
0600         optional_ref<mapped_type> operator[](KeyRange const & key)
0601         {
0602             auto it = find(key);
0603             if (it == end())
0604                 return {};
0605             return it->value;
0606         }
0607 
0608 #ifndef BOOST_PARSER_DOXYGEN
0609         BOOST_TRIE_MAP_C_STR_OVERLOAD(
0610             optional_ref<mapped_type>, operator[])
0611 #endif
0612 
0613         /** Returns an optional reference to the value associated with `match`
0614             in *this (if any). */
0615         optional_ref<mapped_type> operator[](match_result match)
0616         {
0617             if (!match.match)
0618                 return {};
0619             return *const_cast<node_t *>(to_node_ptr(match.node))->value();
0620         }
0621 
0622         /** Inserts the key/value pair `[first, last)`, `value` into *this.
0623             The `inserted` field of the result will be true if the operation
0624             resulted in a new insertion, or false otherwise. */
0625         template<typename KeyIter, typename Sentinel>
0626         insert_result insert(KeyIter first, Sentinel last, Value value)
0627         {
0628             if (empty()) {
0629                 std::unique_ptr<node_t> new_node(new node_t(&header_));
0630                 header_.insert(std::move(new_node));
0631             }
0632 
0633             auto match = longest_match_impl(first, last);
0634             if (first == last && match.match) {
0635                 return {iterator(iter_state_t{
0636                             to_node_ptr(match.node)->parent(),
0637                             to_node_ptr(match.node)->index_within_parent()}),
0638                         false};
0639             }
0640             auto node = create_children(
0641                 const_cast<node_t *>(to_node_ptr(match.node)), first, last);
0642             node->value() = std::move(value);
0643             ++size_;
0644             return {iterator(iter_state_t{node->parent(), 0}), true};
0645         }
0646 
0647         /** Inserts the key/value pair `key`, `value` into *this.  The
0648             `inserted` field of the result will be true if the operation
0649             resulted in a new insertion, or false otherwise. */
0650         template<typename KeyRange>
0651         insert_result insert(KeyRange const & key, Value value)
0652         {
0653             return insert(detail::begin(key), detail::end(key), std::move(value));
0654         }
0655 
0656         template<typename Char, std::size_t N>
0657         insert_result insert(Char const (&chars)[N], Value value)
0658         {
0659             static_assert(
0660                 std::is_same<Char, key_element_type>::value,
0661                 "Only well-formed when Char is Key::value_type.");
0662             return insert(
0663                 detail::char_range<Char const>{chars, chars + N - 1},
0664                 std::move(value));
0665         }
0666 
0667         /** Inserts the key/value pair `e` into *this.  The `inserted` field
0668             of the result will be true if the operation resulted in a new
0669             insertion, or false otherwise. */
0670         insert_result insert(value_type e)
0671         {
0672             return insert(
0673                 detail::begin(e.key), detail::end(e.key), std::move(e.value));
0674         }
0675 
0676         /** Inserts the sequence of key/value pairs `[first, last)` into
0677             *this.  The `inserted` field of the result will be true if the
0678             operation resulted in a new insertion, or false otherwise. */
0679         template<typename Iter, typename Sentinel>
0680         void insert(Iter first, Sentinel last)
0681         {
0682             for (; first != last; ++first) {
0683                 insert(first->key, first->value);
0684             }
0685         }
0686 
0687         /** Inserts the sequence of key/value pairs `r` into *this.  The
0688             `inserted` field of the result will be true if the operation
0689             resulted in a new insertion, or false otherwise. */
0690         template<typename Range>
0691         insert_result insert(Range const & r)
0692         {
0693             return insert(detail::begin(r), detail::end(r));
0694         }
0695 
0696         /** Inserts the sequence of key/value pairs `il` into this.  The
0697             `inserted` field of the result will be true if the operation
0698             resulted in a new insertion, or false otherwise. */
0699         void insert(std::initializer_list<value_type> il)
0700         {
0701             for (auto const & x : il) {
0702                 insert(x);
0703             }
0704         }
0705 
0706         /** Inserts the key/value pair `[first, last)`, `value` into *this, or
0707             assigns `value` over the existing value associated with `[first,
0708             last)`, if this key is already found in *this.  The `inserted`
0709             field of the result will be true if the operation resulted in a
0710             new insertion, or false otherwise. */
0711         template<typename KeyIter, typename Sentinel>
0712         insert_result
0713         insert_or_assign(KeyIter first, Sentinel last, Value value)
0714         {
0715             auto it = first;
0716             auto match = longest_match_impl(it, last);
0717             if (it == last && match.match) {
0718                 const_cast<Value &>(*to_node_ptr(match.node)->value()) =
0719                     std::move(value);
0720                 return insert_result{
0721                     iterator(iter_state_t{
0722                         to_node_ptr(match.node)->parent(),
0723                         to_node_ptr(match.node)->index_within_parent()}),
0724                     false};
0725             }
0726             return insert(first, last, std::move(value));
0727         }
0728 
0729         /** Inserts the key/value pair `key`, `value` into *this, or assigns
0730             `value` over the existing value associated with `key`, if `key` is
0731             already found in *this.  The `inserted` field of the result will
0732             be true if the operation resulted in a new insertion, or false
0733             otherwise. */
0734         template<typename KeyRange>
0735         insert_result insert_or_assign(KeyRange const & key, Value value)
0736         {
0737             return insert_or_assign(
0738                 detail::begin(key), detail::end(key), std::move(value));
0739         }
0740 
0741         template<typename Char, std::size_t N>
0742         insert_result insert_or_assign(Char const (&chars)[N], Value value)
0743         {
0744             static_assert(
0745                 std::is_same<Char, key_element_type>::value,
0746                 "Only well-formed when Char is Key::value_type.");
0747             return insert_or_assign(
0748                 detail::char_range<Char const>{chars, chars + N - 1},
0749                 std::move(value));
0750         }
0751 
0752         /** Erases the key/value pair associated with `key` from
0753             *this. Returns true if the key is found in *this, false
0754             otherwise. */
0755         template<typename KeyRange>
0756         bool erase(KeyRange const & key)
0757         {
0758             auto it = find(key);
0759             if (it == end())
0760                 return false;
0761             erase(it);
0762             return true;
0763         }
0764 
0765 #ifndef BOOST_PARSER_DOXYGEN
0766         BOOST_TRIE_MAP_C_STR_OVERLOAD(bool, erase)
0767 #endif
0768 
0769         /** Erases the key/value pair pointed to by `it` from *this.  Returns
0770             an iterator to the next key/value pair in this. */
0771         iterator erase(iterator it)
0772         {
0773             auto state = it.it_.state_;
0774 
0775             --size_;
0776 
0777             auto node =
0778                 const_cast<node_t *>(state.parent_->child(state.index_));
0779             if (!node->empty()) {
0780                 // node has a value, but also children.  Remove the value and
0781                 // return the next-iterator.
0782                 ++it;
0783                 node->value() = std::optional<Value>();
0784                 return it;
0785             }
0786 
0787             // node has a value, *and* no children.  Remove it and all its
0788             // singular predecessors.
0789             const_cast<node_t *>(state.parent_)->erase(state.index_);
0790             while (state.parent_->parent() && state.parent_->empty() &&
0791                    !state.parent_->value()) {
0792                 state = parent_state(state);
0793                 const_cast<node_t *>(state.parent_)->erase(state.index_);
0794             }
0795 
0796             if (state.parent_->parent())
0797                 state = parent_state(state);
0798             auto retval = iterator(state);
0799             if (!empty())
0800                 ++retval;
0801 
0802             return retval;
0803         }
0804 
0805         /** Erases the sequence of key/value pairs pointed to by `[first,
0806             last)` from *this.  Returns an iterator to the next key/value pair
0807             in *this. */
0808         iterator erase(iterator first, iterator last)
0809         {
0810             auto retval = last;
0811             if (first == last)
0812                 return retval;
0813             --last;
0814             while (last != first) {
0815                 erase(last--);
0816             }
0817             erase(last);
0818             return retval;
0819         }
0820 
0821         void swap(trie_map & other)
0822         {
0823             header_.swap(other.header_);
0824             std::swap(size_, other.size_);
0825             std::swap(comp_, other.comp_);
0826         }
0827 
0828         friend bool operator==(trie_map const & lhs, trie_map const & rhs)
0829         {
0830             return lhs.size() == rhs.size() &&
0831                    std::equal(lhs.begin(), lhs.end(), rhs.begin());
0832         }
0833         friend bool operator!=(trie_map const & lhs, trie_map const & rhs)
0834         {
0835             return !(lhs == rhs);
0836         }
0837 
0838 #ifndef BOOST_PARSER_DOXYGEN
0839 
0840     private:
0841         trie_map const * const_this()
0842         {
0843             return const_cast<trie_map const *>(this);
0844         }
0845         static node_t const * to_node_ptr(void const * ptr)
0846         {
0847             return static_cast<node_t const *>(ptr);
0848         }
0849 
0850         template<std::size_t KeySize>
0851         void from_trie_impl(
0852             detail::trie_node_t<
0853                 detail::no_index_within_parent_t,
0854                 Key,
0855                 Value,
0856                 KeySize> const & node,
0857             Key & key,
0858             bool root = true)
0859         {
0860             // TODO: Use an iterative approach instead?
0861 
0862             if (!!node.value()) {
0863                 insert(key, *node.value());
0864             }
0865 
0866             std::vector<key_element_type> next_elements;
0867             node.copy_next_key_elements(std::back_inserter(next_elements));
0868             for (auto const & e : next_elements) {
0869                 auto const * n = node.child(e, comp_);
0870                 if (!root)
0871                     key.insert(key.end(), e);
0872                 from_trie_impl(*n, key, false);
0873                 if (!root)
0874                     key.erase(std::prev(key.end()));
0875             }
0876         }
0877 
0878         template<typename KeyIter, typename Sentinel>
0879         match_result longest_match_impl(KeyIter & first, Sentinel last) const
0880         {
0881             return extend_subsequence_impl(
0882                 match_result{&header_, 0, false, true}, first, last);
0883         }
0884 
0885         template<typename KeyIter, typename Sentinel>
0886         match_result extend_subsequence_impl(
0887             match_result prev, KeyIter & first, Sentinel last) const
0888         {
0889             if (to_node_ptr(prev.node) == &header_) {
0890                 if (header_.empty())
0891                     return prev;
0892                 prev.node = header_.child(0);
0893             }
0894 
0895             if (first == last) {
0896                 prev.match = !!to_node_ptr(prev.node)->value();
0897                 prev.leaf = to_node_ptr(prev.node)->empty();
0898                 return prev;
0899             }
0900 
0901             node_t const * node = to_node_ptr(prev.node);
0902             size_type size = prev.size;
0903             while (first != last) {
0904                 auto const it = node->find(*first, comp_);
0905                 if (it == node->end())
0906                     break;
0907                 ++first;
0908                 ++size;
0909                 node = it->get();
0910             }
0911 
0912             return match_result{node, size, !!node->value(), node->empty()};
0913         }
0914 
0915         static match_result back_up_to_match(match_result retval)
0916         {
0917             auto node = to_node_ptr(retval.node);
0918             while (node->parent() && !node->value()) {
0919                 retval.node = node = node->parent();
0920                 --retval.size;
0921             }
0922             if (!!node->value())
0923                 retval.match = true;
0924             return retval;
0925         }
0926 
0927         template<typename KeyIter, typename Sentinel>
0928         node_t * create_children(node_t * node, KeyIter first, Sentinel last)
0929         {
0930             auto retval = node;
0931             for (; first != last; ++first) {
0932                 std::unique_ptr<node_t> new_node(new node_t(retval));
0933                 retval =
0934                     retval->insert(*first, comp_, std::move(new_node))->get();
0935             }
0936             return retval;
0937         }
0938 
0939         template<bool LowerBound, typename KeyRange>
0940         const_iterator bound_impl(KeyRange const & key) const
0941         {
0942             auto first = detail::begin(key);
0943             auto const last = detail::end(key);
0944             auto match = longest_match_impl(first, last);
0945             if (first == last && match.match) {
0946                 auto retval = const_iterator(iter_state_t{
0947                     to_node_ptr(match.node)->parent(),
0948                     to_node_ptr(match.node)->index_within_parent()});
0949                 if (!LowerBound)
0950                     ++retval;
0951                 return retval;
0952             }
0953 
0954             auto node = to_node_ptr(match.node);
0955             if (node->before_child_subtree(*first)) {
0956                 // If the next element of the key would be before this node's
0957                 // children, use the successor of this node; let
0958                 // const_iterator::operator++() figure out for us which node
0959                 // that is.
0960                 return ++const_iterator(
0961                     iter_state_t{node->parent(), node->index_within_parent()});
0962             }
0963 
0964             auto const it = node->lower_bound(*first, comp_);
0965             if (it == node->end()) {
0966                 // Find the max value in this subtree, and go one past that.
0967                 do {
0968                     node = to_node_ptr(node->max_child());
0969                 } while (!node->value());
0970                 return ++const_iterator(
0971                     iter_state_t{node->parent(), node->parent()->size() - 1});
0972             }
0973 
0974             // Otherwise, find the min value within the child found above.
0975             std::size_t parent_index = it - node->begin();
0976             node = to_node_ptr(it->get());
0977             while (!node->value()) {
0978                 node = to_node_ptr(node->min_child());
0979                 parent_index = 0;
0980             }
0981             return const_iterator(iter_state_t{node->parent(), parent_index});
0982         }
0983 
0984         node_t header_;
0985         size_type size_;
0986         key_compare comp_;
0987 
0988 #endif
0989     };
0990 
0991     template<typename Key, typename Compare>
0992     struct trie_set;
0993 
0994     template<typename Key>
0995     struct const_trie_set_iterator;
0996 
0997     template<typename Key, typename Value>
0998     struct const_trie_map_iterator : stl_interfaces::iterator_interface<
0999                                          const_trie_map_iterator<Key, Value>,
1000                                          std::bidirectional_iterator_tag,
1001                                          trie_element<Key, Value>,
1002                                          trie_element<Key, Value const &>>
1003     {
1004     private:
1005         using state_t = detail::trie_iterator_state_t<Key, Value>;
1006         state_t state_;
1007         using ref_type = trie_element<Key, Value const &>;
1008         using ptr_type = stl_interfaces::proxy_arrow_result<ref_type>;
1009 
1010     public:
1011         const_trie_map_iterator() : state_{nullptr, 0} {}
1012 
1013         const_trie_map_iterator(trie_match_result match_result)
1014         {
1015             BOOST_PARSER_ASSERT(match_result.node);
1016             BOOST_PARSER_ASSERT(match_result.match);
1017             auto node = static_cast<detail::trie_node_t<
1018                 detail::index_within_parent_t,
1019                 Key,
1020                 Value> const *>(match_result.node);
1021             state_.parent_ = node->parent();
1022             state_.index_ = node->index_within_parent();
1023         }
1024 
1025         ref_type operator*() const
1026         {
1027             return ref_type{detail::reconstruct_key(state_),
1028                             state_.parent_->child_value(state_.index_)};
1029         }
1030         ptr_type operator->() const
1031         {
1032             ref_type && deref_result = **this;
1033             return ptr_type(
1034                 ref_type{std::move(deref_result.key), deref_result.value});
1035          }
1036 
1037         const_trie_map_iterator & operator++()
1038         {
1039             auto node = to_node(state_);
1040             if (node && !node->empty()) {
1041                 state_.parent_ = node;
1042                 state_.index_ = 0;
1043             } else {
1044                 // Try the next sibling node.
1045                 ++state_.index_;
1046                 auto const first_state = state_;
1047                 while (state_.parent_->parent() &&
1048                        state_.parent_->parent()->parent() &&
1049                        state_.parent_->size() <= state_.index_) {
1050                     state_ = parent_state(state_);
1051                     ++state_.index_;
1052                 }
1053 
1054                 // If we went all the way up, incrementing indices, and they
1055                 // were all at size() for each node, the first increment above
1056                 // must have taken us to the end; use that.
1057                 if ((!state_.parent_->parent() ||
1058                      !state_.parent_->parent()->parent()) &&
1059                     state_.parent_->size() <= state_.index_) {
1060                     state_ = first_state;
1061                     return *this;
1062                 }
1063             }
1064 
1065             node = state_.parent_->child(state_.index_);
1066             while (!node->value()) {
1067                 auto i = 0u;
1068                 node = node->child(i);
1069                 state_ = state_t{node->parent(), i};
1070             }
1071 
1072             return *this;
1073         }
1074         const_trie_map_iterator & operator--()
1075         {
1076             // Decrement-from-end case.
1077             if (state_.index_ == state_.parent_->size()) {
1078                 --state_.index_;
1079                 return *this;
1080             }
1081 
1082             // Back up one node at a time until we find an ancestor with a
1083             // value or a previous sibling.
1084             while (state_.parent_->parent() && state_.index_ == 0) {
1085                 state_ = parent_state(state_);
1086                 if (state_.parent_->child(state_.index_)->value())
1087                     return *this;
1088             }
1089 
1090             // If we get found no value above, go down the maximum subtree of
1091             // the previous sibling.
1092             if (state_.index_)
1093                 --state_.index_;
1094             auto node = state_.parent_->child(state_.index_);
1095             while (!node->empty()) {
1096                 auto i = node->size() - 1;
1097                 node = node->child(i);
1098                 state_ = state_t{node->parent(), i};
1099             }
1100 
1101             return *this;
1102         }
1103 
1104         friend bool operator==(
1105             const_trie_map_iterator lhs, const_trie_map_iterator rhs)
1106         {
1107             return lhs.state_.parent_ == rhs.state_.parent_ &&
1108                    lhs.state_.index_ == rhs.state_.index_;
1109         }
1110 
1111         using base_type = stl_interfaces::iterator_interface<
1112             const_trie_map_iterator<Key, Value>,
1113             std::bidirectional_iterator_tag,
1114             trie_element<Key, Value>,
1115             trie_element<Key, Value const &>>;
1116         using base_type::operator++;
1117         using base_type::operator--;
1118 
1119 #ifndef BOOST_PARSER_DOXYGEN
1120 
1121     private:
1122         explicit const_trie_map_iterator(state_t state) : state_(state) {}
1123 
1124         template<typename KeyT, typename ValueT, typename Compare>
1125         friend struct trie_map;
1126         template<typename KeyT, typename Compare>
1127         friend struct trie_set;
1128         template<typename KeyT, typename ValueT>
1129         friend struct trie_map_iterator;
1130         template<typename KeyT>
1131         friend struct const_trie_set_iterator;
1132 
1133 #endif
1134     };
1135 
1136     template<typename Key, typename Value>
1137     struct trie_map_iterator : stl_interfaces::iterator_interface<
1138                                    trie_map_iterator<Key, Value>,
1139                                    std::bidirectional_iterator_tag,
1140                                    trie_element<Key, Value>,
1141                                    trie_element<Key, Value &>>
1142     {
1143     private:
1144         const_trie_map_iterator<Key, Value> it_;
1145         using ref_type = trie_element<Key, Value &>;
1146         using ptr_type = stl_interfaces::proxy_arrow_result<ref_type>;
1147 
1148     public:
1149         trie_map_iterator() {}
1150 
1151         trie_map_iterator(trie_match_result match_result) :
1152             trie_map_iterator(const_trie_map_iterator<Key, Value>(match_result))
1153         {}
1154 
1155         ref_type operator*() const
1156         {
1157             return ref_type{detail::reconstruct_key(it_.state_),
1158                             it_.state_.parent_->child_value(it_.state_.index_)};
1159         };
1160 
1161         ptr_type operator->() const
1162         {
1163             ref_type && deref_result = **this;
1164             return ptr_type(
1165                 ref_type{std::move(deref_result.key), deref_result.value});
1166         }
1167 
1168         trie_map_iterator & operator++()
1169         {
1170             ++it_;
1171             return *this;
1172         }
1173         trie_map_iterator & operator--()
1174         {
1175             --it_;
1176             return *this;
1177         }
1178 
1179         friend bool
1180         operator==(trie_map_iterator lhs, trie_map_iterator rhs)
1181         {
1182             return lhs.it_ == rhs.it_;
1183         }
1184 
1185         using base_type = stl_interfaces::iterator_interface<
1186             trie_map_iterator<Key, Value>,
1187             std::bidirectional_iterator_tag,
1188             trie_element<Key, Value>,
1189             trie_element<Key, Value &>>;
1190         using base_type::operator++;
1191         using base_type::operator--;
1192 
1193 #ifndef BOOST_PARSER_DOXYGEN
1194 
1195     private:
1196         explicit trie_map_iterator(
1197             detail::trie_iterator_state_t<Key, Value> state) :
1198             it_(state)
1199         {}
1200         explicit trie_map_iterator(const_trie_map_iterator<Key, Value> it) :
1201             it_(it)
1202         {}
1203 
1204         template<typename KeyT, typename ValueT, typename Compare>
1205         friend struct trie_map;
1206         template<typename KeyT, typename Compare>
1207         friend struct trie_set;
1208 
1209 #endif
1210     };
1211 
1212 }}
1213 
1214 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
1215 
1216 namespace std::ranges {
1217     template<typename Iter>
1218     inline constexpr bool
1219         enable_borrowed_range<boost::parser::detail::text::trie_range<Iter>> =
1220             true;
1221     template<typename Iter>
1222     inline constexpr bool enable_borrowed_range<
1223         boost::parser::detail::text::const_trie_range<Iter>> = true;
1224 }
1225 
1226 #endif
1227 
1228 #endif