mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
779 lines
30 KiB
C++
779 lines
30 KiB
C++
// Copyright (c) FIRST and other WPILib contributors.
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
#include <initializer_list>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace wpi::util {
|
|
|
|
/**
|
|
* StringMap is a sorted associative container that contains key-value pairs
|
|
* with unique string keys. Keys are sorted in the same order as std::string's
|
|
* are compared. Search, removal, and insertion operations have logarithmic
|
|
* complexity. The underlying implementation is std::map<std::string, T>.
|
|
*/
|
|
template <typename T,
|
|
typename Allocator = std::allocator<std::pair<const std::string, T>>>
|
|
class StringMap : public std::map<std::string, T, std::less<>, Allocator> {
|
|
public:
|
|
using map_type = typename std::map<std::string, T, std::less<>>;
|
|
using key_type = typename map_type::key_type;
|
|
using mapped_type = typename map_type::mapped_type;
|
|
using value_type = typename map_type::value_type;
|
|
using size_type = typename map_type::size_type;
|
|
using difference_type = typename map_type::difference_type;
|
|
using key_compare = typename map_type::key_compare;
|
|
using allocator_type = typename map_type::allocator_type;
|
|
using reference = typename map_type::reference;
|
|
using const_reference = typename map_type::const_reference;
|
|
using pointer = typename map_type::pointer;
|
|
using const_pointer = typename map_type::const_pointer;
|
|
using iterator = typename map_type::iterator;
|
|
using const_iterator = typename map_type::const_iterator;
|
|
using reverse_iterator = typename map_type::reverse_iterator;
|
|
using const_reverse_iterator = typename map_type::const_reverse_iterator;
|
|
using node_type = typename map_type::node_type;
|
|
using insert_return_type = typename map_type::insert_return_type;
|
|
|
|
/** Constructs an empty container. */
|
|
StringMap() = default;
|
|
|
|
/**
|
|
* Constructs an empty container.
|
|
*
|
|
* @param alloc allocator to use for all memory allocations of this container
|
|
*/
|
|
explicit StringMap(const Allocator& alloc) : map_type{alloc} {}
|
|
|
|
/**
|
|
* Constructs the container with the contents of the range [first, last). If
|
|
* multiple elements in the range have keys that compare equivalent, it is
|
|
* unspecified which element is inserted. If [first, last) is not a valid
|
|
* range, the behavior is undefined.
|
|
*
|
|
* @param first start of the range to copy the elements from
|
|
* @param last end of the range to copy the elements from
|
|
* @param alloc allocator to use for all memory allocations of this container
|
|
*/
|
|
template <typename InputIt>
|
|
StringMap(InputIt first, InputIt last, const Allocator& alloc = Allocator())
|
|
: map_type{first, last, alloc} {}
|
|
|
|
/** Copy constructor. */
|
|
StringMap(const StringMap&) = default;
|
|
|
|
/**
|
|
* Copy constructor.
|
|
*
|
|
* @param other another container to be used as source to initialize the
|
|
* elements of the container with
|
|
* @param alloc allocator to use for all memory allocations of this container
|
|
*/
|
|
StringMap(const StringMap& other, const Allocator& alloc)
|
|
: map_type{other, alloc} {}
|
|
|
|
/** Move constructor. */
|
|
StringMap(StringMap&&) = default;
|
|
|
|
/**
|
|
* Move constructor.
|
|
*
|
|
* @param other another container to be used as source to initialize the
|
|
* elements of the container with
|
|
* @param alloc allocator to use for all memory allocations of this container
|
|
*/
|
|
StringMap(StringMap&& other, const Allocator& alloc)
|
|
: map_type{other, alloc} {}
|
|
|
|
/**
|
|
* Initializer-list constructor. Construct the container with the contents of
|
|
* the initializer list init. If multiple elements in the range have keys
|
|
* that compare equal, it is unspecified which element is inserted.
|
|
*
|
|
* @param init initializer list to initialize the elements of the container
|
|
* with
|
|
* @param alloc allocator to use for all memory allocations of this container
|
|
*/
|
|
// NOLINTNEXTLINE (google-explicit-constructor)
|
|
StringMap(std::initializer_list<value_type> init,
|
|
const Allocator& alloc = Allocator())
|
|
: map_type{init, alloc} {}
|
|
|
|
/** Copy assignment operator. */
|
|
StringMap& operator=(const StringMap&) = default;
|
|
|
|
/** Move assignment operator. */
|
|
StringMap& operator=(StringMap&&) noexcept(
|
|
std::allocator_traits<Allocator>::is_always_equal::value &&
|
|
std::is_nothrow_move_assignable<std::less<>>::value) = default;
|
|
|
|
/**
|
|
* Replaces the contents with those identified by initializer list ilist.
|
|
*
|
|
* @param ilist initializer list to use as data source
|
|
*/
|
|
StringMap& operator=(std::initializer_list<value_type> ilist) {
|
|
map_type::operator=(ilist);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
T& at(const std::string& key) { return map_type::at(key); }
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
const T& at(const std::string& key) const { return map_type::at(key); }
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
T& at(const char* key) { return at(std::string_view{key}); }
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
const T& at(const char* key) const { return at(std::string_view{key}); }
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
T& at(std::string_view key) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::at(key);
|
|
#else
|
|
auto it = find(key);
|
|
if (it == this->end()) {
|
|
throw std::out_of_range{std::string{key}};
|
|
}
|
|
return it->second;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Returns a reference to the mapped value of the element with the specified
|
|
* key. If no such element exists, an exception of type std::out_of_range is
|
|
* thrown.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the requested element.
|
|
*/
|
|
const T& at(std::string_view key) const {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::at(key);
|
|
#else
|
|
auto it = find(key);
|
|
if (it == this->end()) {
|
|
throw std::out_of_range{std::string{key}};
|
|
}
|
|
return it->second;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Returns a reference to the value that is mapped to a key, performing an
|
|
* insertion if such a key does not exist.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the new element if no element
|
|
* with key key existed. Otherwise, a reference to the mapped value
|
|
* of the existing element whose key is equal to key.
|
|
*/
|
|
T& operator[](const std::string& key) { return map_type::operator[](key); }
|
|
|
|
/**
|
|
* Returns a reference to the value that is mapped to a key, performing an
|
|
* insertion if such a key does not exist.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the new element if no element
|
|
* with key key existed. Otherwise, a reference to the mapped value
|
|
* of the existing element whose key is equal to key.
|
|
*/
|
|
T& operator[](std::string&& key) {
|
|
return map_type::operator[](std::move(key));
|
|
}
|
|
|
|
/**
|
|
* Returns a reference to the value that is mapped to a key, performing an
|
|
* insertion if such a key does not exist.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the new element if no element
|
|
* with key key existed. Otherwise, a reference to the mapped value
|
|
* of the existing element whose key is equal to key.
|
|
*/
|
|
T& operator[](const char* key) { return operator[](std::string_view{key}); }
|
|
|
|
/**
|
|
* Returns a reference to the value that is mapped to a key, performing an
|
|
* insertion if such a key does not exist.
|
|
*
|
|
* @param key the key of the element to find
|
|
* @return A reference to the mapped value of the new element if no element
|
|
* with key key existed. Otherwise, a reference to the mapped value
|
|
* of the existing element whose key is equal to key.
|
|
*/
|
|
T& operator[](std::string_view key) { return try_emplace(key).first->second; }
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return The bool component is true if the insertion took place and false if
|
|
* the assignment took place. The iterator component is pointing at
|
|
* the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
std::pair<iterator, bool> insert_or_assign(std::string&& key, M&& obj) {
|
|
return map_type::insert_or_assign(std::move(key), std::forward<M>(obj));
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return The bool component is true if the insertion took place and false if
|
|
* the assignment took place. The iterator component is pointing at
|
|
* the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
std::pair<iterator, bool> insert_or_assign(const char* key, M&& obj) {
|
|
return insert_or_assign(std::string_view{key}, std::forward<M>(obj));
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return The bool component is true if the insertion took place and false if
|
|
* the assignment took place. The iterator component is pointing at
|
|
* the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
std::pair<iterator, bool> insert_or_assign(std::string_view key, M&& obj) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::insert_or_assign(key, std::forward<M>(obj));
|
|
#else
|
|
auto it = lower_bound(key);
|
|
if (it != this->end() && it->first == key) {
|
|
it->second = std::forward<M>(obj);
|
|
return {it, false};
|
|
} else {
|
|
return {this->insert(it, {std::string{key}, std::forward<M>(obj)}), true};
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return Iterator pointing at the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
iterator insert_or_assign(const_iterator hint, std::string&& key, M&& obj) {
|
|
return map_type::insert_or_assign(hint, std::move(key),
|
|
std::forward<M>(obj));
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return Iterator pointing at the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
iterator insert_or_assign(const_iterator hint, const char* key, M&& obj) {
|
|
return insert_or_assign(hint, std::string_view{key}, std::forward<M>(obj));
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, assigns obj to the
|
|
* mapped type corresponding to that key. If the key does not exist, inserts
|
|
* the value as if by calling insert().
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param obj the value to insert or assign
|
|
* @return Iterator pointing at the element that was inserted or updated.
|
|
*/
|
|
template <typename M>
|
|
iterator insert_or_assign(const_iterator hint, std::string_view key,
|
|
M&& obj) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::insert_or_assign(hint, key, std::forward<M>(obj));
|
|
#else
|
|
return map_type::insert_or_assign(hint, std::string{key},
|
|
std::forward<M>(obj));
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Inserts a new element into the container constructed in-place with the
|
|
* given args, if there is no element with the key in the container.
|
|
*
|
|
* No iterators or references are invalidated.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> emplace(std::string&& key, Args&&... args) {
|
|
return map_type::emplace(std::move(key), std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Inserts a new element into the container constructed in-place with the
|
|
* given args, if there is no element with the key in the container.
|
|
*
|
|
* No iterators or references are invalidated.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> emplace(const char* key, Args&&... args) {
|
|
return emplace(std::string_view{key}, std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Inserts a new element into the container constructed in-place with the
|
|
* given args, if there is no element with the key in the container.
|
|
*
|
|
* No iterators or references are invalidated.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> emplace(std::string_view key, Args&&... args) {
|
|
return try_emplace(key, std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> try_emplace(std::string&& key, Args&&... args) {
|
|
return map_type::try_emplace(std::move(key), std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> try_emplace(const char* key, Args&&... args) {
|
|
return try_emplace(std::string_view{key}, std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return A pair consisting of an interator to the inserted element (or to
|
|
* the element that prevented the insertion) and a bool value set to
|
|
* true if and only if the insertion took place.
|
|
*/
|
|
template <typename... Args>
|
|
std::pair<iterator, bool> try_emplace(std::string_view key, Args&&... args) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::try_emplace(key, std::forward<Args>(args)...);
|
|
#else
|
|
auto it = lower_bound(key);
|
|
if (it != this->end() && it->first == key) {
|
|
return {it, false};
|
|
} else {
|
|
return {try_emplace(it, key, std::forward<Args>(args)...), true};
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return An interator to the inserted element, or to the element that
|
|
* prevented the insertion.
|
|
*/
|
|
template <typename... Args>
|
|
iterator try_emplace(const_iterator hint, std::string&& key, Args&&... args) {
|
|
return map_type::try_emplace(hint, std::move(key),
|
|
std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return An interator to the inserted element, or to the element that
|
|
* prevented the insertion.
|
|
*/
|
|
template <typename... Args>
|
|
iterator try_emplace(const_iterator hint, const char* key, Args&&... args) {
|
|
return try_emplace(hint, std::string_view{key},
|
|
std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* If a key equal to key already exists in the container, does nothing.
|
|
* Otherwise, inserts a new element into the container with key key and value
|
|
* constructed with args.
|
|
*
|
|
* @param hint iterator to the position before which the new element will be
|
|
* inserted
|
|
* @param key the key used both to look up and to insert if not found
|
|
* @param args arguments to forward to the constructor of the element
|
|
* @return An interator to the inserted element, or to the element that
|
|
* prevented the insertion.
|
|
*/
|
|
template <typename... Args>
|
|
iterator try_emplace(const_iterator hint, std::string_view key,
|
|
Args&&... args) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::try_emplace(hint, key, std::forward<Args>(args)...);
|
|
#else
|
|
return map_type::try_emplace(hint, std::string{key},
|
|
std::forward<Args>(args)...);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Removes the element at pos.
|
|
*
|
|
* @param pos iterator to the element to remove
|
|
* @return Iterator following the removed element.
|
|
*/
|
|
iterator erase(iterator pos) { return map_type::erase(pos); }
|
|
|
|
/**
|
|
* Removes the element at pos.
|
|
*
|
|
* @param pos iterator to the element to remove
|
|
* @return Iterator following the removed element.
|
|
*/
|
|
iterator erase(const_iterator pos) { return map_type::erase(pos); }
|
|
|
|
/**
|
|
* Removes the elements in the range [first, last), which must be a valid
|
|
* range in this.
|
|
*
|
|
* @param first Start of the range of elements to remove
|
|
* @param last End of the range of elements to remove
|
|
* @return Iterator following the last removed element.
|
|
*/
|
|
iterator erase(iterator first, iterator last) {
|
|
return map_type::erase(first, last);
|
|
}
|
|
|
|
/**
|
|
* Removes the elements in the range [first, last), which must be a valid
|
|
* range in this.
|
|
*
|
|
* @param first Start of the range of elements to remove
|
|
* @param last End of the range of elements to remove
|
|
* @return Iterator following the last removed element.
|
|
*/
|
|
iterator erase(const_iterator first, const_iterator last) {
|
|
return map_type::erase(first, last);
|
|
}
|
|
|
|
/**
|
|
* Removes the element (if one exists) with the key equal to key.
|
|
*
|
|
* @param key key value of the elements to remove
|
|
* @return Number of elements removed (0 or 1).
|
|
*/
|
|
size_type erase(std::string_view key) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_erasure
|
|
return map_type::erase(key);
|
|
#else
|
|
auto it = find(key);
|
|
if (it == this->end()) {
|
|
return 0;
|
|
}
|
|
this->erase(it);
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Exchanges the contents of the container with those of other. Does not
|
|
* invoke any move, copy, or swap operations on individual elements.
|
|
*
|
|
* All iterators and references remain valid. The end() iterator is
|
|
* invalidated.
|
|
*
|
|
* @param other container to exchange the contents with
|
|
*/
|
|
void swap(StringMap& other) noexcept(
|
|
std::allocator_traits<Allocator>::is_always_equal::value &&
|
|
std::is_nothrow_swappable<std::less<>>::value) {
|
|
map_type::swap(other);
|
|
}
|
|
|
|
/**
|
|
* Unlinks the node that contains the element pointed to by position and
|
|
* returns a node handle that owns it.
|
|
*
|
|
* @param position a valid iterator into this container
|
|
* @return A node handle that owns the extracted element
|
|
*/
|
|
node_type extract(const_iterator position) {
|
|
return map_type::extract(position);
|
|
}
|
|
|
|
/**
|
|
* If the container has an element with key equal to key, unlinks the node
|
|
* that contains that element from the container and returns a node handle
|
|
* that owns it. Otherwise, returns an empty node handle.
|
|
*
|
|
* @param key a key to identify the node to be extracted
|
|
* @return A node handle that owns the extracted element, or empty node handle
|
|
* in case the element is not found.
|
|
*/
|
|
node_type extract(std::string_view key) {
|
|
#ifdef __cpp_lib_associative_heterogeneous_insertion
|
|
return map_type::extract(key);
|
|
#else
|
|
auto it = find(key);
|
|
if (it == this->end()) {
|
|
return {};
|
|
}
|
|
return extract(it);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Returns the number of elements with key that equals the specified argument.
|
|
*
|
|
* @param key key value of the elements to count
|
|
* @return Number of elements with key that equals key (either 0 or 1).
|
|
*/
|
|
size_type count(std::string_view key) const { return map_type::count(key); }
|
|
|
|
/**
|
|
* Finds an element with key equal to key.
|
|
*
|
|
* @param key key value of the element to search for
|
|
* @return An iterator to the requested element. If no such element is found,
|
|
* past-the-end (see end()) iterator is returned.
|
|
*/
|
|
iterator find(std::string_view key) { return map_type::find(key); }
|
|
|
|
/**
|
|
* Finds an element with key equal to key.
|
|
*
|
|
* @param key key value of the element to search for
|
|
* @return An iterator to the requested element. If no such element is found,
|
|
* past-the-end (see end()) iterator is returned.
|
|
*/
|
|
const_iterator find(std::string_view key) const {
|
|
return map_type::find(key);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is an element with key equal to key in the container.
|
|
*
|
|
* @param key key value of the element to search for
|
|
* @return true if there is such an element, otherwise false
|
|
*/
|
|
bool contains(std::string_view key) const { return map_type::contains(key); }
|
|
|
|
/**
|
|
* Returns a range containing all elements with the given key in the
|
|
* container. The range is defined by two iterators, one pointing to the
|
|
* first element that is not less than key and another pointing to the first
|
|
* element greater than key. Alternatively, the first iterator may be
|
|
* obtained with lower_bound(), and the second with upper_bound().
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return std::pair containing a pair of iterators defining the wanted range:
|
|
* the first pointing to the first element that is not less than key
|
|
* and the second pointing to the first element greater than key. If
|
|
* there are no elements not less than key, past-the-end (see end())
|
|
* iterator is returned as the first element. Similarly if there are
|
|
* no elements greater than key, past-the-end iterator is returned as
|
|
* the second element.
|
|
*/
|
|
std::pair<iterator, iterator> equal_range(std::string_view key) {
|
|
return map_type::equal_range(key);
|
|
}
|
|
|
|
/**
|
|
* Returns a range containing all elements with the given key in the
|
|
* container. The range is defined by two iterators, one pointing to the
|
|
* first element that is not less than key and another pointing to the first
|
|
* element greater than key. Alternatively, the first iterator may be
|
|
* obtained with lower_bound(), and the second with upper_bound().
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return std::pair containing a pair of iterators defining the wanted range:
|
|
* the first pointing to the first element that is not less than key
|
|
* and the second pointing to the first element greater than key. If
|
|
* there are no elements not less than key, past-the-end (see end())
|
|
* iterator is returned as the first element. Similarly if there are
|
|
* no elements greater than key, past-the-end iterator is returned as
|
|
* the second element.
|
|
*/
|
|
std::pair<const_iterator, const_iterator> equal_range(
|
|
std::string_view key) const {
|
|
return map_type::equal_range(key);
|
|
}
|
|
|
|
/**
|
|
* Returns an iterator pointing to the first element that is not less than
|
|
* (i.e. greater or equal to) key.
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return Iterator pointing to the first element that is not less than key.
|
|
* If no such element is found, a past-the-end iterator (see end()) is
|
|
* returned.
|
|
*/
|
|
iterator lower_bound(std::string_view key) {
|
|
return map_type::lower_bound(key);
|
|
}
|
|
|
|
/**
|
|
* Returns an iterator pointing to the first element that is not less than
|
|
* (i.e. greater or equal to) key.
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return Iterator pointing to the first element that is not less than key.
|
|
* If no such element is found, a past-the-end iterator (see end()) is
|
|
* returned.
|
|
*/
|
|
const_iterator lower_bound(std::string_view key) const {
|
|
return map_type::lower_bound(key);
|
|
}
|
|
|
|
/**
|
|
* Returns an interator pointing to the first element that is greater than
|
|
* key.
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return Iterator pointing to the first element that is greater than key.
|
|
* If no such element is found, past-the-end (see end()) iterator is
|
|
* returned.
|
|
*/
|
|
iterator upper_bound(std::string_view key) {
|
|
return map_type::upper_bound(key);
|
|
}
|
|
|
|
/**
|
|
* Returns an interator pointing to the first element that is greater than
|
|
* key.
|
|
*
|
|
* @param key key value to compare the elements to
|
|
* @return Iterator pointing to the first element that is greater than key.
|
|
* If no such element is found, past-the-end (see end()) iterator is
|
|
* returned.
|
|
*/
|
|
const_iterator upper_bound(std::string_view key) const {
|
|
return map_type::upper_bound(key);
|
|
}
|
|
};
|
|
|
|
} // namespace wpi::util
|
|
|
|
namespace std {
|
|
template <typename T>
|
|
inline void swap(wpi::util::StringMap<T>& lhs, wpi::util::StringMap<T>& rhs) {
|
|
lhs.swap(rhs);
|
|
}
|
|
} // namespace std
|