Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.11.3
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 #pragma once
0010 
0011 #include <functional> // equal_to, less
0012 #include <initializer_list> // initializer_list
0013 #include <iterator> // input_iterator_tag, iterator_traits
0014 #include <memory> // allocator
0015 #include <stdexcept> // for out_of_range
0016 #include <type_traits> // enable_if, is_convertible
0017 #include <utility> // pair
0018 #include <vector> // vector
0019 
0020 #include <nlohmann/detail/macro_scope.hpp>
0021 #include <nlohmann/detail/meta/type_traits.hpp>
0022 
0023 NLOHMANN_JSON_NAMESPACE_BEGIN
0024 
0025 /// ordered_map: a minimal map-like container that preserves insertion order
0026 /// for use within nlohmann::basic_json<ordered_map>
0027 template <class Key, class T, class IgnoredLess = std::less<Key>,
0028           class Allocator = std::allocator<std::pair<const Key, T>>>
0029                   struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
0030 {
0031     using key_type = Key;
0032     using mapped_type = T;
0033     using Container = std::vector<std::pair<const Key, T>, Allocator>;
0034     using iterator = typename Container::iterator;
0035     using const_iterator = typename Container::const_iterator;
0036     using size_type = typename Container::size_type;
0037     using value_type = typename Container::value_type;
0038 #ifdef JSON_HAS_CPP_14
0039     using key_compare = std::equal_to<>;
0040 #else
0041     using key_compare = std::equal_to<Key>;
0042 #endif
0043 
0044     // Explicit constructors instead of `using Container::Container`
0045     // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
0046     ordered_map() noexcept(noexcept(Container())) : Container{} {}
0047     explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
0048     template <class It>
0049     ordered_map(It first, It last, const Allocator& alloc = Allocator())
0050         : Container{first, last, alloc} {}
0051     ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
0052         : Container{init, alloc} {}
0053 
0054     std::pair<iterator, bool> emplace(const key_type& key, T&& t)
0055     {
0056         for (auto it = this->begin(); it != this->end(); ++it)
0057         {
0058             if (m_compare(it->first, key))
0059             {
0060                 return {it, false};
0061             }
0062         }
0063         Container::emplace_back(key, std::forward<T>(t));
0064         return {std::prev(this->end()), true};
0065     }
0066 
0067     template<class KeyType, detail::enable_if_t<
0068                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0069     std::pair<iterator, bool> emplace(KeyType && key, T && t)
0070     {
0071         for (auto it = this->begin(); it != this->end(); ++it)
0072         {
0073             if (m_compare(it->first, key))
0074             {
0075                 return {it, false};
0076             }
0077         }
0078         Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
0079         return {std::prev(this->end()), true};
0080     }
0081 
0082     T& operator[](const key_type& key)
0083     {
0084         return emplace(key, T{}).first->second;
0085     }
0086 
0087     template<class KeyType, detail::enable_if_t<
0088                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0089     T & operator[](KeyType && key)
0090     {
0091         return emplace(std::forward<KeyType>(key), T{}).first->second;
0092     }
0093 
0094     const T& operator[](const key_type& key) const
0095     {
0096         return at(key);
0097     }
0098 
0099     template<class KeyType, detail::enable_if_t<
0100                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0101     const T & operator[](KeyType && key) const
0102     {
0103         return at(std::forward<KeyType>(key));
0104     }
0105 
0106     T& at(const key_type& key)
0107     {
0108         for (auto it = this->begin(); it != this->end(); ++it)
0109         {
0110             if (m_compare(it->first, key))
0111             {
0112                 return it->second;
0113             }
0114         }
0115 
0116         JSON_THROW(std::out_of_range("key not found"));
0117     }
0118 
0119     template<class KeyType, detail::enable_if_t<
0120                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0121     T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
0122     {
0123         for (auto it = this->begin(); it != this->end(); ++it)
0124         {
0125             if (m_compare(it->first, key))
0126             {
0127                 return it->second;
0128             }
0129         }
0130 
0131         JSON_THROW(std::out_of_range("key not found"));
0132     }
0133 
0134     const T& at(const key_type& key) const
0135     {
0136         for (auto it = this->begin(); it != this->end(); ++it)
0137         {
0138             if (m_compare(it->first, key))
0139             {
0140                 return it->second;
0141             }
0142         }
0143 
0144         JSON_THROW(std::out_of_range("key not found"));
0145     }
0146 
0147     template<class KeyType, detail::enable_if_t<
0148                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0149     const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
0150     {
0151         for (auto it = this->begin(); it != this->end(); ++it)
0152         {
0153             if (m_compare(it->first, key))
0154             {
0155                 return it->second;
0156             }
0157         }
0158 
0159         JSON_THROW(std::out_of_range("key not found"));
0160     }
0161 
0162     size_type erase(const key_type& key)
0163     {
0164         for (auto it = this->begin(); it != this->end(); ++it)
0165         {
0166             if (m_compare(it->first, key))
0167             {
0168                 // Since we cannot move const Keys, re-construct them in place
0169                 for (auto next = it; ++next != this->end(); ++it)
0170                 {
0171                     it->~value_type(); // Destroy but keep allocation
0172                     new (&*it) value_type{std::move(*next)};
0173                 }
0174                 Container::pop_back();
0175                 return 1;
0176             }
0177         }
0178         return 0;
0179     }
0180 
0181     template<class KeyType, detail::enable_if_t<
0182                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0183     size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
0184     {
0185         for (auto it = this->begin(); it != this->end(); ++it)
0186         {
0187             if (m_compare(it->first, key))
0188             {
0189                 // Since we cannot move const Keys, re-construct them in place
0190                 for (auto next = it; ++next != this->end(); ++it)
0191                 {
0192                     it->~value_type(); // Destroy but keep allocation
0193                     new (&*it) value_type{std::move(*next)};
0194                 }
0195                 Container::pop_back();
0196                 return 1;
0197             }
0198         }
0199         return 0;
0200     }
0201 
0202     iterator erase(iterator pos)
0203     {
0204         return erase(pos, std::next(pos));
0205     }
0206 
0207     iterator erase(iterator first, iterator last)
0208     {
0209         if (first == last)
0210         {
0211             return first;
0212         }
0213 
0214         const auto elements_affected = std::distance(first, last);
0215         const auto offset = std::distance(Container::begin(), first);
0216 
0217         // This is the start situation. We need to delete elements_affected
0218         // elements (3 in this example: e, f, g), and need to return an
0219         // iterator past the last deleted element (h in this example).
0220         // Note that offset is the distance from the start of the vector
0221         // to first. We will need this later.
0222 
0223         // [ a, b, c, d, e, f, g, h, i, j ]
0224         //               ^        ^
0225         //             first    last
0226 
0227         // Since we cannot move const Keys, we re-construct them in place.
0228         // We start at first and re-construct (viz. copy) the elements from
0229         // the back of the vector. Example for first iteration:
0230 
0231         //               ,--------.
0232         //               v        |   destroy e and re-construct with h
0233         // [ a, b, c, d, e, f, g, h, i, j ]
0234         //               ^        ^
0235         //               it       it + elements_affected
0236 
0237         for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
0238         {
0239             it->~value_type(); // destroy but keep allocation
0240             new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
0241         }
0242 
0243         // [ a, b, c, d, h, i, j, h, i, j ]
0244         //               ^        ^
0245         //             first    last
0246 
0247         // remove the unneeded elements at the end of the vector
0248         Container::resize(this->size() - static_cast<size_type>(elements_affected));
0249 
0250         // [ a, b, c, d, h, i, j ]
0251         //               ^        ^
0252         //             first    last
0253 
0254         // first is now pointing past the last deleted element, but we cannot
0255         // use this iterator, because it may have been invalidated by the
0256         // resize call. Instead, we can return begin() + offset.
0257         return Container::begin() + offset;
0258     }
0259 
0260     size_type count(const key_type& key) const
0261     {
0262         for (auto it = this->begin(); it != this->end(); ++it)
0263         {
0264             if (m_compare(it->first, key))
0265             {
0266                 return 1;
0267             }
0268         }
0269         return 0;
0270     }
0271 
0272     template<class KeyType, detail::enable_if_t<
0273                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0274     size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
0275     {
0276         for (auto it = this->begin(); it != this->end(); ++it)
0277         {
0278             if (m_compare(it->first, key))
0279             {
0280                 return 1;
0281             }
0282         }
0283         return 0;
0284     }
0285 
0286     iterator find(const key_type& key)
0287     {
0288         for (auto it = this->begin(); it != this->end(); ++it)
0289         {
0290             if (m_compare(it->first, key))
0291             {
0292                 return it;
0293             }
0294         }
0295         return Container::end();
0296     }
0297 
0298     template<class KeyType, detail::enable_if_t<
0299                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
0300     iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
0301     {
0302         for (auto it = this->begin(); it != this->end(); ++it)
0303         {
0304             if (m_compare(it->first, key))
0305             {
0306                 return it;
0307             }
0308         }
0309         return Container::end();
0310     }
0311 
0312     const_iterator find(const key_type& key) const
0313     {
0314         for (auto it = this->begin(); it != this->end(); ++it)
0315         {
0316             if (m_compare(it->first, key))
0317             {
0318                 return it;
0319             }
0320         }
0321         return Container::end();
0322     }
0323 
0324     std::pair<iterator, bool> insert( value_type&& value )
0325     {
0326         return emplace(value.first, std::move(value.second));
0327     }
0328 
0329     std::pair<iterator, bool> insert( const value_type& value )
0330     {
0331         for (auto it = this->begin(); it != this->end(); ++it)
0332         {
0333             if (m_compare(it->first, value.first))
0334             {
0335                 return {it, false};
0336             }
0337         }
0338         Container::push_back(value);
0339         return {--this->end(), true};
0340     }
0341 
0342     template<typename InputIt>
0343     using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
0344             std::input_iterator_tag>::value>::type;
0345 
0346     template<typename InputIt, typename = require_input_iter<InputIt>>
0347     void insert(InputIt first, InputIt last)
0348     {
0349         for (auto it = first; it != last; ++it)
0350         {
0351             insert(*it);
0352         }
0353     }
0354 
0355 private:
0356     JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
0357 };
0358 
0359 NLOHMANN_JSON_NAMESPACE_END