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