univalue.h raw
1 // Copyright 2014 BitPay Inc.
2 // Copyright 2015 Bitcoin Core Developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://opensource.org/licenses/mit-license.php.
5
6 #ifndef BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
7 #define BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
8
9 #include <charconv>
10 #include <cstddef>
11 #include <cstdint>
12 #include <map>
13 #include <stdexcept>
14 #include <string>
15 #include <string_view>
16 #include <system_error>
17 #include <type_traits>
18 #include <utility>
19 #include <vector>
20
21 // NOLINTNEXTLINE(misc-no-recursion)
22 class UniValue {
23 public:
24 enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
25
26 class type_error : public std::runtime_error
27 {
28 using std::runtime_error::runtime_error;
29 };
30
31 UniValue() { typ = VNULL; }
32 UniValue(UniValue::VType type, std::string str = {}) : typ{type}, val{std::move(str)} {}
33 template <typename Ref, typename T = std::remove_cv_t<std::remove_reference_t<Ref>>,
34 std::enable_if_t<std::is_floating_point_v<T> || // setFloat
35 std::is_same_v<bool, T> || // setBool
36 std::is_signed_v<T> || std::is_unsigned_v<T> || // setInt
37 std::is_constructible_v<std::string, T>, // setStr
38 bool> = true>
39 UniValue(Ref&& val)
40 {
41 if constexpr (std::is_floating_point_v<T>) {
42 setFloat(val);
43 } else if constexpr (std::is_same_v<bool, T>) {
44 setBool(val);
45 } else if constexpr (std::is_signed_v<T>) {
46 setInt(int64_t{val});
47 } else if constexpr (std::is_unsigned_v<T>) {
48 setInt(uint64_t{val});
49 } else {
50 setStr(std::string{std::forward<Ref>(val)});
51 }
52 }
53
54 void clear();
55
56 void setNull();
57 void setBool(bool val);
58 void setNumStr(std::string str);
59 void setInt(uint64_t val);
60 void setInt(int64_t val);
61 void setInt(int val_) { return setInt(int64_t{val_}); }
62 void setFloat(double val);
63 void setStr(std::string str);
64 void setArray();
65 void setObject();
66
67 enum VType getType() const { return typ; }
68 const std::string& getValStr() const { return val; }
69 bool empty() const { return (values.size() == 0); }
70
71 size_t size() const { return values.size(); }
72
73 void reserve(size_t new_cap);
74
75 void getObjMap(std::map<std::string,UniValue>& kv) const;
76 bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
77 const UniValue& operator[](const std::string& key) const;
78 const UniValue& operator[](size_t index) const;
79 bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
80
81 bool isNull() const { return (typ == VNULL); }
82 bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
83 bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
84 bool isBool() const { return (typ == VBOOL); }
85 bool isStr() const { return (typ == VSTR); }
86 bool isNum() const { return (typ == VNUM); }
87 bool isArray() const { return (typ == VARR); }
88 bool isObject() const { return (typ == VOBJ); }
89
90 void push_back(UniValue val);
91 void push_backV(const std::vector<UniValue>& vec);
92 template <class It>
93 void push_backV(It first, It last);
94
95 void pushKVEnd(std::string key, UniValue val);
96 void pushKV(std::string key, UniValue val);
97 void pushKVs(UniValue obj);
98
99 std::string write(unsigned int prettyIndent = 0,
100 unsigned int indentLevel = 0) const;
101
102 bool read(std::string_view raw);
103
104 private:
105 UniValue::VType typ;
106 std::string val; // numbers are stored as C++ strings
107 std::vector<std::string> keys;
108 std::vector<UniValue> values;
109
110 void checkType(const VType& expected) const;
111 bool findKey(const std::string& key, size_t& retIdx) const;
112 void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
113 void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
114
115 public:
116 // Strict type-specific getters, these throw std::runtime_error if the
117 // value is of unexpected type
118 const std::vector<std::string>& getKeys() const;
119 const std::vector<UniValue>& getValues() const;
120 template <typename Int>
121 Int getInt() const;
122 bool get_bool() const;
123 const std::string& get_str() const;
124 double get_real() const;
125 const UniValue& get_obj() const;
126 const UniValue& get_array() const;
127
128 enum VType type() const { return getType(); }
129 const UniValue& find_value(std::string_view key) const;
130 };
131
132 template <class It>
133 void UniValue::push_backV(It first, It last)
134 {
135 checkType(VARR);
136 values.insert(values.end(), first, last);
137 }
138
139 template <typename Int>
140 Int UniValue::getInt() const
141 {
142 static_assert(std::is_integral_v<Int>);
143 checkType(VNUM);
144 Int result;
145 const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
146 if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
147 throw std::runtime_error("JSON integer out of range");
148 }
149 return result;
150 }
151
152 enum jtokentype {
153 JTOK_ERR = -1,
154 JTOK_NONE = 0, // eof
155 JTOK_OBJ_OPEN,
156 JTOK_OBJ_CLOSE,
157 JTOK_ARR_OPEN,
158 JTOK_ARR_CLOSE,
159 JTOK_COLON,
160 JTOK_COMMA,
161 JTOK_KW_NULL,
162 JTOK_KW_TRUE,
163 JTOK_KW_FALSE,
164 JTOK_NUMBER,
165 JTOK_STRING,
166 };
167
168 extern enum jtokentype getJsonToken(std::string& tokenVal,
169 unsigned int& consumed, const char *raw, const char *end);
170 extern const char *uvTypeName(UniValue::VType t);
171
172 static inline bool jsonTokenIsValue(enum jtokentype jtt)
173 {
174 switch (jtt) {
175 case JTOK_KW_NULL:
176 case JTOK_KW_TRUE:
177 case JTOK_KW_FALSE:
178 case JTOK_NUMBER:
179 case JTOK_STRING:
180 return true;
181
182 default:
183 return false;
184 }
185
186 // not reached
187 }
188
189 static inline bool json_isspace(int ch)
190 {
191 switch (ch) {
192 case 0x20:
193 case 0x09:
194 case 0x0a:
195 case 0x0d:
196 return true;
197
198 default:
199 return false;
200 }
201
202 // not reached
203 }
204
205 extern const UniValue NullUniValue;
206
207 #endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
208