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 http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef __UNIVALUE_H__
7 #define __UNIVALUE_H__
8 
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <string>
13 #include <vector>
14 #include <map>
15 #include <cassert>
16 
17 #include <sstream>        // .get_int64()
18 
19 class UniValue {
20 public:
21     enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
22 
UniValue()23     UniValue() { typ = VNULL; }
24     UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
25         typ = initialType;
26         val = initialStr;
27     }
UniValue(uint64_t val_)28     UniValue(uint64_t val_) {
29         setInt(val_);
30     }
UniValue(int64_t val_)31     UniValue(int64_t val_) {
32         setInt(val_);
33     }
UniValue(bool val_)34     UniValue(bool val_) {
35         setBool(val_);
36     }
UniValue(int val_)37     UniValue(int val_) {
38         setInt(val_);
39     }
UniValue(double val_)40     UniValue(double val_) {
41         setFloat(val_);
42     }
UniValue(const std::string & val_)43     UniValue(const std::string& val_) {
44         setStr(val_);
45     }
UniValue(const char * val_)46     UniValue(const char *val_) {
47         std::string s(val_);
48         setStr(s);
49     }
~UniValue()50     ~UniValue() {}
51 
52     void clear();
53 
54     bool setNull();
55     bool setBool(bool val);
56     bool setNumStr(const std::string& val);
57     bool setInt(uint64_t val);
58     bool setInt(int64_t val);
setInt(int val_)59     bool setInt(int val_) { return setInt((int64_t)val_); }
60     bool setFloat(double val);
61     bool setStr(const std::string& val);
62     bool setArray();
63     bool setObject();
64 
getType()65     enum VType getType() const { return typ; }
getValStr()66     const std::string& getValStr() const { return val; }
empty()67     bool empty() const { return (values.size() == 0); }
68 
size()69     size_t size() const { return values.size(); }
70 
getBool()71     bool getBool() const { return isTrue(); }
72     void getObjMap(std::map<std::string,UniValue>& kv) const;
73     bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
74     const UniValue& operator[](const std::string& key) const;
75     const UniValue& operator[](size_t index) const;
exists(const std::string & key)76     bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
77 
isNull()78     bool isNull() const { return (typ == VNULL); }
isTrue()79     bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
isFalse()80     bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
isBool()81     bool isBool() const { return (typ == VBOOL); }
isStr()82     bool isStr() const { return (typ == VSTR); }
isNum()83     bool isNum() const { return (typ == VNUM); }
isArray()84     bool isArray() const { return (typ == VARR); }
isObject()85     bool isObject() const { return (typ == VOBJ); }
86 
87     bool push_back(const UniValue& val);
push_back(const std::string & val_)88     bool push_back(const std::string& val_) {
89         UniValue tmpVal(VSTR, val_);
90         return push_back(tmpVal);
91     }
push_back(const char * val_)92     bool push_back(const char *val_) {
93         std::string s(val_);
94         return push_back(s);
95     }
push_back(uint64_t val_)96     bool push_back(uint64_t val_) {
97         UniValue tmpVal(val_);
98         return push_back(tmpVal);
99     }
push_back(int64_t val_)100     bool push_back(int64_t val_) {
101         UniValue tmpVal(val_);
102         return push_back(tmpVal);
103     }
push_back(int val_)104     bool push_back(int val_) {
105         UniValue tmpVal(val_);
106         return push_back(tmpVal);
107     }
push_back(double val_)108     bool push_back(double val_) {
109         UniValue tmpVal(val_);
110         return push_back(tmpVal);
111     }
112     bool push_backV(const std::vector<UniValue>& vec);
113 
114     void __pushKV(const std::string& key, const UniValue& val);
115     bool pushKV(const std::string& key, const UniValue& val);
pushKV(const std::string & key,const std::string & val_)116     bool pushKV(const std::string& key, const std::string& val_) {
117         UniValue tmpVal(VSTR, val_);
118         return pushKV(key, tmpVal);
119     }
pushKV(const std::string & key,const char * val_)120     bool pushKV(const std::string& key, const char *val_) {
121         std::string _val(val_);
122         return pushKV(key, _val);
123     }
pushKV(const std::string & key,int64_t val_)124     bool pushKV(const std::string& key, int64_t val_) {
125         UniValue tmpVal(val_);
126         return pushKV(key, tmpVal);
127     }
pushKV(const std::string & key,uint64_t val_)128     bool pushKV(const std::string& key, uint64_t val_) {
129         UniValue tmpVal(val_);
130         return pushKV(key, tmpVal);
131     }
pushKV(const std::string & key,bool val_)132     bool pushKV(const std::string& key, bool val_) {
133         UniValue tmpVal((bool)val_);
134         return pushKV(key, tmpVal);
135     }
pushKV(const std::string & key,int val_)136     bool pushKV(const std::string& key, int val_) {
137         UniValue tmpVal((int64_t)val_);
138         return pushKV(key, tmpVal);
139     }
pushKV(const std::string & key,double val_)140     bool pushKV(const std::string& key, double val_) {
141         UniValue tmpVal(val_);
142         return pushKV(key, tmpVal);
143     }
144     bool pushKVs(const UniValue& obj);
145 
146     std::string write(unsigned int prettyIndent = 0,
147                       unsigned int indentLevel = 0) const;
148 
149     bool read(const char *raw, size_t len);
read(const char * raw)150     bool read(const char *raw) { return read(raw, strlen(raw)); }
read(const std::string & rawStr)151     bool read(const std::string& rawStr) {
152         return read(rawStr.data(), rawStr.size());
153     }
154 
155 private:
156     UniValue::VType typ;
157     std::string val;                       // numbers are stored as C++ strings
158     std::vector<std::string> keys;
159     std::vector<UniValue> values;
160 
161     bool findKey(const std::string& key, size_t& retIdx) const;
162     void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
163     void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
164 
165 public:
166     // Strict type-specific getters, these throw std::runtime_error if the
167     // value is of unexpected type
168     const std::vector<std::string>& getKeys() const;
169     const std::vector<UniValue>& getValues() const;
170     bool get_bool() const;
171     const std::string& get_str() const;
172     int get_int() const;
173     int64_t get_int64() const;
174     double get_real() const;
175     const UniValue& get_obj() const;
176     const UniValue& get_array() const;
177 
type()178     enum VType type() const { return getType(); }
179     friend const UniValue& find_value( const UniValue& obj, const std::string& name);
180 };
181 
182 enum jtokentype {
183     JTOK_ERR        = -1,
184     JTOK_NONE       = 0,                           // eof
185     JTOK_OBJ_OPEN,
186     JTOK_OBJ_CLOSE,
187     JTOK_ARR_OPEN,
188     JTOK_ARR_CLOSE,
189     JTOK_COLON,
190     JTOK_COMMA,
191     JTOK_KW_NULL,
192     JTOK_KW_TRUE,
193     JTOK_KW_FALSE,
194     JTOK_NUMBER,
195     JTOK_STRING,
196 };
197 
198 extern enum jtokentype getJsonToken(std::string& tokenVal,
199                                     unsigned int& consumed, const char *raw, const char *end);
200 extern const char *uvTypeName(UniValue::VType t);
201 
jsonTokenIsValue(enum jtokentype jtt)202 static inline bool jsonTokenIsValue(enum jtokentype jtt)
203 {
204     switch (jtt) {
205     case JTOK_KW_NULL:
206     case JTOK_KW_TRUE:
207     case JTOK_KW_FALSE:
208     case JTOK_NUMBER:
209     case JTOK_STRING:
210         return true;
211 
212     default:
213         return false;
214     }
215 
216     // not reached
217 }
218 
json_isspace(int ch)219 static inline bool json_isspace(int ch)
220 {
221     switch (ch) {
222     case 0x20:
223     case 0x09:
224     case 0x0a:
225     case 0x0d:
226         return true;
227 
228     default:
229         return false;
230     }
231 
232     // not reached
233 }
234 
235 extern const UniValue NullUniValue;
236 
237 const UniValue& find_value( const UniValue& obj, const std::string& name);
238 
239 #endif // __UNIVALUE_H__
240