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#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, Number, 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::Number), value(v) {} // NOLINT
61 JsonValue(int v) : tag(Kind::Number), value(v) {} // NOLINT
62 JsonValue(long v) : tag(Kind::Number), value(v) {} // NOLINT
63 JsonValue(long long v); // NOLINT
64 JsonValue(unsigned v) : tag(Kind::Number), value(v) {} // NOLINT
65 JsonValue(unsigned long v) : tag(Kind::Number), value(v) {} // NOLINT
66 JsonValue(unsigned long long v); // NOLINT
67 JsonValue(double v) : tag(Kind::Number), value(v) {} // NOLINT
68 JsonValue(float v) : tag(Kind::Number), value(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 // is_integral is true for bool
78 template <typename T, typename std::enable_if_t<std::is_integral_v<T>, int> = 0>
79 bool operator==(const T &v) const {
80 return (tag == Kind::Number) && (v == value);
81 }
82 bool operator==(const double &v) const;
83 bool operator==(const float &v) const;
84 bool operator==(const cstring &s) const;
85 // FIXME: replace these two methods with std::string view, cannot do now as
86 // std::string is implicitly convertible to cstring
87 bool operator==(const char *s) const;
88 bool operator==(const std::string &s) const;
89 bool operator==(const JsonValue &other) const;
90
91 bool isNumber() const { return tag == Kind::Number; }
92 bool isBool() const { return tag == Kind::True || tag == Kind::False; }
93 bool isString() const { return tag == Kind::String; }
94 bool isNull() const { return tag == Kind::Null; }
95
96 bool getBool() const;
97 cstring getString() const;
98 big_int getValue() const;
99 int getInt() const;
100
101 static JsonValue *null;
102
103 private:
104 JsonValue(Kind kind) : tag(kind) { // NOLINT
105 if (kind == Kind::String || kind == Kind::Number)
106 throw std::logic_error("Incorrect constructor called");
107 }
108
109 const Kind tag;
110 const big_int value = 0;
111 const cstring str = cstring::empty;
112
113 DECLARE_TYPEINFO(JsonValue, IJson);
114};
115
116class JsonArray final : public IJson, public std::vector<IJson *> {
117 friend class Test::TestJson;
118
119 public:
120 void serialize(std::ostream &out) const override;
121 JsonArray *clone() const { return new JsonArray(*this); }
122 JsonArray *append(IJson *value);
123 JsonArray *append(big_int v) {
124 append(new JsonValue(v));
125 return this;
126 }
127 template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
128 JsonArray *append(T v) {
129 append(new JsonValue(v));
130 return this;
131 }
132 JsonArray *append(double v) {
133 append(new JsonValue(v));
134 return this;
135 }
136 JsonArray *append(float v) {
137 append(new JsonValue(v));
138 return this;
139 }
140 JsonArray *append(cstring s) {
141 append(new JsonValue(s));
142 return this;
143 }
144 // FIXME: replace these two methods with std::string view, cannot do now as
145 // std::string is implicitly convertible to cstring
146 JsonArray *append(const char *s) {
147 append(new JsonValue(s));
148 return this;
149 }
150 JsonArray *append(const std::string &s) {
151 append(new JsonValue(s));
152 return this;
153 }
154 JsonArray *concatenate(const Util::JsonArray *other) {
155 for (auto v : *other) append(v);
156 return this;
157 }
158 JsonArray(std::initializer_list<IJson *> data) : std::vector<IJson *>(data) {} // NOLINT
159 JsonArray() = default;
160 JsonArray(std::vector<IJson *> &data) : std::vector<IJson *>(data) {} // NOLINT
161
162 DECLARE_TYPEINFO(JsonArray, IJson);
163};
164
165class JsonObject final : public IJson, public string_map<IJson *> {
166 friend class Test::TestJson;
167
168 using base = string_map<IJson *>;
169
170 public:
171 JsonObject() = default;
172 void serialize(std::ostream &out) const override;
173 JsonObject *emplace_non_null(cstring label, IJson *value);
174
175 JsonObject *emplace(cstring label, IJson *value);
176 JsonObject *emplace(std::string_view label, IJson *value);
177
178 template <class T, class String>
179 auto emplace(String label,
180 T &&s) -> std::enable_if_t<!std::is_convertible_v<T, IJson *>, JsonObject *> {
181 emplace(label, new JsonValue(std::forward<T>(s)));
182 return this;
183 }
184
185 IJson *get(cstring label) const { return ::P4::get(*this, label); }
186 IJson *get(std::string_view label) const { return ::P4::get(*this, label); }
187 template <class T, class S>
188 T *getAs(S label) const {
189 return get(label)->template to<T>();
190 }
191
192 DECLARE_TYPEINFO(JsonObject, IJson);
193};
194
195} // namespace P4::Util
196
197#endif /* LIB_JSON_H_ */
Definition castable.h:36
Definition json.h:41
Definition json.h:116
Definition json.h:51
Definition cstring.h:85
Definition json.h:35
T * to() noexcept
Definition rtti.h:226