123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- // __ _____ _____ _____
- // __| | __| | | | JSON for Modern C++
- // | | |__ | | | | | | version 3.11.2
- // |_____|_____|_____|_|___| https://github.com/nlohmann/json
- //
- // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
- // SPDX-License-Identifier: MIT
- #pragma once
- #include <functional> // equal_to, less
- #include <initializer_list> // initializer_list
- #include <iterator> // input_iterator_tag, iterator_traits
- #include <memory> // allocator
- #include <stdexcept> // for out_of_range
- #include <type_traits> // enable_if, is_convertible
- #include <utility> // pair
- #include <vector> // vector
- #include <nlohmann/detail/macro_scope.hpp>
- #include <nlohmann/detail/meta/type_traits.hpp>
- NLOHMANN_JSON_NAMESPACE_BEGIN
- /// ordered_map: a minimal map-like container that preserves insertion order
- /// for use within nlohmann::basic_json<ordered_map>
- template <class Key, class T, class IgnoredLess = std::less<Key>,
- class Allocator = std::allocator<std::pair<const Key, T>>>
- struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
- {
- using key_type = Key;
- using mapped_type = T;
- using Container = std::vector<std::pair<const Key, T>, Allocator>;
- using iterator = typename Container::iterator;
- using const_iterator = typename Container::const_iterator;
- using size_type = typename Container::size_type;
- using value_type = typename Container::value_type;
- #ifdef JSON_HAS_CPP_14
- using key_compare = std::equal_to<>;
- #else
- using key_compare = std::equal_to<Key>;
- #endif
- // Explicit constructors instead of `using Container::Container`
- // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
- ordered_map() noexcept(noexcept(Container())) : Container{} {}
- explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
- template <class It>
- ordered_map(It first, It last, const Allocator& alloc = Allocator())
- : Container{first, last, alloc} {}
- ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
- : Container{init, alloc} {}
- std::pair<iterator, bool> emplace(const key_type& key, T&& t)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return {it, false};
- }
- }
- Container::emplace_back(key, std::forward<T>(t));
- return {std::prev(this->end()), true};
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- std::pair<iterator, bool> emplace(KeyType && key, T && t)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return {it, false};
- }
- }
- Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
- return {std::prev(this->end()), true};
- }
- T& operator[](const key_type& key)
- {
- return emplace(key, T{}).first->second;
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- T & operator[](KeyType && key)
- {
- return emplace(std::forward<KeyType>(key), T{}).first->second;
- }
- const T& operator[](const key_type& key) const
- {
- return at(key);
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- const T & operator[](KeyType && key) const
- {
- return at(std::forward<KeyType>(key));
- }
- T& at(const key_type& key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it->second;
- }
- }
- JSON_THROW(std::out_of_range("key not found"));
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- T & at(KeyType && key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it->second;
- }
- }
- JSON_THROW(std::out_of_range("key not found"));
- }
- const T& at(const key_type& key) const
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it->second;
- }
- }
- JSON_THROW(std::out_of_range("key not found"));
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- const T & at(KeyType && key) const
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it->second;
- }
- }
- JSON_THROW(std::out_of_range("key not found"));
- }
- size_type erase(const key_type& key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- // Since we cannot move const Keys, re-construct them in place
- for (auto next = it; ++next != this->end(); ++it)
- {
- it->~value_type(); // Destroy but keep allocation
- new (&*it) value_type{std::move(*next)};
- }
- Container::pop_back();
- return 1;
- }
- }
- return 0;
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- size_type erase(KeyType && key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- // Since we cannot move const Keys, re-construct them in place
- for (auto next = it; ++next != this->end(); ++it)
- {
- it->~value_type(); // Destroy but keep allocation
- new (&*it) value_type{std::move(*next)};
- }
- Container::pop_back();
- return 1;
- }
- }
- return 0;
- }
- iterator erase(iterator pos)
- {
- return erase(pos, std::next(pos));
- }
- iterator erase(iterator first, iterator last)
- {
- if (first == last)
- {
- return first;
- }
- const auto elements_affected = std::distance(first, last);
- const auto offset = std::distance(Container::begin(), first);
- // This is the start situation. We need to delete elements_affected
- // elements (3 in this example: e, f, g), and need to return an
- // iterator past the last deleted element (h in this example).
- // Note that offset is the distance from the start of the vector
- // to first. We will need this later.
- // [ a, b, c, d, e, f, g, h, i, j ]
- // ^ ^
- // first last
- // Since we cannot move const Keys, we re-construct them in place.
- // We start at first and re-construct (viz. copy) the elements from
- // the back of the vector. Example for first iteration:
- // ,--------.
- // v | destroy e and re-construct with h
- // [ a, b, c, d, e, f, g, h, i, j ]
- // ^ ^
- // it it + elements_affected
- for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
- {
- it->~value_type(); // destroy but keep allocation
- new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
- }
- // [ a, b, c, d, h, i, j, h, i, j ]
- // ^ ^
- // first last
- // remove the unneeded elements at the end of the vector
- Container::resize(this->size() - static_cast<size_type>(elements_affected));
- // [ a, b, c, d, h, i, j ]
- // ^ ^
- // first last
- // first is now pointing past the last deleted element, but we cannot
- // use this iterator, because it may have been invalidated by the
- // resize call. Instead, we can return begin() + offset.
- return Container::begin() + offset;
- }
- size_type count(const key_type& key) const
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return 1;
- }
- }
- return 0;
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- size_type count(KeyType && key) const
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return 1;
- }
- }
- return 0;
- }
- iterator find(const key_type& key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it;
- }
- }
- return Container::end();
- }
- template<class KeyType, detail::enable_if_t<
- detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
- iterator find(KeyType && key)
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it;
- }
- }
- return Container::end();
- }
- const_iterator find(const key_type& key) const
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, key))
- {
- return it;
- }
- }
- return Container::end();
- }
- std::pair<iterator, bool> insert( value_type&& value )
- {
- return emplace(value.first, std::move(value.second));
- }
- std::pair<iterator, bool> insert( const value_type& value )
- {
- for (auto it = this->begin(); it != this->end(); ++it)
- {
- if (m_compare(it->first, value.first))
- {
- return {it, false};
- }
- }
- Container::push_back(value);
- return {--this->end(), true};
- }
- template<typename InputIt>
- using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
- std::input_iterator_tag>::value>::type;
- template<typename InputIt, typename = require_input_iter<InputIt>>
- void insert(InputIt first, InputIt last)
- {
- for (auto it = first; it != last; ++it)
- {
- insert(*it);
- }
- }
- private:
- JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
- };
- NLOHMANN_JSON_NAMESPACE_END
|