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