PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Foundation/src/Var.cpp

https://github.com/mkrivos/poco
C++ | 665 lines | 551 code | 92 blank | 22 comment | 123 complexity | ee2831abdc57f1c2ef260d526929ffcd MD5 | raw file
  1. //
  2. // Var.cpp
  3. //
  4. // Library: Foundation
  5. // Package: Core
  6. // Module: Var
  7. //
  8. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
  9. // and Contributors.
  10. //
  11. // SPDX-License-Identifier: BSL-1.0
  12. //
  13. #include "Poco/Dynamic/Var.h"
  14. #include "Poco/Dynamic/Struct.h"
  15. #include "Poco/NumberParser.h"
  16. #include <algorithm>
  17. #include <cctype>
  18. #include <vector>
  19. #include <list>
  20. #include <deque>
  21. namespace Poco {
  22. namespace Dynamic {
  23. Var::Var()
  24. #ifdef POCO_NO_SOO
  25. : _pHolder(0)
  26. #endif
  27. {
  28. }
  29. Var::Var(const char* pVal)
  30. #ifdef POCO_NO_SOO
  31. : _pHolder(new VarHolderImpl<std::string>(pVal))
  32. {
  33. }
  34. #else
  35. {
  36. construct(std::string(pVal));
  37. }
  38. #endif
  39. Var::Var(const Var& other)
  40. #ifdef POCO_NO_SOO
  41. : _pHolder(other._pHolder ? other._pHolder->clone() : 0)
  42. {
  43. }
  44. #else
  45. {
  46. if ((this != &other) && !other.isEmpty())
  47. construct(other);
  48. }
  49. #endif
  50. #if __cplusplus >= 201103L
  51. Var::Var(Var&& val) noexcept
  52. : _pHolder(std::move(val._pHolder))
  53. {
  54. val._pHolder = nullptr;
  55. }
  56. Var& Var::operator = (Var&& other) noexcept
  57. {
  58. if (_pHolder)
  59. delete _pHolder;
  60. _pHolder = std::move(other._pHolder);
  61. other._pHolder = nullptr;
  62. return *this;
  63. }
  64. #endif
  65. Var::~Var()
  66. {
  67. destruct();
  68. }
  69. Var& Var::operator = (const Var& rhs)
  70. {
  71. #ifdef POCO_NO_SOO
  72. Var tmp(rhs);
  73. swap(tmp);
  74. #else
  75. if ((this != &rhs) && !rhs.isEmpty())
  76. construct(rhs);
  77. else if ((this != &rhs) && rhs.isEmpty())
  78. _placeholder.erase();
  79. #endif
  80. return *this;
  81. }
  82. const Var Var::operator + (const Var& other) const
  83. {
  84. if (isInteger())
  85. {
  86. if (isSigned())
  87. return add<Poco::Int64>(other);
  88. else
  89. return add<Poco::UInt64>(other);
  90. }
  91. else if (isNumeric())
  92. return add<double>(other);
  93. else if (isString())
  94. return add<std::string>(other);
  95. else
  96. throw InvalidArgumentException("Invalid operation for this data type.");
  97. }
  98. Var& Var::operator += (const Var& other)
  99. {
  100. if (isInteger())
  101. {
  102. if (isSigned())
  103. return *this = add<Poco::Int64>(other);
  104. else
  105. return *this = add<Poco::UInt64>(other);
  106. }
  107. else if (isNumeric())
  108. return *this = add<double>(other);
  109. else if (isString())
  110. return *this = add<std::string>(other);
  111. else
  112. throw InvalidArgumentException("Invalid operation for this data type.");
  113. }
  114. const Var Var::operator - (const Var& other) const
  115. {
  116. if (isInteger())
  117. {
  118. if (isSigned())
  119. return subtract<Poco::Int64>(other);
  120. else
  121. return subtract<Poco::UInt64>(other);
  122. }
  123. else if (isNumeric())
  124. return subtract<double>(other);
  125. else
  126. throw InvalidArgumentException("Invalid operation for this data type.");
  127. }
  128. Var& Var::operator -= (const Var& other)
  129. {
  130. if (isInteger())
  131. {
  132. if (isSigned())
  133. return *this = subtract<Poco::Int64>(other);
  134. else
  135. return *this = subtract<Poco::UInt64>(other);
  136. }
  137. else if (isNumeric())
  138. return *this = subtract<double>(other);
  139. else
  140. throw InvalidArgumentException("Invalid operation for this data type.");
  141. }
  142. const Var Var::operator * (const Var& other) const
  143. {
  144. if (isInteger())
  145. {
  146. if (isSigned())
  147. return multiply<Poco::Int64>(other);
  148. else
  149. return multiply<Poco::UInt64>(other);
  150. }
  151. else if (isNumeric())
  152. return multiply<double>(other);
  153. else
  154. throw InvalidArgumentException("Invalid operation for this data type.");
  155. }
  156. Var& Var::operator *= (const Var& other)
  157. {
  158. if (isInteger())
  159. {
  160. if (isSigned())
  161. return *this = multiply<Poco::Int64>(other);
  162. else
  163. return *this = multiply<Poco::UInt64>(other);
  164. }
  165. else if (isNumeric())
  166. return *this = multiply<double>(other);
  167. else
  168. throw InvalidArgumentException("Invalid operation for this data type.");
  169. }
  170. const Var Var::operator / (const Var& other) const
  171. {
  172. if (isInteger())
  173. {
  174. if (isSigned())
  175. return divide<Poco::Int64>(other);
  176. else
  177. return divide<Poco::UInt64>(other);
  178. }
  179. else if (isNumeric())
  180. return divide<double>(other);
  181. else
  182. throw InvalidArgumentException("Invalid operation for this data type.");
  183. }
  184. Var& Var::operator /= (const Var& other)
  185. {
  186. if (isInteger())
  187. {
  188. if (isSigned())
  189. return *this = divide<Poco::Int64>(other);
  190. else
  191. return *this = divide<Poco::UInt64>(other);
  192. }
  193. else if (isNumeric())
  194. return *this = divide<double>(other);
  195. else
  196. throw InvalidArgumentException("Invalid operation for this data type.");
  197. }
  198. Var& Var::operator ++ ()
  199. {
  200. if (!isInteger())
  201. throw InvalidArgumentException("Invalid operation for this data type.");
  202. return *this = *this + 1;
  203. }
  204. const Var Var::operator ++ (int)
  205. {
  206. if (!isInteger())
  207. throw InvalidArgumentException("Invalid operation for this data type.");
  208. Var tmp(*this);
  209. *this += 1;
  210. return tmp;
  211. }
  212. Var& Var::operator -- ()
  213. {
  214. if (!isInteger())
  215. throw InvalidArgumentException("Invalid operation for this data type.");
  216. return *this = *this - 1;
  217. }
  218. const Var Var::operator -- (int)
  219. {
  220. if (!isInteger())
  221. throw InvalidArgumentException("Invalid operation for this data type.");
  222. Var tmp(*this);
  223. *this -= 1;
  224. return tmp;
  225. }
  226. bool Var::operator == (const Var& other) const
  227. {
  228. if (isEmpty() != other.isEmpty()) return false;
  229. if (isEmpty() && other.isEmpty()) return true;
  230. return convert<std::string>() == other.convert<std::string>();
  231. }
  232. bool Var::operator == (const char* other) const
  233. {
  234. if (isEmpty()) return false;
  235. return convert<std::string>() == other;
  236. }
  237. bool Var::operator != (const Var& other) const
  238. {
  239. if (isEmpty() && other.isEmpty()) return false;
  240. else if (isEmpty() || other.isEmpty()) return true;
  241. return convert<std::string>() != other.convert<std::string>();
  242. }
  243. bool Var::operator != (const char* other) const
  244. {
  245. if (isEmpty()) return true;
  246. return convert<std::string>() != other;
  247. }
  248. bool Var::operator < (const Var& other) const
  249. {
  250. if (isEmpty() || other.isEmpty()) return false;
  251. return convert<std::string>() < other.convert<std::string>();
  252. }
  253. bool Var::operator <= (const Var& other) const
  254. {
  255. if (isEmpty() || other.isEmpty()) return false;
  256. return convert<std::string>() <= other.convert<std::string>();
  257. }
  258. bool Var::operator > (const Var& other) const
  259. {
  260. if (isEmpty() || other.isEmpty()) return false;
  261. return convert<std::string>() > other.convert<std::string>();
  262. }
  263. bool Var::operator >= (const Var& other) const
  264. {
  265. if (isEmpty() || other.isEmpty()) return false;
  266. return convert<std::string>() >= other.convert<std::string>();
  267. }
  268. bool Var::operator || (const Var& other) const
  269. {
  270. if (isEmpty() || other.isEmpty()) return false;
  271. return convert<bool>() || other.convert<bool>();
  272. }
  273. bool Var::operator && (const Var& other) const
  274. {
  275. if (isEmpty() || other.isEmpty()) return false;
  276. return convert<bool>() && other.convert<bool>();
  277. }
  278. void Var::empty()
  279. {
  280. #ifdef POCO_NO_SOO
  281. delete _pHolder;
  282. _pHolder = 0;
  283. #else
  284. if (_placeholder.isLocal()) this->~Var();
  285. else delete content();
  286. _placeholder.erase();
  287. #endif
  288. }
  289. void Var::clear()
  290. {
  291. #ifdef POCO_NO_SOO
  292. delete _pHolder;
  293. _pHolder = 0;
  294. #else
  295. if (_placeholder.isLocal()) this->~Var();
  296. else delete content();
  297. _placeholder.erase();
  298. #endif
  299. }
  300. Var& Var::getAt(std::size_t n)
  301. {
  302. if (isVector())
  303. return holderImpl<std::vector<Var>,
  304. InvalidAccessException>("Not a vector.")->operator[](n);
  305. else if (isList())
  306. return holderImpl<std::list<Var>,
  307. InvalidAccessException>("Not a list.")->operator[](n);
  308. else if (isDeque())
  309. return holderImpl<std::deque<Var>,
  310. InvalidAccessException>("Not a deque.")->operator[](n);
  311. else if (isStruct())
  312. {
  313. #ifdef POCO_ENABLE_CPP11
  314. if (isOrdered())
  315. return structIndexOperator(holderImpl<Struct<int, OrderedMap<int, Var>, OrderedSet<int> >,
  316. InvalidAccessException>("Not a struct."), static_cast<int>(n));
  317. else
  318. #endif // POCO_ENABLE_CPP11
  319. return structIndexOperator(holderImpl<Struct<int, std::map<int, Var>, std::set<int> >,
  320. InvalidAccessException>("Not a struct."), static_cast<int>(n));
  321. }
  322. else if (!isString() && !isEmpty() && (n == 0))
  323. return *this;
  324. throw RangeException("Index out of bounds.");
  325. }
  326. char& Var::at(std::size_t n)
  327. {
  328. if (isString())
  329. {
  330. return holderImpl<std::string,
  331. InvalidAccessException>("Not a string.")->operator[](n);
  332. }
  333. throw InvalidAccessException("Not a string.");
  334. }
  335. Var& Var::getAt(const std::string& name)
  336. {
  337. if (isStruct())
  338. {
  339. #ifdef POCO_ENABLE_CPP11
  340. if (isOrdered())
  341. return structIndexOperator(holderImpl<OrderedDynamicStruct, InvalidAccessException>("Not a struct."), name);
  342. else
  343. #endif // POCO_ENABLE_CPP11
  344. return structIndexOperator(holderImpl<DynamicStruct, InvalidAccessException>("Not a struct."), name);
  345. }
  346. throw InvalidAccessException("Not a struct.");
  347. }
  348. Var Var::parse(const std::string& val)
  349. {
  350. std::string::size_type t = 0;
  351. return parse(val, t);
  352. }
  353. Var Var::parse(const std::string& val, std::string::size_type& pos)
  354. {
  355. // { -> an Object==DynamicStruct
  356. // [ -> an array
  357. // '/" -> a string (strip '/")
  358. // other: also treat as string
  359. skipWhiteSpace(val, pos);
  360. if (pos < val.size())
  361. {
  362. switch (val[pos])
  363. {
  364. case '{':
  365. return parseObject(val, pos);
  366. case '[':
  367. return parseArray(val, pos);
  368. case '"':
  369. return parseJSONString(val, pos);
  370. default:
  371. {
  372. std::string str = parseString(val, pos);
  373. if (str == "false") return false;
  374. if (str == "true") return true;
  375. bool isNumber = false;
  376. bool isSigned = false;
  377. int separators = 0;
  378. int frac = 0;
  379. int index = 0;
  380. size_t size = str.size();
  381. for (size_t i = 0; i < size ; ++i)
  382. {
  383. int ch = str[i];
  384. if ((ch == '-' || ch == '+') && index == 0)
  385. {
  386. if (ch == '-') isSigned = true;
  387. }
  388. else if (Ascii::isDigit(ch))
  389. {
  390. isNumber |= true;
  391. }
  392. else if (ch == '.' || ch == ',')
  393. {
  394. frac = ch;
  395. ++separators;
  396. if (separators > 1) return str;
  397. }
  398. else return str;
  399. ++index;
  400. }
  401. if (frac && isNumber)
  402. {
  403. const double number = NumberParser::parseFloat(str, static_cast<char>(frac));
  404. return Var(number);
  405. }
  406. else if (frac == 0 && isNumber && isSigned)
  407. {
  408. const Poco::Int64 number = NumberParser::parse64(str);
  409. return number;
  410. }
  411. else if (frac == 0 && isNumber && !isSigned)
  412. {
  413. const Poco::UInt64 number = NumberParser::parseUnsigned64(str);
  414. return number;
  415. }
  416. return str;
  417. }
  418. }
  419. }
  420. std::string empty;
  421. return empty;
  422. }
  423. Var Var::parseObject(const std::string& val, std::string::size_type& pos)
  424. {
  425. poco_assert_dbg (pos < val.size() && val[pos] == '{');
  426. ++pos;
  427. skipWhiteSpace(val, pos);
  428. DynamicStruct aStruct;
  429. while (val[pos] != '}' && pos < val.size())
  430. {
  431. std::string key = parseString(val, pos);
  432. skipWhiteSpace(val, pos);
  433. if (val[pos] != ':')
  434. throw DataFormatException("Incorrect object, must contain: key : value pairs");
  435. ++pos; // skip past :
  436. Var value = parse(val, pos);
  437. aStruct.insert(key, value);
  438. skipWhiteSpace(val, pos);
  439. if (val[pos] == ',')
  440. {
  441. ++pos;
  442. skipWhiteSpace(val, pos);
  443. }
  444. }
  445. if (val[pos] != '}')
  446. throw DataFormatException("Unterminated object");
  447. ++pos;
  448. return aStruct;
  449. }
  450. Var Var::parseArray(const std::string& val, std::string::size_type& pos)
  451. {
  452. poco_assert_dbg (pos < val.size() && val[pos] == '[');
  453. ++pos;
  454. skipWhiteSpace(val, pos);
  455. std::vector<Var> result;
  456. while (val[pos] != ']' && pos < val.size())
  457. {
  458. result.push_back(parse(val, pos));
  459. skipWhiteSpace(val, pos);
  460. if (val[pos] == ',')
  461. {
  462. ++pos;
  463. skipWhiteSpace(val, pos);
  464. }
  465. }
  466. if (val[pos] != ']')
  467. throw DataFormatException("Unterminated array");
  468. ++pos;
  469. return result;
  470. }
  471. std::string Var::parseString(const std::string& val, std::string::size_type& pos)
  472. {
  473. poco_assert_dbg (pos < val.size());
  474. if (val[pos] == '"')
  475. {
  476. return parseJSONString(val, pos);
  477. }
  478. else
  479. {
  480. std::string result;
  481. while (pos < val.size()
  482. && !Poco::Ascii::isSpace(val[pos])
  483. && val[pos] != ','
  484. && val[pos] != ']'
  485. && val[pos] != '}')
  486. {
  487. result += val[pos++];
  488. }
  489. return result;
  490. }
  491. }
  492. std::string Var::parseJSONString(const std::string& val, std::string::size_type& pos)
  493. {
  494. poco_assert_dbg (pos < val.size() && val[pos] == '"');
  495. ++pos;
  496. std::string result;
  497. bool done = false;
  498. while (pos < val.size() && !done)
  499. {
  500. switch (val[pos])
  501. {
  502. case '"':
  503. done = true;
  504. ++pos;
  505. break;
  506. case '\\':
  507. if (pos < val.size())
  508. {
  509. ++pos;
  510. switch (val[pos])
  511. {
  512. case 'b':
  513. result += '\b';
  514. break;
  515. case 'f':
  516. result += '\f';
  517. break;
  518. case 'n':
  519. result += '\n';
  520. break;
  521. case 'r':
  522. result += '\r';
  523. break;
  524. case 't':
  525. result += '\t';
  526. break;
  527. default:
  528. result += val[pos];
  529. break;
  530. }
  531. break;
  532. }
  533. else
  534. {
  535. result += val[pos];
  536. }
  537. ++pos;
  538. break;
  539. default:
  540. result += val[pos++];
  541. break;
  542. }
  543. }
  544. if (!done) throw Poco::DataFormatException("unterminated JSON string");
  545. return result;
  546. }
  547. void Var::skipWhiteSpace(const std::string& val, std::string::size_type& pos)
  548. {
  549. poco_assert_dbg (pos < val.size());
  550. while (std::isspace(val[pos]) && pos < val.size())
  551. ++pos;
  552. }
  553. std::string Var::toString(const Var& any)
  554. {
  555. std::string res;
  556. Impl::appendJSONValue(res, any);
  557. return res;
  558. }
  559. /*
  560. Var& Var::structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const
  561. {
  562. return pStr->operator[](n);
  563. }
  564. */
  565. } } // namespace Poco::Dynamic