P4C
The P4 Compiler
Loading...
Searching...
No Matches
backends/tofino/bf-asm/json.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_JSON_H_ // NOLINT(build/header_guard)
19#define BACKENDS_TOFINO_BF_ASM_JSON_H_
20
21#include <assert.h>
22
23#include <cinttypes>
24#include <iostream>
25#include <map>
26#include <memory>
27#include <stdexcept>
28#include <string>
29#include <typeindex>
30#include <vector>
31
32#include "backends/tofino/bf-asm/rvalue_reference_wrapper.h"
33#include "lib/ordered_map.h"
34
35using namespace P4;
36
37namespace json {
38
39/* this is std::make_unique, except that is missing in some compilers/versions. We give
40 * it a different name as other compilers complain about ambiguities if we don't... */
41template <class T, class... Args>
42std::unique_ptr<T> mkuniq(Args &&...args) {
43 std::unique_ptr<T> ret(new T(std::forward<Args>(args)...));
44 return ret;
45}
46
47class number;
48class string;
49class vector;
50class map;
51
52class obj {
53 public:
54 obj() {}
55 obj(const obj &) = default;
56 obj(obj &&) = default;
57 obj &operator=(const obj &) & = default;
58 obj &operator=(obj &&) & = default;
59 virtual ~obj() {}
60 virtual bool operator<(const obj &a) const = 0;
61 bool operator>=(const obj &a) const { return !(*this < a); }
62 bool operator>(const obj &a) const { return a < *this; }
63 bool operator<=(const obj &a) const { return !(a < *this); }
64 virtual bool operator==(const obj &a) const = 0;
65 bool operator!=(const obj &a) const { return !(*this == a); }
66 virtual bool operator==(const char * /*str*/) const { return false; }
67 virtual bool operator==(const std::string & /*str*/) const { return false; }
68 virtual bool operator==(const string & /*str*/) const { return false; }
69 bool operator!=(const char *str) const { return !(*this == str); }
70 virtual bool operator==(int64_t /*val*/) const { return false; }
71 bool operator!=(int64_t val) const { return !(*this == val); }
72 struct ptrless {
73 bool operator()(const obj *a, const obj *b) const { return b ? a ? *a < *b : true : false; }
74 bool operator()(const std::unique_ptr<obj> &a, const std::unique_ptr<obj> &b) const {
75 return b ? a ? *a < *b : true : false;
76 }
77 };
78 virtual void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
79 const char * /*pfx*/ = "") const = 0;
80 virtual bool test_width(int &limit) const = 0;
81 virtual number *as_number() { return nullptr; }
82 virtual const number *as_number() const { return nullptr; }
83 virtual string *as_string() { return nullptr; }
84 virtual const string *as_string() const { return nullptr; }
85 virtual vector *as_vector() { return nullptr; }
86 virtual const vector *as_vector() const { return nullptr; }
87 virtual map *as_map() { return nullptr; }
88 virtual const map *as_map() const { return nullptr; }
89 virtual const char *c_str() const { return nullptr; }
90 template <class T>
91 bool is() const {
92 return dynamic_cast<const T *>(this) != nullptr;
93 }
94 template <class T>
95 T &to() {
96 return dynamic_cast<T &>(*this);
97 }
98 template <class T>
99 const T &to() const {
100 return dynamic_cast<const T &>(*this);
101 }
102 virtual std::unique_ptr<obj> copy() && = 0; // Creates a shallow copy of unique_ptr
103 virtual std::unique_ptr<obj> clone() const = 0; // Creates a deep copy of obj
104 static std::unique_ptr<obj> clone_ptr(const std::unique_ptr<obj> &a) {
105 return a ? a->clone() : std::unique_ptr<obj>();
106 }
107 std::string toString() const;
108};
109
110class True : public obj {
111 bool operator<(const obj &a) const {
112 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
113 }
114 bool operator==(const obj &a) const { return dynamic_cast<const True *>(&a) != 0; }
115 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
116 const char * /*pfx*/ = "") const {
117 out << "true";
118 }
119 bool test_width(int &limit) const {
120 limit -= 4;
121 return limit >= 0;
122 }
123 std::unique_ptr<obj> copy() && { return mkuniq<True>(std::move(*this)); }
124 std::unique_ptr<obj> clone() const { return mkuniq<True>(); }
125};
126
127class False : public obj {
128 bool operator<(const obj &a) const {
129 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
130 }
131 bool operator==(const obj &a) const { return dynamic_cast<const False *>(&a) != 0; }
132 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
133 const char * /*pfx*/ = "") const {
134 out << "false";
135 }
136 bool test_width(int &limit) const {
137 limit -= 5;
138 return limit >= 0;
139 }
140 std::unique_ptr<obj> copy() && { return mkuniq<False>(std::move(*this)); }
141 std::unique_ptr<obj> clone() const { return mkuniq<False>(); }
142};
143
144class number : public obj {
145 public:
146 int64_t val;
147 explicit number(int64_t l) : val(l) {}
148 ~number() {}
149 bool operator<(const obj &a) const override {
150 if (auto *b = dynamic_cast<const number *>(&a)) return val < b->val;
151 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
152 }
153 bool operator==(const obj &a) const override {
154 if (auto *b = dynamic_cast<const number *>(&a)) return val == b->val;
155 return false;
156 }
157 bool operator==(int64_t v) const override { return val == v; }
158 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
159 const char * /*pfx*/ = "") const override {
160 out << val;
161 }
162 bool test_width(int &limit) const override {
163 char buf[32];
164 limit -= snprintf(buf, sizeof(buf), "%" PRId64, val);
165 return limit >= 0;
166 }
167 number *as_number() override { return this; }
168 const number *as_number() const override { return this; }
169 std::unique_ptr<obj> copy() && override { return mkuniq<number>(std::move(*this)); }
170 std::unique_ptr<obj> clone() const override { return mkuniq<number>(val); }
171};
172
173class string : public obj, public std::string {
174 public:
175 string() {}
176 string(const string &) = default;
177 string(const std::string &a) : std::string(a) {} // NOLINT(runtime/explicit)
178 string(const char *a) : std::string(a) {} // NOLINT(runtime/explicit)
179 string(string &&) = default;
180 string(std::string &&a) : std::string(a) {} // NOLINT
181 string(int64_t l) : std::string(std::to_string(l)) {} // NOLINT
182 string &operator=(const string &) & = default;
183 string &operator=(string &&) & = default;
184 ~string() {}
185 bool operator<(const obj &a) const override {
186 if (const string *b = dynamic_cast<const string *>(&a))
187 return static_cast<const std::string &>(*this) < static_cast<const std::string &>(*b);
188 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
189 }
190 bool operator==(const obj &a) const override {
191 if (const string *b = dynamic_cast<const string *>(&a))
192 return static_cast<const std::string &>(*this) == static_cast<const std::string &>(*b);
193 return false;
194 }
195 bool operator==(const string &a) const override {
196 return static_cast<const std::string &>(*this) == static_cast<const std::string &>(a);
197 }
198 bool operator==(const char *str) const override {
199 return static_cast<const std::string &>(*this) == str;
200 }
201 bool operator==(const std::string &str) const override {
202 return static_cast<const std::string &>(*this) == str;
203 }
204 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
205 const char * /*pfx*/ = "") const override {
206 out << '"' << *this << '"';
207 }
208 bool test_width(int &limit) const override {
209 limit -= size() + 2;
210 return limit >= 0;
211 }
212 const char *c_str() const override { return std::string::c_str(); }
213 string *as_string() override { return this; }
214 const string *as_string() const override { return this; }
215 std::unique_ptr<obj> copy() && override { return mkuniq<string>(std::move(*this)); }
216 std::unique_ptr<obj> clone() const override { return mkuniq<string>(*this); }
217};
218
219class map; // forward decl
220
221typedef std::vector<std::unique_ptr<obj>> vector_base;
222class vector : public obj, public vector_base {
223 public:
224 vector() {}
225 vector(const vector &) = delete;
226 vector(vector &&) = default;
227 vector(const std::initializer_list<rvalue_reference_wrapper<obj>> &init) {
228 for (auto o : init) push_back(o.get().copy());
229 }
230 vector &operator=(const vector &) & = delete;
231 vector &operator=(vector &&) & = default;
232 ~vector() {}
233 bool operator<(const obj &a) const override {
234 if (const vector *b = dynamic_cast<const vector *>(&a)) {
235 auto p1 = begin(), p2 = b->begin();
236 while (p1 != end() && p2 != b->end()) {
237 if (**p1 < **p2) return true;
238 if (**p1 != **p2) return false;
239 p1++;
240 p2++;
241 }
242 return p2 != b->end();
243 }
244 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
245 }
246 using obj::operator<=;
247 using obj::operator>=;
248 using obj::operator>;
249 bool operator==(const obj &a) const override {
250 if (const vector *b = dynamic_cast<const vector *>(&a)) {
251 auto p1 = begin(), p2 = b->begin();
252 while (p1 != end() && p2 != b->end()) {
253 if (**p1 != **p2) return false;
254 p1++;
255 p2++;
256 }
257 return (p1 == end() && p2 == b->end());
258 }
259 return false;
260 }
261 using obj::operator!=;
262 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
263 const char * /*pfx*/ = "") const override;
264 bool test_width(int &limit) const override {
265 limit -= 2;
266 for (auto &e : *this) {
267 if (e ? !e->test_width(limit) : (limit -= 4) < 0) return false;
268 if ((limit -= 2) < 0) return false;
269 }
270 return true;
271 }
272 using vector_base::push_back;
273 void push_back(decltype(nullptr)) { push_back(std::unique_ptr<obj>()); }
274 void push_back(bool t) {
275 if (t)
276 push_back(mkuniq<True>(True()));
277 else
278 push_back(mkuniq<False>(False()));
279 }
280 void push_back(int64_t n) { push_back(mkuniq<number>(number(n))); }
281 void push_back(int n) { push_back((int64_t)n); }
282 void push_back(unsigned int n) { push_back((int64_t)n); }
283 void push_back(uint64_t n) { push_back((int64_t)n); }
284 void push_back(const char *s) { push_back(mkuniq<string>(string(s))); }
285 void push_back(std::string s) { push_back(mkuniq<string>(string(s))); }
286 void push_back(string s) { push_back(mkuniq<string>(s)); }
287 void push_back(vector &&v) { push_back(mkuniq<vector>(std::move(v))); }
288 void push_back(json::map &&); // NOLINT(whitespace/operators)
289 vector *as_vector() override { return this; }
290 const vector *as_vector() const override { return this; }
291 std::unique_ptr<obj> copy() && override { return mkuniq<vector>(std::move(*this)); }
292 std::unique_ptr<obj> clone() const override {
293 vector *v = new vector();
294 for (auto &e : *this) v->push_back(clone_ptr(e));
295 return std::unique_ptr<vector>(v);
296 }
297};
298
300class map : public obj, public map_base {
301 public:
302 map() {}
303 map(const map &) = default;
304 map(map &&) = default;
305 map(const std::initializer_list<std::pair<std::string, obj &&>> &init) {
306 for (auto &pair : init) (*this)[pair.first] = std::move(pair.second).copy();
307 }
308 map &operator=(const map &) & = default;
309 map &operator=(map &&) & = default;
310 ~map() {
311 for (auto &e : *this) delete e.first;
312 }
313 bool operator<(const obj &a) const override {
314 if (const map *b = dynamic_cast<const map *>(&a)) {
315 auto p1 = begin(), p2 = b->begin();
316 while (p1 != end() && p2 != b->end()) {
317 if (*p1->first < *p2->first) return true;
318 if (*p1->first != *p2->first) return false;
319 if (*p1->second < *p2->second) return true;
320 if (*p1->second != *p2->second) return false;
321 p1++;
322 p2++;
323 }
324 return p2 != b->end();
325 }
326 return std::type_index(typeid(*this)) < std::type_index(typeid(a));
327 }
328 using obj::operator<=;
329 using obj::operator>=;
330 using obj::operator>;
331 bool operator==(const obj &a) const override {
332 if (const map *b = dynamic_cast<const map *>(&a)) {
333 auto p1 = begin(), p2 = b->begin();
334 while (p1 != end() && p2 != b->end()) {
335 if (*p1->first != *p2->first) return false;
336 if (*p1->second != *p2->second) return false;
337 p1++;
338 p2++;
339 }
340 return (p1 == end() && p2 == b->end());
341 }
342 return false;
343 }
344 using obj::operator!=;
345 std::unique_ptr<obj> remove(const char *key) {
346 string tmp(key);
347 auto itr = find(&tmp);
348 if (itr != end()) {
349 std::unique_ptr<obj> val = std::move(itr->second);
350 this->erase(itr);
351 return val;
352 }
353 return std::unique_ptr<obj>();
354 }
355 void print_on(std::ostream &out, int /*indent*/ = 0, int /*width*/ = 80,
356 const char * /*pfx*/ = "") const override;
357 bool test_width(int &limit) const override {
358 limit -= 2;
359 for (auto &e : *this) {
360 if (!e.first->test_width(limit)) return false;
361 if (e.second ? !e.second->test_width(limit) : (limit -= 4) < 0) return false;
362 if ((limit -= 4) < 0) return false;
363 }
364 return true;
365 }
366 using map_base::count;
367 map_base::size_type count(const char *str) const {
368 string tmp(str);
369 return count(&tmp);
370 }
371 map_base::size_type count(std::string &str) const {
372 string tmp(str);
373 return count(&tmp);
374 }
375 map_base::size_type count(int64_t n) const {
376 number tmp(n);
377 return count(&tmp);
378 }
379 // using map_base::operator[];
380 obj *operator[](const std::unique_ptr<obj> &i) const {
381 auto rv = find(i.get());
382 if (rv != end()) return rv->second.get();
383 return 0;
384 }
385 obj *operator[](const char *str) const {
386 string tmp(str);
387 auto rv = find(&tmp);
388 if (rv != end()) return rv->second.get();
389 return 0;
390 }
391 obj *operator[](const std::string &str) const {
392 string tmp(str);
393 auto rv = find(&tmp);
394 if (rv != end()) return rv->second.get();
395 return 0;
396 }
397 obj *operator[](int64_t n) const {
398 number tmp(n);
399 auto rv = find(&tmp);
400 if (rv != end()) return rv->second.get();
401 return 0;
402 }
403
404 private:
405 class element_ref {
406 map &self;
407 std::unique_ptr<obj> key;
408 map_base::iterator iter;
409
410 public:
411 element_ref(map &s, const char *k) : self(s) {
412 string tmp(k);
413 iter = self.find(&tmp);
414 if (iter == self.end()) key.reset(new string(std::move(tmp)));
415 }
416 element_ref(map &s, int64_t k) : self(s) {
417 number tmp(k);
418 iter = self.find(&tmp);
419 if (iter == self.end()) key.reset(new number(std::move(tmp)));
420 }
421 element_ref(map &s, std::unique_ptr<obj> &&k) : self(s) {
422 iter = self.find(k.get());
423 if (iter == self.end()) key = std::move(k);
424 }
425 void operator=(decltype(nullptr)) {
426 if (key) {
427 iter = self.emplace(key.release(), std::unique_ptr<obj>()).first;
428 } else {
429 assert(iter != self.end());
430 iter->second.reset();
431 }
432 }
433 bool operator=(bool t) {
434 if (key) {
435 iter = self.emplace(key.release(),
436 std::unique_ptr<obj>(t ? static_cast<obj *>(new True())
437 : static_cast<obj *>(new False())))
438 .first;
439 } else {
440 assert(iter != self.end());
441 iter->second.reset(t ? static_cast<obj *>(new True())
442 : static_cast<obj *>(new False()));
443 }
444 return t;
445 }
446 bool operator=(void *); // not defined to avoid converting pointers to bool
447 bool operator==(string &str) {
448 if (key) return false;
449 assert(iter != self.end());
450 return *iter->second == str;
451 }
452 bool operator!=(string &str) { return !(*this == str); }
453 bool operator==(const std::string &str) {
454 if (key) return false;
455 assert(iter != self.end());
456 return *iter->second == str;
457 }
458 bool operator!=(const std::string &str) { return !(*this == str); }
459 bool operator==(int64_t v) {
460 if (key) return false;
461 assert(iter != self.end());
462 return *iter->second == v;
463 }
464 bool operator!=(int64_t v) { return !(*this == v); }
465 const char *operator=(const char *v) {
466 if (key) {
467 iter = self.emplace(key.release(), std::unique_ptr<obj>(new string(v))).first;
468 } else {
469 assert(iter != self.end());
470 iter->second.reset(new string(v));
471 }
472 return v;
473 }
474 const std::string &operator=(const std::string &v) {
475 if (key) {
476 iter = self.emplace(key.release(), std::unique_ptr<obj>(new string(v))).first;
477 } else {
478 assert(iter != self.end());
479 iter->second.reset(new string(v));
480 }
481 return v;
482 }
483 int64_t operator=(int64_t v) {
484 if (key) {
485 iter = self.emplace(key.release(), std::unique_ptr<obj>(new number(v))).first;
486 } else {
487 assert(iter != self.end());
488 iter->second.reset(new number(v));
489 }
490 return v;
491 }
492 int operator=(int v) { return static_cast<int>(*this = static_cast<int64_t>(v)); }
493 unsigned int operator=(unsigned int v) { return (unsigned int)(*this = (int64_t)v); }
494#if defined(__clang__) && defined(__APPLE__)
495 // Clang ang gcc on Mac OS can't agree whether size_t overloads uint64_t or unsigned long
496 // or the overload is not defined!
497 size_t operator=(size_t v) { return (size_t)(*this = (int64_t)v); }
498#endif
499 uint64_t operator=(uint64_t v) { return (uint64_t)(*this = (int64_t)v); }
500 vector &operator=(vector &&v) {
501 if (key) {
502 iter = self.emplace(key.release(), mkuniq<vector>(std::move(v))).first;
503 } else {
504 assert(iter != self.end());
505 iter->second = mkuniq<vector>(std::move(v));
506 }
507 return dynamic_cast<vector &>(*iter->second);
508 }
509 map &operator=(map &&v) {
510 if (key) {
511 iter = self.emplace(key.release(), mkuniq<map>(std::move(v))).first;
512 } else {
513 assert(iter != self.end());
514 iter->second = mkuniq<map>(std::move(v));
515 }
516 return dynamic_cast<map &>(*iter->second);
517 }
518 const std::unique_ptr<obj> &operator=(std::unique_ptr<obj> &&v) {
519 if (key) {
520 iter = self.emplace(key.release(), std::move(v)).first;
521 } else {
522 assert(iter != self.end());
523 iter->second = std::move(v);
524 }
525 return iter->second;
526 }
527 obj &operator*() {
528 assert(!key && iter != self.end());
529 return *iter->second;
530 }
531 explicit operator bool() const { return !key; }
532 obj *get() const { return key ? 0 : iter->second.get(); }
533 obj *operator->() const { return key ? 0 : iter->second.get(); }
534 operator vector &() {
535 if (key) iter = self.emplace(key.release(), mkuniq<vector>()).first;
536 return dynamic_cast<vector &>(*iter->second);
537 }
538 operator map &() {
539 if (key) iter = self.emplace(key.release(), mkuniq<map>()).first;
540 return dynamic_cast<map &>(*iter->second);
541 }
542 element_ref operator[](const char *str) {
543 if (key) iter = self.emplace(key.release(), mkuniq<map>()).first;
544 map *m = dynamic_cast<map *>(iter->second.get());
545 if (!m) throw std::runtime_error("lookup in non-map json object");
546 return element_ref(*m, str);
547 }
548 element_ref operator[](const std::string &str) {
549 if (key) iter = self.emplace(key.release(), mkuniq<map>()).first;
550 map *m = dynamic_cast<map *>(iter->second.get());
551 if (!m) throw std::runtime_error("lookup in non-map json object");
552 return element_ref(*m, str.c_str());
553 }
554 element_ref operator[](int64_t n) {
555 if (key) iter = self.emplace(key.release(), mkuniq<map>()).first;
556 map *m = dynamic_cast<map *>(iter->second.get());
557 if (!m) throw std::runtime_error("lookup in non-map json object");
558 return element_ref(*m, n);
559 }
560 element_ref operator[](std::unique_ptr<obj> &&i) {
561 if (key) iter = self.emplace(key.release(), mkuniq<map>()).first;
562 map *m = dynamic_cast<map *>(iter->second.get());
563 if (!m) throw std::runtime_error("lookup in non-map json object");
564 return element_ref(*m, std::move(i));
565 }
566 template <class T>
567 void push_back(T &&v) {
568 vector &vec = *this;
569 vec.push_back(std::forward<T>(v));
570 }
571 template <class T>
572 bool is() const {
573 return !key && dynamic_cast<T *>(iter->second.get()) != nullptr;
574 }
575 template <class T>
576 T &to() {
577 if (key) iter = self.emplace(key.release(), mkuniq<T>()).first;
578 return dynamic_cast<T &>(*iter->second);
579 }
580 };
581 friend std::ostream &operator<<(std::ostream &out, const element_ref &el);
582
583 public:
584 element_ref operator[](const char *str) { return element_ref(*this, str); }
585 element_ref operator[](const std::string &str) { return element_ref(*this, str.c_str()); }
586 element_ref operator[](int64_t n) { return element_ref(*this, n); }
587 element_ref operator[](std::unique_ptr<obj> &&i) { return element_ref(*this, std::move(i)); }
588 using map_base::erase;
589 map_base::size_type erase(const char *str) {
590 string tmp(str);
591 return map_base::erase(&tmp);
592 }
593 map_base::size_type erase(int64_t n) {
594 number tmp(n);
595 return map_base::erase(&tmp);
596 }
597 map *as_map() override { return this; }
598 const map *as_map() const override { return this; }
599 std::unique_ptr<obj> copy() && override { return mkuniq<map>(std::move(*this)); }
600 std::unique_ptr<obj> clone() const override {
601 map *m = new map();
602 for (auto &e : *this)
603 m->emplace(e.first ? e.first->clone().release() : nullptr, clone_ptr(e.second));
604 return std::unique_ptr<map>(m);
605 }
606
611 map &merge(const map &a);
612};
613
614inline void vector::push_back(map &&m) { emplace_back(mkuniq<map>(std::move(m))); }
615
616std::istream &operator>>(std::istream &in, std::unique_ptr<obj> &json);
617inline std::istream &operator>>(std::istream &in, obj *&json) {
618 std::unique_ptr<obj> p;
619 in >> p;
620 if (in) json = p.release();
621 return in;
622}
623
624inline std::ostream &operator<<(std::ostream &out, const obj *json) {
625 json->print_on(out);
626 return out;
627}
628inline std::ostream &operator<<(std::ostream &out, const std::unique_ptr<obj> &json) {
629 return out << json.get();
630}
631inline std::ostream &operator<<(std::ostream &out, const map::element_ref &el) {
632 el->print_on(out);
633 return out;
634}
635
636} // end namespace json
637
638extern void dump(const json::obj *);
639extern void dump(const json::obj &);
640
641#endif /* BACKENDS_TOFINO_BF_ASM_JSON_H_ */
Definition ordered_map.h:32
Definition backends/tofino/bf-asm/json.h:127
Definition backends/tofino/bf-asm/json.h:110
Definition backends/tofino/bf-asm/json.h:300
map & merge(const map &a)
Definition backends/tofino/bf-asm/json.cpp:229
Definition backends/tofino/bf-asm/json.h:144
Definition backends/tofino/bf-asm/json.h:52
Definition backends/tofino/bf-asm/json.h:173
Definition backends/tofino/bf-asm/json.h:222
Definition rvalue_reference_wrapper.h:22
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition bson.cpp:69
Definition backends/tofino/bf-asm/json.h:72