P4C
The P4 Compiler
Loading...
Searching...
No Matches
string_map.h
1/*
2Licensed under the Apache License, Version 2.0 (the "License");
3you may not use this file except in compliance with the License.
4You may obtain a copy of the License at
5
6 http://www.apache.org/licenses/LICENSE-2.0
7
8Unless required by applicable law or agreed to in writing, software
9distributed under the License is distributed on an "AS IS" BASIS,
10WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11See the License for the specific language governing permissions and
12limitations under the License.
13*/
14
15#ifndef LIB_STRING_MAP_H_
16#define LIB_STRING_MAP_H_
17
18#include <initializer_list>
19#include <list>
20#include <stdexcept>
21#include <utility>
22
23#include "absl/container/flat_hash_map.h"
24#include "cstring.h"
25
26namespace P4 {
27
40template <class V>
42 public:
43 using key_type = cstring;
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 &;
48
49 private:
50 // TODO: Allow different containers (e.g. vector / small vector)
51 using list_type = std::list<value_type>;
52 using list_iterator = typename list_type::iterator;
53 list_type data;
54
55 public:
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>;
60
61 private:
62 using map_type = absl::flat_hash_map<cstring, list_iterator>;
63 map_type data_map;
64 void init_data_map() {
65 data_map.clear();
66 for (auto it = data.begin(); it != data.end(); it++) data_map.emplace(it->first, it);
67 }
68 iterator tr_iter(typename map_type::iterator i) {
69 if (i == data_map.end()) return data.end();
70 return i->second;
71 }
72 const_iterator tr_iter(typename map_type::const_iterator i) const {
73 if (i == data_map.end()) return data.end();
74 return i->second;
75 }
76
77 public:
78 using size_type = typename map_type::size_type;
79
80 string_map() = default;
81 string_map(const string_map &a) : data(a.data) { init_data_map(); }
82 template <typename InputIt>
83 string_map(InputIt first, InputIt last) {
84 insert(first, last);
85 }
86 string_map(string_map &&a) = default;
87 string_map &operator=(const string_map &a) {
88 if (this != &a) {
89 data.clear();
90 data.insert(data.end(), a.data.begin(), a.data.end());
91 init_data_map();
92 }
93 return *this;
94 }
95 string_map &operator=(string_map &&a) = default;
96 string_map(std::initializer_list<value_type> il) { insert(il.begin(), il.end()); }
97
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(); }
110
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(); }
116 bool operator==(const string_map &a) const { return data == a.data; }
117 bool operator!=(const string_map &a) const { return data != a.data; }
118 void clear() {
119 data.clear();
120 data_map.clear();
121 }
122
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();
131
132 return tr_iter(data_map.find(key));
133 }
134 const_iterator find(cstring a) const { return tr_iter(data_map.find(a)); }
135 const_iterator find(std::string_view a) const {
136 cstring key = cstring::get_cached(a);
137 if (key.isNull()) return data.end();
138
139 return tr_iter(data_map.find(key));
140 }
141
142 size_type count(cstring a) const { return data_map.count(a); }
143 size_type count(std::string_view a) const {
144 cstring key = cstring::get_cached(a);
145 if (key.isNull()) return 0;
146
147 return data_map.count(key);
148 }
149
150 bool contains(cstring a) const { return data_map.contains(a); }
151 bool contains(std::string_view a) const {
152 cstring key = cstring::get_cached(a);
153 if (key.isNull()) return false;
154
155 return data_map.contains(key);
156 }
157
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);
165 }
166 return it->second;
167 }
168
169 template <typename Key>
170 V &at(Key &&k) {
171 auto it = find(std::forward<Key>(k));
172 if (it == data.end()) throw std::out_of_range("string_map::at");
173 return it->second;
174 }
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");
179 return it->second;
180 }
181
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);
189 return {it, true};
190 }
191 return {it, false};
192 }
193
194 std::pair<iterator, bool> insert(value_type &&value) {
195 return emplace(std::move(value.first), std::move(value.second));
196 }
197 std::pair<iterator, bool> insert(const value_type &value) {
198 return emplace(value.first, value.second);
199 }
200
201 template <class InputIterator>
202 void insert(InputIterator b, InputIterator e) {
203 while (b != e) insert(*b++);
204 }
205
206 iterator erase(const_iterator pos) {
207 auto it = data_map.find(pos->first);
208 assert(it != data_map.end());
209 // get the non-const std::list iterator -- libstdc++ is missing
210 // std::list::erase(const_iterator) overload
211 auto list_it = it->second;
212 data_map.erase(it);
213 return data.erase(list_it);
214 }
215 size_type erase(cstring k) {
216 auto it = find(k);
217 if (it != data.end()) {
218 data_map.erase(k);
219 data.erase(it);
220 return 1;
221 }
222 return 0;
223 }
224 size_type erase(std::string_view k) {
225 auto it = find(k);
226 if (it != data.end()) {
227 data_map.erase(it->first);
228 data.erase(it);
229 return 1;
230 }
231 return 0;
232 }
233
234 void swap(string_map &other) {
235 using std::swap;
236 swap(data, other.data);
237 swap(data_map, other.data_map);
238 }
239};
240
241} // namespace P4
242
243#endif /* LIB_STRING_MAP_H_ */
Definition cstring.h:85
static cstring get_cached(std::string_view s)
Definition cstring.cpp:194
Definition string_map.h:41
bool operator==(const string_map &a) const
Definition string_map.h:116
iterator find(std::string_view a)
Definition string_map.h:128
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24