44 using mapped_type = V;
45 using value_type = std::pair<cstring, V>;
46 using reference = value_type &;
47 using const_reference =
const value_type &;
51 using list_type = std::list<value_type>;
52 using list_iterator =
typename list_type::iterator;
56 using iterator =
typename list_type::iterator;
57 using const_iterator =
typename list_type::const_iterator;
58 using reverse_iterator = std::reverse_iterator<iterator>;
59 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
62 using map_type = absl::flat_hash_map<cstring, list_iterator>;
64 void init_data_map() {
66 for (
auto it = data.begin(); it != data.end(); it++) data_map.emplace(it->first, it);
68 iterator tr_iter(
typename map_type::iterator i) {
69 if (i == data_map.end())
return data.end();
72 const_iterator tr_iter(
typename map_type::const_iterator i)
const {
73 if (i == data_map.end())
return data.end();
78 using size_type =
typename map_type::size_type;
82 template <
typename InputIt>
90 data.insert(data.end(), a.data.begin(), a.data.end());
96 string_map(std::initializer_list<value_type> il) { insert(il.begin(), il.end()); }
98 iterator begin()
noexcept {
return data.begin(); }
99 const_iterator begin()
const noexcept {
return data.begin(); }
100 iterator end()
noexcept {
return data.end(); }
101 const_iterator end()
const noexcept {
return data.end(); }
102 reverse_iterator rbegin()
noexcept {
return data.rbegin(); }
103 const_reverse_iterator rbegin()
const noexcept {
return data.rbegin(); }
104 reverse_iterator rend()
noexcept {
return data.rend(); }
105 const_reverse_iterator rend()
const noexcept {
return data.rend(); }
106 const_iterator cbegin()
const noexcept {
return data.cbegin(); }
107 const_iterator cend()
const noexcept {
return data.cend(); }
108 const_reverse_iterator crbegin()
const noexcept {
return data.crbegin(); }
109 const_reverse_iterator crend()
const noexcept {
return data.crend(); }
111 bool empty()
const noexcept {
return data.empty(); }
112 size_type size()
const noexcept {
return data_map.size(); }
113 size_type max_size()
const noexcept {
return data_map.max_size(); }
117 bool operator!=(
const string_map &a)
const {
return data != a.data; }
123 iterator find(cstring a) {
return tr_iter(data_map.find(a)); }
128 iterator
find(std::string_view a) {
130 if (key.isNull())
return data.end();
132 return tr_iter(data_map.find(key));
134 const_iterator find(
cstring a)
const {
return tr_iter(data_map.find(a)); }
135 const_iterator find(std::string_view a)
const {
137 if (key.isNull())
return data.end();
139 return tr_iter(data_map.find(key));
142 size_type count(cstring a)
const {
return data_map.count(a); }
143 size_type count(std::string_view a)
const {
145 if (key.isNull())
return 0;
147 return data_map.count(key);
150 bool contains(cstring a)
const {
return data_map.contains(a); }
151 bool contains(std::string_view a)
const {
153 if (key.isNull())
return false;
155 return data_map.contains(key);
158 template <
typename Key>
159 V &operator[](Key &&k) {
160 auto it = find(key_type(std::forward<Key>(k)));
161 if (it == data.end()) {
162 it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k),
163 std::forward_as_tuple());
164 data_map.emplace(it->first, it);
169 template <
typename Key>
171 auto it = find(std::forward<Key>(k));
172 if (it == data.end())
throw std::out_of_range(
"string_map::at");
175 template <
typename Key>
176 const V &at(Key &&k)
const {
177 auto it = find(std::forward<Key>(k));
178 if (it == data.end())
throw std::out_of_range(
"string_map::at");
182 template <
typename Key,
typename... VV>
183 std::pair<iterator, bool> emplace(Key &&k, VV &&...v) {
184 auto it = find(key_type(std::forward<Key>(k)));
185 if (it == data.end()) {
186 it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k),
187 std::forward_as_tuple(std::forward<VV>(v)...));
188 data_map.emplace(it->first, it);
194 std::pair<iterator, bool> insert(value_type &&value) {
195 return emplace(std::move(value.first), std::move(value.second));
197 std::pair<iterator, bool> insert(
const value_type &value) {
198 return emplace(value.first, value.second);
201 template <
class InputIterator>
202 void insert(InputIterator b, InputIterator e) {
203 while (b != e) insert(*b++);
206 iterator erase(const_iterator pos) {
207 auto it = data_map.find(pos->first);
208 assert(it != data_map.end());
211 auto list_it = it->second;
213 return data.erase(list_it);
215 size_type erase(cstring k) {
217 if (it != data.end()) {
224 size_type erase(std::string_view k) {
226 if (it != data.end()) {
227 data_map.erase(it->first);
234 void swap(string_map &other) {
236 swap(data, other.data);
237 swap(data_map, other.data_map);