Var.cpp 10 KB

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