42 using mapped_type = V;
43 using value_type = std::pair<cstring, V>;
44 using reference = value_type &;
45 using const_reference =
const value_type &;
49 using list_type = std::list<value_type>;
50 using list_iterator =
typename list_type::iterator;
54 using iterator =
typename list_type::iterator;
55 using const_iterator =
typename list_type::const_iterator;
56 using reverse_iterator = std::reverse_iterator<iterator>;
57 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
60 using map_type = absl::flat_hash_map<cstring, list_iterator>;
62 void init_data_map() {
64 for (
auto it = data.begin(); it != data.end(); it++) data_map.emplace(it->first, it);
66 iterator tr_iter(
typename map_type::iterator i) {
67 if (i == data_map.end())
return data.end();
70 const_iterator tr_iter(
typename map_type::const_iterator i)
const {
71 if (i == data_map.end())
return data.end();
76 using size_type =
typename map_type::size_type;
80 template <
typename InputIt>
88 data.insert(data.end(), a.data.begin(), a.data.end());
94 string_map(std::initializer_list<value_type> il) { insert(il.begin(), il.end()); }
96 iterator begin()
noexcept {
return data.begin(); }
97 const_iterator begin()
const noexcept {
return data.begin(); }
98 iterator end()
noexcept {
return data.end(); }
99 const_iterator end()
const noexcept {
return data.end(); }
100 reverse_iterator rbegin()
noexcept {
return data.rbegin(); }
101 const_reverse_iterator rbegin()
const noexcept {
return data.rbegin(); }
102 reverse_iterator rend()
noexcept {
return data.rend(); }
103 const_reverse_iterator rend()
const noexcept {
return data.rend(); }
104 const_iterator cbegin()
const noexcept {
return data.cbegin(); }
105 const_iterator cend()
const noexcept {
return data.cend(); }
106 const_reverse_iterator crbegin()
const noexcept {
return data.crbegin(); }
107 const_reverse_iterator crend()
const noexcept {
return data.crend(); }
109 bool empty()
const noexcept {
return data.empty(); }
110 size_type size()
const noexcept {
return data_map.size(); }
111 size_type max_size()
const noexcept {
return data_map.max_size(); }
115 bool operator!=(
const string_map &a)
const {
return data != a.data; }
121 iterator find(
cstring a) {
return tr_iter(data_map.find(a)); }
126 iterator
find(std::string_view a) {
128 if (key.isNull())
return data.end();
130 return tr_iter(data_map.find(key));
132 const_iterator find(
cstring a)
const {
return tr_iter(data_map.find(a)); }
133 const_iterator find(std::string_view a)
const {
135 if (key.isNull())
return data.end();
137 return tr_iter(data_map.find(key));
140 size_type count(
cstring a)
const {
return data_map.count(a); }
141 size_type count(std::string_view a)
const {
143 if (key.isNull())
return 0;
145 return data_map.count(key);
148 bool contains(
cstring a)
const {
return data_map.contains(a); }
149 bool contains(std::string_view a)
const {
151 if (key.isNull())
return false;
153 return data_map.contains(key);
156 template <
typename Key>
157 V &operator[](Key &&k) {
158 auto it = find(key_type(std::forward<Key>(k)));
159 if (it == data.end()) {
160 it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k),
161 std::forward_as_tuple());
162 data_map.emplace(it->first, it);
167 template <
typename Key>
169 auto it = find(std::forward<Key>(k));
170 if (it == data.end())
throw std::out_of_range(
"string_map::at");
173 template <
typename Key>
174 const V &at(Key &&k)
const {
175 auto it = find(std::forward<Key>(k));
176 if (it == data.end())
throw std::out_of_range(
"string_map::at");
180 template <
typename Key,
typename... VV>
181 std::pair<iterator, bool> emplace(Key &&k, VV &&...v) {
182 auto it = find(key_type(std::forward<Key>(k)));
183 if (it == data.end()) {
184 it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k),
185 std::forward_as_tuple(std::forward<VV>(v)...));
186 data_map.emplace(it->first, it);
192 std::pair<iterator, bool> insert(value_type &&value) {
193 return emplace(std::move(value.first), std::move(value.second));
195 std::pair<iterator, bool> insert(
const value_type &value) {
196 return emplace(value.first, value.second);
199 template <
class InputIterator>
200 void insert(InputIterator b, InputIterator e) {
201 while (b != e) insert(*b++);
204 iterator erase(const_iterator pos) {
205 auto it = data_map.find(pos->first);
206 assert(it != data_map.end());
209 auto list_it = it->second;
211 return data.erase(list_it);
215 if (it != data.end()) {
222 size_type erase(std::string_view k) {
224 if (it != data.end()) {
225 data_map.erase(it->first);
234 swap(data, other.data);
235 swap(data_map, other.data_map);