P4C
The P4 Compiler
Loading...
Searching...
No Matches
json.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef LIB_JSON_H_
18#define LIB_JSON_H_
19
20#include <iostream>
21#include <stdexcept>
22#include <type_traits>
23#include <vector>
24
25#ifdef P4C_GTEST_ENABLED
26#include "gtest/gtest_prod.h"
27#endif
28#include "lib/big_int.h"
29#include "lib/castable.h"
30#include "lib/cstring.h"
31#include "lib/map.h"
32#include "lib/string_map.h"
33
34namespace P4::Test {
35class TestJson;
36}
37
38namespace P4::Util {
39
40class IJson : public ICastable {
41 public:
42 virtual ~IJson() {}
43 virtual void serialize(std::ostream &out) const = 0;
44 cstring toString() const;
45 void dump() const;
46
47 DECLARE_TYPEINFO(IJson);
48};
49
50class JsonValue final : public IJson {
51#ifdef P4C_GTEST_ENABLED
52 FRIEND_TEST(Util, Json);
53#endif
54
55 public:
56 enum Kind { String, Number, True, False, Null };
57 JsonValue() : tag(Kind::Null) {}
58 JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT
59 JsonValue(big_int v) : tag(Kind::Number), value(v) {} // NOLINT
60 JsonValue(int v) : tag(Kind::Number), value(v) {} // NOLINT
61 JsonValue(long v) : tag(Kind::Number), value(v) {} // NOLINT
62 JsonValue(long long v); // NOLINT
63 JsonValue(unsigned v) : tag(Kind::Number), value(v) {} // NOLINT
64 JsonValue(unsigned long v) : tag(Kind::Number), value(v) {} // NOLINT
65 JsonValue(unsigned long long v); // NOLINT
66 JsonValue(double v) : tag(Kind::Number), value(v) {} // NOLINT
67 JsonValue(float v) : tag(Kind::Number), value(v) {} // NOLINT
68 JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT
69 // FIXME: replace these two ctors with std::string view, cannot do now as
70 // std::string is implicitly convertible to cstring
71 JsonValue(const char *s) : tag(Kind::String), str(s) {} // NOLINT
72 JsonValue(const std::string &s) : tag(Kind::String), str(s) {} // NOLINT
73 void serialize(std::ostream &out) const override;
74
75 bool operator==(const big_int &v) const;
76 // is_integral is true for bool
77 template <typename T, typename std::enable_if_t<std::is_integral_v<T>, int> = 0>
78 bool operator==(const T &v) const {
79 return (tag == Kind::Number) && (v == value);
80 }
81 bool operator==(const double &v) const;
82 bool operator==(const float &v) const;
83 bool operator==(const cstring &s) const;
84 // FIXME: replace these two methods with std::string view, cannot do now as
85 // std::string is implicitly convertible to cstring
86 bool operator==(const char *s) const;
87 bool operator==(const std::string &s) const;
88 bool operator==(const JsonValue &other) const;
89
90 bool isNumber() const { return tag == Kind::Number; }
91 bool isBool() const { return tag == Kind::True || tag == Kind::False; }
92 bool isString() const { return tag == Kind::String; }
93 bool isNull() const { return tag == Kind::Null; }
94
95 bool getBool() const;
96 cstring getString() const;
97 big_int getValue() const;
98 int getInt() const;
99
100 static JsonValue *null;
101
102 private:
103 JsonValue(Kind kind) : tag(kind) { // NOLINT
104 if (kind == Kind::String || kind == Kind::Number)
105 throw std::logic_error("Incorrect constructor called");
106 }
107
108 const Kind tag;
109 const big_int value = 0;
110 const cstring str = cstring::empty;
111
112 DECLARE_TYPEINFO(JsonValue, IJson);
113};
114
115class JsonArray final : public IJson, public std::vector<IJson *> {
116 friend class Test::TestJson;
117
118 public:
119 void serialize(std::ostream &out) const override;
120 JsonArray *clone() const { return new JsonArray(*this); }
121 JsonArray *append(IJson *value);
122 JsonArray *append(big_int v) {
123 append(new JsonValue(v));
124 return this;
125 }
126 template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
127 JsonArray *append(T v) {
128 append(new JsonValue(v));
129 return this;
130 }
131 JsonArray *append(double v) {
132 append(new JsonValue(v));
133 return this;
134 }
135 JsonArray *append(float v) {
136 append(new JsonValue(v));
137 return this;
138 }
139 JsonArray *append(cstring s) {
140 append(new JsonValue(s));
141 return this;
142 }
143 // FIXME: replace these two methods with std::string view, cannot do now as
144 // std::string is implicitly convertible to cstring
145 JsonArray *append(const char *s) {
146 append(new JsonValue(s));
147 return this;
148 }
149 JsonArray *append(const std::string &s) {
150 append(new JsonValue(s));
151 return this;
152 }
153 JsonArray *concatenate(const Util::JsonArray *other) {
154 for (auto v : *other) append(v);
155 return this;
156 }
157 JsonArray(std::initializer_list<IJson *> data) : std::vector<IJson *>(data) {} // NOLINT
158 JsonArray() = default;
159 JsonArray(std::vector<IJson *> &data) : std::vector<IJson *>(data) {} // NOLINT
160
161 DECLARE_TYPEINFO(JsonArray, IJson);
162};
163
164class JsonObject final : public IJson, public string_map<IJson *> {
165 friend class Test::TestJson;
166
168
169 public:
170 JsonObject() = default;
171 void serialize(std::ostream &out) const override;
172 JsonObject *emplace_non_null(cstring label, IJson *value);
173
174 JsonObject *emplace(cstring label, IJson *value);
175 JsonObject *emplace(std::string_view label, IJson *value);
176
177 template <class T, class String>
178 auto emplace(String label,
179 T &&s) -> std::enable_if_t<!std::is_convertible_v<T, IJson *>, JsonObject *> {
180 emplace(label, new JsonValue(std::forward<T>(s)));
181 return this;
182 }
183
184 IJson *get(cstring label) const { return ::P4::get(*this, label); }
185 IJson *get(std::string_view label) const { return ::P4::get(*this, label); }
186 template <class T, class S>
187 T *getAs(S label) const {
188 return get(label)->template to<T>();
189 }
190
191 DECLARE_TYPEINFO(JsonObject, IJson);
192};
193
194} // namespace P4::Util
195
196#endif /* LIB_JSON_H_ */
Definition castable.h:36
Definition json.h:40
Definition json.h:115
Definition json.h:164
Definition json.h:50
Definition cstring.h:85
Definition string_map.h:41
T * to() noexcept
Definition rtti.h:226