P4C
The P4 Compiler
Loading...
Searching...
No Matches
lib/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#include "config.h"
26#ifdef P4C_GTEST_ENABLED
27#include "gtest/gtest_prod.h"
28#endif
29#include "lib/big_int.h"
30#include "lib/castable.h"
31#include "lib/cstring.h"
32#include "lib/map.h"
33#include "lib/string_map.h"
34
35namespace P4::Test {
36class TestJson;
37}
38
39namespace P4::Util {
40
41class IJson : public ICastable {
42 public:
43 virtual ~IJson() {}
44 virtual void serialize(std::ostream &out) const = 0;
45 cstring toString() const;
46 void dump() const;
47
48 DECLARE_TYPEINFO(IJson);
49};
50
51class JsonValue final : public IJson {
52#ifdef P4C_GTEST_ENABLED
53 FRIEND_TEST(Util, Json);
54#endif
55
56 public:
57 enum Kind { String, Integer, Float, True, False, Null };
58 JsonValue() : tag(Kind::Null) {}
59 JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT
60 JsonValue(big_int v) : tag(Kind::Integer), intValue(v) {} // NOLINT
61 JsonValue(int v) : tag(Kind::Integer), intValue(v) {} // NOLINT
62 JsonValue(long v) : tag(Kind::Integer), intValue(v) {} // NOLINT
63 JsonValue(long long v); // NOLINT
64 JsonValue(unsigned v) : tag(Kind::Integer), intValue(v) {} // NOLINT
65 JsonValue(unsigned long v) : tag(Kind::Integer), intValue(v) {} // NOLINT
66 JsonValue(unsigned long long v); // NOLINT
67 JsonValue(double v) : tag(Kind::Float), floatValue(v) {} // NOLINT
68 JsonValue(float v) : tag(Kind::Float), floatValue(v) {} // NOLINT
69 JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT
70 // FIXME: replace these two ctors with std::string view, cannot do now as
71 // std::string is implicitly convertible to cstring
72 JsonValue(const char *s) : tag(Kind::String), str(s) {} // NOLINT
73 JsonValue(const std::string &s) : tag(Kind::String), str(s) {} // NOLINT
74 void serialize(std::ostream &out) const override;
75
76 bool operator==(const big_int &v) const;
77 // Integer types
78 template <typename T, typename std::enable_if_t<std::is_integral_v<T>, int> = 0>
79 bool operator==(const T &v) const {
80 if (tag == Kind::Integer) return intValue == v;
81 return false;
82 }
83
84 template <typename T, typename std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
85 bool operator==(const T &v) const {
86 if (tag == Kind::Integer) return static_cast<double>(intValue) == static_cast<double>(v);
87 if (tag == Kind::Float) return floatValue == static_cast<double>(v);
88 return false;
89 }
90 bool operator==(const double &v) const;
91 bool operator==(const float &v) const;
92 bool operator==(const cstring &s) const;
93 // FIXME: replace these two methods with std::string view, cannot do now as
94 // std::string is implicitly convertible to cstring
95 bool operator==(const char *s) const;
96 bool operator==(const std::string &s) const;
97 bool operator==(const JsonValue &other) const;
98
99 bool isNumber() const { return tag == Kind::Integer || tag == Kind::Float; }
100 bool isBool() const { return tag == Kind::True || tag == Kind::False; }
101 bool isString() const { return tag == Kind::String; }
102 bool isNull() const { return tag == Kind::Null; }
103 bool isInteger() const { return tag == Kind::Integer; }
104 bool isFloat() const { return tag == Kind::Float; }
105
106 bool getBool() const;
107 cstring getString() const;
108 big_int getIntValue() const;
109 double getFloatValue() const;
110 int getInt() const;
111
112 static JsonValue *null;
113
114 private:
115 JsonValue(Kind kind) : tag(kind) {
116 if (kind == Kind::String || kind == Kind::Integer || kind == Kind::Float)
117 throw std::logic_error("Incorrect constructor called");
118 }
119
120 const Kind tag;
121 const big_int intValue = 0;
122 const double floatValue = 0.0;
123 const cstring str = cstring::empty;
124
125 DECLARE_TYPEINFO(JsonValue, IJson);
126};
127
128class JsonArray final : public IJson, public std::vector<IJson *> {
129 friend class Test::TestJson;
130
131 public:
132 void serialize(std::ostream &out) const override;
133 JsonArray *clone() const { return new JsonArray(*this); }
134 JsonArray *append(IJson *value);
135 JsonArray *append(big_int v) {
136 append(new JsonValue(v));
137 return this;
138 }
139 template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
140 JsonArray *append(T v) {
141 append(new JsonValue(v));
142 return this;
143 }
144 JsonArray *append(double v) {
145 append(new JsonValue(v));
146 return this;
147 }
148 JsonArray *append(float v) {
149 append(new JsonValue(v));
150 return this;
151 }
152 JsonArray *append(cstring s) {
153 append(new JsonValue(s));
154 return this;
155 }
156 // FIXME: replace these two methods with std::string view, cannot do now as
157 // std::string is implicitly convertible to cstring
158 JsonArray *append(const char *s) {
159 append(new JsonValue(s));
160 return this;
161 }
162 JsonArray *append(const std::string &s) {
163 append(new JsonValue(s));
164 return this;
165 }
166 JsonArray *concatenate(const Util::JsonArray *other) {
167 for (auto v : *other) append(v);
168 return this;
169 }
170 JsonArray(std::initializer_list<IJson *> data) : std::vector<IJson *>(data) {} // NOLINT
171 JsonArray() = default;
172 JsonArray(std::vector<IJson *> &data) : std::vector<IJson *>(data) {} // NOLINT
173
174 DECLARE_TYPEINFO(JsonArray, IJson);
175};
176
177class JsonObject final : public IJson, public string_map<IJson *> {
178 friend class Test::TestJson;
179
180 using base = string_map<IJson *>;
181
182 public:
183 JsonObject() = default;
184 void serialize(std::ostream &out) const override;
185 JsonObject *emplace_non_null(cstring label, IJson *value);
186
187 JsonObject *emplace(cstring label, IJson *value);
188 JsonObject *emplace(std::string_view label, IJson *value);
189
190 template <class T, class String>
191 auto emplace(String label,
192 T &&s) -> std::enable_if_t<!std::is_convertible_v<T, IJson *>, JsonObject *> {
193 emplace(label, new JsonValue(std::forward<T>(s)));
194 return this;
195 }
196
197 IJson *get(cstring label) const { return ::P4::get(*this, label); }
198 IJson *get(std::string_view label) const { return ::P4::get(*this, label); }
199 template <class T, class S>
200 T *getAs(S label) const {
201 return get(label)->template to<T>();
202 }
203
204 DECLARE_TYPEINFO(JsonObject, IJson);
205};
206
207} // namespace P4::Util
208
209#endif /* LIB_JSON_H_ */
Definition castable.h:36
Definition lib/json.h:41
Definition lib/json.h:128
Definition lib/json.h:51
Definition cstring.h:85
Definition lib/json.h:35
T * to() noexcept
Definition rtti.h:226