PageRenderTime 22ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/univalue/lib/univalue.cpp

https://gitlab.com/jslee1/bitcoin
C++ | 360 lines | 290 code | 60 blank | 10 comment | 81 complexity | e0822cc3fc580f6c02e38a3bd297e596 MD5 | raw file
  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. #include <stdint.h>
  6. #include <errno.h>
  7. #include <iomanip>
  8. #include <limits>
  9. #include <sstream>
  10. #include <stdexcept>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "univalue.h"
  14. namespace
  15. {
  16. static bool ParsePrechecks(const std::string& str)
  17. {
  18. if (str.empty()) // No empty string allowed
  19. return false;
  20. if (str.size() >= 1 && (json_isspace(str[0]) || json_isspace(str[str.size()-1]))) // No padding allowed
  21. return false;
  22. if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
  23. return false;
  24. return true;
  25. }
  26. bool ParseInt32(const std::string& str, int32_t *out)
  27. {
  28. if (!ParsePrechecks(str))
  29. return false;
  30. char *endp = NULL;
  31. errno = 0; // strtol will not set errno if valid
  32. long int n = strtol(str.c_str(), &endp, 10);
  33. if(out) *out = (int32_t)n;
  34. // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
  35. // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
  36. // platforms the size of these types may be different.
  37. return endp && *endp == 0 && !errno &&
  38. n >= std::numeric_limits<int32_t>::min() &&
  39. n <= std::numeric_limits<int32_t>::max();
  40. }
  41. bool ParseInt64(const std::string& str, int64_t *out)
  42. {
  43. if (!ParsePrechecks(str))
  44. return false;
  45. char *endp = NULL;
  46. errno = 0; // strtoll will not set errno if valid
  47. long long int n = strtoll(str.c_str(), &endp, 10);
  48. if(out) *out = (int64_t)n;
  49. // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
  50. // we still have to check that the returned value is within the range of an *int64_t*.
  51. return endp && *endp == 0 && !errno &&
  52. n >= std::numeric_limits<int64_t>::min() &&
  53. n <= std::numeric_limits<int64_t>::max();
  54. }
  55. bool ParseDouble(const std::string& str, double *out)
  56. {
  57. if (!ParsePrechecks(str))
  58. return false;
  59. if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
  60. return false;
  61. std::istringstream text(str);
  62. text.imbue(std::locale::classic());
  63. double result;
  64. text >> result;
  65. if(out) *out = result;
  66. return text.eof() && !text.fail();
  67. }
  68. }
  69. using namespace std;
  70. const UniValue NullUniValue;
  71. void UniValue::clear()
  72. {
  73. typ = VNULL;
  74. val.clear();
  75. keys.clear();
  76. values.clear();
  77. }
  78. bool UniValue::setNull()
  79. {
  80. clear();
  81. return true;
  82. }
  83. bool UniValue::setBool(bool val_)
  84. {
  85. clear();
  86. typ = VBOOL;
  87. if (val_)
  88. val = "1";
  89. return true;
  90. }
  91. static bool validNumStr(const string& s)
  92. {
  93. string tokenVal;
  94. unsigned int consumed;
  95. enum jtokentype tt = getJsonToken(tokenVal, consumed, s.c_str());
  96. return (tt == JTOK_NUMBER);
  97. }
  98. bool UniValue::setNumStr(const string& val_)
  99. {
  100. if (!validNumStr(val_))
  101. return false;
  102. clear();
  103. typ = VNUM;
  104. val = val_;
  105. return true;
  106. }
  107. bool UniValue::setInt(uint64_t val)
  108. {
  109. string s;
  110. ostringstream oss;
  111. oss << val;
  112. return setNumStr(oss.str());
  113. }
  114. bool UniValue::setInt(int64_t val)
  115. {
  116. string s;
  117. ostringstream oss;
  118. oss << val;
  119. return setNumStr(oss.str());
  120. }
  121. bool UniValue::setFloat(double val)
  122. {
  123. string s;
  124. ostringstream oss;
  125. oss << std::setprecision(16) << val;
  126. bool ret = setNumStr(oss.str());
  127. typ = VNUM;
  128. return ret;
  129. }
  130. bool UniValue::setStr(const string& val_)
  131. {
  132. clear();
  133. typ = VSTR;
  134. val = val_;
  135. return true;
  136. }
  137. bool UniValue::setArray()
  138. {
  139. clear();
  140. typ = VARR;
  141. return true;
  142. }
  143. bool UniValue::setObject()
  144. {
  145. clear();
  146. typ = VOBJ;
  147. return true;
  148. }
  149. bool UniValue::push_back(const UniValue& val)
  150. {
  151. if (typ != VARR)
  152. return false;
  153. values.push_back(val);
  154. return true;
  155. }
  156. bool UniValue::push_backV(const std::vector<UniValue>& vec)
  157. {
  158. if (typ != VARR)
  159. return false;
  160. values.insert(values.end(), vec.begin(), vec.end());
  161. return true;
  162. }
  163. bool UniValue::pushKV(const std::string& key, const UniValue& val)
  164. {
  165. if (typ != VOBJ)
  166. return false;
  167. keys.push_back(key);
  168. values.push_back(val);
  169. return true;
  170. }
  171. bool UniValue::pushKVs(const UniValue& obj)
  172. {
  173. if (typ != VOBJ || obj.typ != VOBJ)
  174. return false;
  175. for (unsigned int i = 0; i < obj.keys.size(); i++) {
  176. keys.push_back(obj.keys[i]);
  177. values.push_back(obj.values.at(i));
  178. }
  179. return true;
  180. }
  181. int UniValue::findKey(const std::string& key) const
  182. {
  183. for (unsigned int i = 0; i < keys.size(); i++) {
  184. if (keys[i] == key)
  185. return (int) i;
  186. }
  187. return -1;
  188. }
  189. bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
  190. {
  191. for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin();
  192. it != t.end(); it++) {
  193. int idx = findKey(it->first);
  194. if (idx < 0)
  195. return false;
  196. if (values.at(idx).getType() != it->second)
  197. return false;
  198. }
  199. return true;
  200. }
  201. const UniValue& UniValue::operator[](const std::string& key) const
  202. {
  203. if (typ != VOBJ)
  204. return NullUniValue;
  205. int index = findKey(key);
  206. if (index < 0)
  207. return NullUniValue;
  208. return values.at(index);
  209. }
  210. const UniValue& UniValue::operator[](unsigned int index) const
  211. {
  212. if (typ != VOBJ && typ != VARR)
  213. return NullUniValue;
  214. if (index >= values.size())
  215. return NullUniValue;
  216. return values.at(index);
  217. }
  218. const char *uvTypeName(UniValue::VType t)
  219. {
  220. switch (t) {
  221. case UniValue::VNULL: return "null";
  222. case UniValue::VBOOL: return "bool";
  223. case UniValue::VOBJ: return "object";
  224. case UniValue::VARR: return "array";
  225. case UniValue::VSTR: return "string";
  226. case UniValue::VNUM: return "number";
  227. }
  228. // not reached
  229. return NULL;
  230. }
  231. const UniValue& find_value(const UniValue& obj, const std::string& name)
  232. {
  233. for (unsigned int i = 0; i < obj.keys.size(); i++)
  234. if (obj.keys[i] == name)
  235. return obj.values.at(i);
  236. return NullUniValue;
  237. }
  238. std::vector<std::string> UniValue::getKeys() const
  239. {
  240. if (typ != VOBJ)
  241. throw std::runtime_error("JSON value is not an object as expected");
  242. return keys;
  243. }
  244. std::vector<UniValue> UniValue::getValues() const
  245. {
  246. if (typ != VOBJ && typ != VARR)
  247. throw std::runtime_error("JSON value is not an object or array as expected");
  248. return values;
  249. }
  250. bool UniValue::get_bool() const
  251. {
  252. if (typ != VBOOL)
  253. throw std::runtime_error("JSON value is not a boolean as expected");
  254. return getBool();
  255. }
  256. std::string UniValue::get_str() const
  257. {
  258. if (typ != VSTR)
  259. throw std::runtime_error("JSON value is not a string as expected");
  260. return getValStr();
  261. }
  262. int UniValue::get_int() const
  263. {
  264. if (typ != VNUM)
  265. throw std::runtime_error("JSON value is not an integer as expected");
  266. int32_t retval;
  267. if (!ParseInt32(getValStr(), &retval))
  268. throw std::runtime_error("JSON integer out of range");
  269. return retval;
  270. }
  271. int64_t UniValue::get_int64() const
  272. {
  273. if (typ != VNUM)
  274. throw std::runtime_error("JSON value is not an integer as expected");
  275. int64_t retval;
  276. if (!ParseInt64(getValStr(), &retval))
  277. throw std::runtime_error("JSON integer out of range");
  278. return retval;
  279. }
  280. double UniValue::get_real() const
  281. {
  282. if (typ != VNUM)
  283. throw std::runtime_error("JSON value is not a number as expected");
  284. double retval;
  285. if (!ParseDouble(getValStr(), &retval))
  286. throw std::runtime_error("JSON double out of range");
  287. return retval;
  288. }
  289. const UniValue& UniValue::get_obj() const
  290. {
  291. if (typ != VOBJ)
  292. throw std::runtime_error("JSON value is not an object as expected");
  293. return *this;
  294. }
  295. const UniValue& UniValue::get_array() const
  296. {
  297. if (typ != VARR)
  298. throw std::runtime_error("JSON value is not an array as expected");
  299. return *this;
  300. }