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 #include <stdint.h>
7 #include <iomanip>
8 #include <sstream>
9 #include <stdlib.h>
10
11 #include "univalue.h"
12 #include "univalue_utffilter.h"
13
14 const UniValue NullUniValue;
15
clear()16 void UniValue::clear()
17 {
18 typ = VNULL;
19 val.clear();
20 keys.clear();
21 values.clear();
22 }
23
setNull()24 bool UniValue::setNull()
25 {
26 clear();
27 return true;
28 }
29
setBool(bool val_)30 bool UniValue::setBool(bool val_)
31 {
32 clear();
33 typ = VBOOL;
34 if (val_)
35 val = "1";
36 return true;
37 }
38
validNumStr(const std::string & s)39 static bool validNumStr(const std::string& s)
40 {
41 std::string tokenVal;
42 unsigned int consumed;
43 enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size());
44 return (tt == JTOK_NUMBER);
45 }
46
setNumStr(const std::string & val_)47 bool UniValue::setNumStr(const std::string& val_)
48 {
49 if (!validNumStr(val_))
50 return false;
51
52 clear();
53 typ = VNUM;
54 val = val_;
55 return true;
56 }
57
setInt(uint64_t val_)58 bool UniValue::setInt(uint64_t val_)
59 {
60 std::ostringstream oss;
61
62 oss << val_;
63
64 return setNumStr(oss.str());
65 }
66
setInt(int64_t val_)67 bool UniValue::setInt(int64_t val_)
68 {
69 std::ostringstream oss;
70
71 oss << val_;
72
73 return setNumStr(oss.str());
74 }
75
setFloat(double val_)76 bool UniValue::setFloat(double val_)
77 {
78 std::ostringstream oss;
79
80 oss << std::setprecision(16) << val_;
81
82 bool ret = setNumStr(oss.str());
83 typ = VNUM;
84 return ret;
85 }
86
setStr(const std::string & val_)87 bool UniValue::setStr(const std::string& val_)
88 {
89 clear();
90 typ = VSTR;
91 val = val_;
92 return true;
93 }
94
setArray()95 bool UniValue::setArray()
96 {
97 clear();
98 typ = VARR;
99 return true;
100 }
101
setObject()102 bool UniValue::setObject()
103 {
104 clear();
105 typ = VOBJ;
106 return true;
107 }
108
push_back(const UniValue & val_)109 bool UniValue::push_back(const UniValue& val_)
110 {
111 if (typ != VARR)
112 return false;
113
114 values.push_back(val_);
115 return true;
116 }
117
push_backV(const std::vector<UniValue> & vec)118 bool UniValue::push_backV(const std::vector<UniValue>& vec)
119 {
120 if (typ != VARR)
121 return false;
122
123 values.insert(values.end(), vec.begin(), vec.end());
124
125 return true;
126 }
127
__pushKV(const std::string & key,const UniValue & val_)128 void UniValue::__pushKV(const std::string& key, const UniValue& val_)
129 {
130 keys.push_back(key);
131 values.push_back(val_);
132 }
133
pushKV(const std::string & key,const UniValue & val_)134 bool UniValue::pushKV(const std::string& key, const UniValue& val_)
135 {
136 if (typ != VOBJ)
137 return false;
138
139 size_t idx;
140 if (findKey(key, idx))
141 values[idx] = val_;
142 else
143 __pushKV(key, val_);
144 return true;
145 }
146
pushKVs(const UniValue & obj)147 bool UniValue::pushKVs(const UniValue& obj)
148 {
149 if (typ != VOBJ || obj.typ != VOBJ)
150 return false;
151
152 for (size_t i = 0; i < obj.keys.size(); i++)
153 __pushKV(obj.keys[i], obj.values.at(i));
154
155 return true;
156 }
157
getObjMap(std::map<std::string,UniValue> & kv) const158 void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const
159 {
160 if (typ != VOBJ)
161 return;
162
163 kv.clear();
164 for (size_t i = 0; i < keys.size(); i++)
165 kv[keys[i]] = values[i];
166 }
167
findKey(const std::string & key,size_t & retIdx) const168 bool UniValue::findKey(const std::string& key, size_t& retIdx) const
169 {
170 for (size_t i = 0; i < keys.size(); i++) {
171 if (keys[i] == key) {
172 retIdx = i;
173 return true;
174 }
175 }
176
177 return false;
178 }
179
checkObject(const std::map<std::string,UniValue::VType> & t) const180 bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) const
181 {
182 if (typ != VOBJ)
183 return false;
184
185 for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin();
186 it != t.end(); ++it) {
187 size_t idx = 0;
188 if (!findKey(it->first, idx))
189 return false;
190
191 if (values.at(idx).getType() != it->second)
192 return false;
193 }
194
195 return true;
196 }
197
operator [](const std::string & key) const198 const UniValue& UniValue::operator[](const std::string& key) const
199 {
200 if (typ != VOBJ)
201 return NullUniValue;
202
203 size_t index = 0;
204 if (!findKey(key, index))
205 return NullUniValue;
206
207 return values.at(index);
208 }
209
operator [](size_t index) const210 const UniValue& UniValue::operator[](size_t index) const
211 {
212 if (typ != VOBJ && typ != VARR)
213 return NullUniValue;
214 if (index >= values.size())
215 return NullUniValue;
216
217 return values.at(index);
218 }
219
uvTypeName(UniValue::VType t)220 const char *uvTypeName(UniValue::VType t)
221 {
222 switch (t) {
223 case UniValue::VNULL: return "null";
224 case UniValue::VBOOL: return "bool";
225 case UniValue::VOBJ: return "object";
226 case UniValue::VARR: return "array";
227 case UniValue::VSTR: return "string";
228 case UniValue::VNUM: return "number";
229 }
230
231 // not reached
232 return NULL;
233 }
234
find_value(const UniValue & obj,const std::string & name)235 const UniValue& find_value(const UniValue& obj, const std::string& name)
236 {
237 for (unsigned int i = 0; i < obj.keys.size(); i++)
238 if (obj.keys[i] == name)
239 return obj.values.at(i);
240
241 return NullUniValue;
242 }
243
IsValidUtf8String(const std::string & str)244 bool IsValidUtf8String(const std::string& str)
245 {
246 std::string valStr;
247 JSONUTF8StringFilter writer(valStr);
248 for (size_t i = 0; i < str.size (); ++i)
249 writer.push_back(str[i]);
250 return writer.finalize();
251 }
252