configor_value.hpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. // Copyright (c) 2018-2020 configor - Nomango
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // is the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included is
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #pragma once
  21. #include "configor_iterator.hpp"
  22. #include <algorithm> // std::for_each, std::all_of
  23. #include <cmath> // std::fabs
  24. #include <limits> // std::numeric_limits
  25. #include <memory> // std::allocator_traits
  26. #include <sstream> // std::stringstream
  27. #include <type_traits> // std::enable_if, std::is_same, std::is_integral, std::is_floating_point
  28. #include <utility> // std::swap, std::forward, std::declval
  29. namespace configor
  30. {
  31. namespace detail
  32. {
  33. template <typename _ValTy>
  34. class value_constructor;
  35. } // namespace detail
  36. template <typename _Args>
  37. class basic_value final : public value_constant
  38. {
  39. friend detail::value_constructor<basic_value>;
  40. public:
  41. template <typename _Ty>
  42. using allocator_type = typename _Args::template allocator_type<_Ty>;
  43. using boolean_type = typename _Args::boolean_type;
  44. using integer_type = typename _Args::integer_type;
  45. using float_type = typename _Args::float_type;
  46. using char_type = typename _Args::char_type;
  47. using string_type =
  48. typename _Args::template string_type<char_type, std::char_traits<char_type>, allocator_type<char_type>>;
  49. using array_type = typename _Args::template array_type<basic_value, allocator_type<basic_value>>;
  50. using object_type = typename _Args::template object_type<string_type, basic_value, std::less<string_type>,
  51. allocator_type<std::pair<const string_type, basic_value>>>;
  52. template <typename _Ty>
  53. using binder_type = typename _Args::template binder_type<_Ty>;
  54. using size_type = std::size_t;
  55. using difference_type = std::ptrdiff_t;
  56. using iterator = detail::iterator<basic_value>;
  57. using const_iterator = detail::iterator<const basic_value>;
  58. using reverse_iterator = detail::reverse_iterator<iterator>;
  59. using const_reverse_iterator = detail::reverse_iterator<const_iterator>;
  60. union data_type
  61. {
  62. boolean_type boolean;
  63. integer_type integer;
  64. float_type floating;
  65. string_type* string;
  66. object_type* object;
  67. array_type* vector;
  68. };
  69. basic_value(std::nullptr_t = nullptr)
  70. : type_{ value_constant::null }
  71. , data_{}
  72. {
  73. }
  74. basic_value(const value_constant::type t)
  75. : type_{ t }
  76. , data_{}
  77. {
  78. using accessor = detail::value_constructor<basic_value>;
  79. switch (t)
  80. {
  81. case value_constant::object:
  82. accessor::template construct<value_constant::object>(*this);
  83. break;
  84. case value_constant::array:
  85. accessor::template construct<value_constant::array>(*this);
  86. break;
  87. case value_constant::string:
  88. accessor::template construct<value_constant::string>(*this);
  89. break;
  90. case value_constant::integer:
  91. accessor::template construct<value_constant::integer>(*this, integer_type(0));
  92. break;
  93. case value_constant::floating:
  94. accessor::template construct<value_constant::floating>(*this, float_type(0.0));
  95. break;
  96. case value_constant::boolean:
  97. accessor::template construct<value_constant::boolean>(*this, boolean_type(false));
  98. break;
  99. default:
  100. break;
  101. }
  102. }
  103. basic_value(const basic_value& other)
  104. : type_{ other.type() }
  105. , data_{}
  106. {
  107. using accessor = detail::value_constructor<basic_value>;
  108. switch (other.type())
  109. {
  110. case value_constant::object:
  111. accessor::template construct<value_constant::object>(*this, *other.data().object);
  112. break;
  113. case value_constant::array:
  114. accessor::template construct<value_constant::array>(*this, *other.data().vector);
  115. break;
  116. case value_constant::string:
  117. accessor::template construct<value_constant::string>(*this, *other.data().string);
  118. break;
  119. case value_constant::integer:
  120. accessor::template construct<value_constant::integer>(*this, other.data().integer);
  121. break;
  122. case value_constant::floating:
  123. accessor::template construct<value_constant::floating>(*this, other.data().floating);
  124. break;
  125. case value_constant::boolean:
  126. accessor::template construct<value_constant::boolean>(*this, other.data().boolean);
  127. break;
  128. default:
  129. break;
  130. }
  131. }
  132. basic_value(basic_value&& other) noexcept
  133. : type_{ other.type() }
  134. , data_{ other.data() }
  135. {
  136. other.type(value_constant::null);
  137. other.data().object = nullptr;
  138. }
  139. template <typename _CompatibleTy, typename _UTy = typename detail::remove_cvref<_CompatibleTy>::type,
  140. typename std::enable_if<!is_value<_UTy>::value && detail::has_to_value<basic_value, _UTy>::value,
  141. int>::type = 0>
  142. basic_value(_CompatibleTy&& value)
  143. : type_{ value_constant::null }
  144. , data_{}
  145. {
  146. binder_type<_UTy>::to_value(*this, std::forward<_CompatibleTy>(value));
  147. }
  148. ~basic_value()
  149. {
  150. using accessor = detail::value_constructor<basic_value>;
  151. accessor::destroy(*this);
  152. }
  153. const data_type& data() const
  154. {
  155. return data_;
  156. }
  157. data_type& data()
  158. {
  159. return data_;
  160. }
  161. inline value_constant::type type() const
  162. {
  163. return type_;
  164. }
  165. private:
  166. inline void type(value_constant::type t)
  167. {
  168. type_ = t;
  169. }
  170. public:
  171. inline bool is_object() const
  172. {
  173. return type() == value_constant::object;
  174. }
  175. inline bool is_array() const
  176. {
  177. return type() == value_constant::array;
  178. }
  179. inline bool is_string() const
  180. {
  181. return type() == value_constant::string;
  182. }
  183. inline bool is_bool() const
  184. {
  185. return type() == value_constant::boolean;
  186. }
  187. inline bool is_integer() const
  188. {
  189. return type() == value_constant::integer;
  190. }
  191. inline bool is_floating() const
  192. {
  193. return type() == value_constant::floating;
  194. }
  195. inline bool is_number() const
  196. {
  197. return is_integer() || is_floating();
  198. }
  199. inline bool is_null() const
  200. {
  201. return type() == value_constant::null;
  202. }
  203. public:
  204. inline iterator begin()
  205. {
  206. iterator iter(this);
  207. iter.set_begin();
  208. return iter;
  209. }
  210. inline const_iterator begin() const
  211. {
  212. return cbegin();
  213. }
  214. inline const_iterator cbegin() const
  215. {
  216. const_iterator iter(this);
  217. iter.set_begin();
  218. return iter;
  219. }
  220. inline iterator end()
  221. {
  222. iterator iter(this);
  223. iter.set_end();
  224. return iter;
  225. }
  226. inline const_iterator end() const
  227. {
  228. return cend();
  229. }
  230. inline const_iterator cend() const
  231. {
  232. const_iterator iter(this);
  233. iter.set_end();
  234. return iter;
  235. }
  236. inline reverse_iterator rbegin()
  237. {
  238. return reverse_iterator(end());
  239. }
  240. inline const_reverse_iterator rbegin() const
  241. {
  242. return const_reverse_iterator(end());
  243. }
  244. inline const_reverse_iterator crbegin() const
  245. {
  246. return rbegin();
  247. }
  248. inline reverse_iterator rend()
  249. {
  250. return reverse_iterator(begin());
  251. }
  252. inline const_reverse_iterator rend() const
  253. {
  254. return const_reverse_iterator(begin());
  255. }
  256. inline const_reverse_iterator crend() const
  257. {
  258. return rend();
  259. }
  260. public:
  261. inline size_type size() const
  262. {
  263. switch (type())
  264. {
  265. case value_constant::null:
  266. return 0;
  267. case value_constant::array:
  268. return data().vector->size();
  269. case value_constant::object:
  270. return data().object->size();
  271. default:
  272. return 1;
  273. }
  274. }
  275. bool empty() const
  276. {
  277. if (is_null())
  278. return true;
  279. if (is_object())
  280. return data().object->empty();
  281. if (is_array())
  282. return data().vector->empty();
  283. return false;
  284. }
  285. iterator find(const typename object_type::key_type& key)
  286. {
  287. if (is_object())
  288. {
  289. iterator iter(this);
  290. iter.object_it_ = data().object->find(key);
  291. return iter;
  292. }
  293. return end();
  294. }
  295. const_iterator find(const typename object_type::key_type& key) const
  296. {
  297. if (is_object())
  298. {
  299. const_iterator iter(this);
  300. iter.object_it_ = data().object->find(key);
  301. return iter;
  302. }
  303. return cend();
  304. }
  305. inline size_type count(const typename object_type::key_type& key) const
  306. {
  307. return is_object() ? data().object->count(key) : 0;
  308. }
  309. size_type erase(const typename object_type::key_type& key)
  310. {
  311. if (!is_object())
  312. {
  313. throw configor_invalid_key("cannot use erase() with non-object value");
  314. }
  315. return data().object->erase(key);
  316. }
  317. void erase(const size_type index)
  318. {
  319. if (!is_array())
  320. {
  321. throw configor_invalid_key("cannot use erase() with non-array value");
  322. }
  323. data().vector->erase(data().vector->begin() + static_cast<difference_type>(index));
  324. }
  325. template <class _IterTy, typename = typename std::enable_if<std::is_same<_IterTy, iterator>::value
  326. || std::is_same<_IterTy, const_iterator>::value>::type>
  327. _IterTy erase(_IterTy pos)
  328. {
  329. _IterTy result = end();
  330. switch (type())
  331. {
  332. case value_constant::object:
  333. {
  334. result.object_it_ = data().object->erase(pos.object_it_);
  335. break;
  336. }
  337. case value_constant::array:
  338. {
  339. result.array_it_ = data().vector->erase(pos.array_it_);
  340. break;
  341. }
  342. default:
  343. throw configor_invalid_iterator("cannot use erase() with non-object & non-array value");
  344. }
  345. return result;
  346. }
  347. template <class _IterTy, typename = typename std::enable_if<std::is_same<_IterTy, iterator>::value
  348. || std::is_same<_IterTy, const_iterator>::value>::type>
  349. _IterTy erase(_IterTy first, _IterTy last)
  350. {
  351. _IterTy result = end();
  352. switch (type())
  353. {
  354. case value_constant::object:
  355. {
  356. result.object_it_ = data().object->erase(first.object_it_, last.object_it_);
  357. break;
  358. }
  359. case value_constant::array:
  360. {
  361. result.array_it_ = data().vector->erase(first.array_it_, last.array_it_);
  362. break;
  363. }
  364. default:
  365. throw configor_invalid_iterator("cannot use erase() with non-object & non-array value");
  366. }
  367. return result;
  368. }
  369. void push_back(const basic_value& v)
  370. {
  371. emplace_back(v);
  372. }
  373. void push_back(basic_value&& v)
  374. {
  375. emplace_back(std::move(v));
  376. }
  377. template <typename... _Ty>
  378. void emplace_back(_Ty&&... v)
  379. {
  380. if (!is_null() && !is_array())
  381. {
  382. throw configor_type_error("use push_back() or emplace_back() with non-array value");
  383. }
  384. if (is_null())
  385. {
  386. *this = value_constant::array;
  387. }
  388. data().vector->emplace_back(std::forward<_Ty>(v)...);
  389. }
  390. void clear()
  391. {
  392. switch (type())
  393. {
  394. case value_constant::integer:
  395. data().integer = 0;
  396. break;
  397. case value_constant::floating:
  398. data().floating = static_cast<float_type>(0.0);
  399. break;
  400. case value_constant::boolean:
  401. data().boolean = false;
  402. break;
  403. case value_constant::string:
  404. data().string->clear();
  405. break;
  406. case value_constant::array:
  407. data().vector->clear();
  408. break;
  409. case value_constant::object:
  410. data().object->clear();
  411. break;
  412. default:
  413. break;
  414. }
  415. }
  416. private:
  417. // get pointer value
  418. inline boolean_type* do_get_ptr(boolean_type*) noexcept
  419. {
  420. return is_bool() ? &data().boolean : nullptr;
  421. }
  422. inline const boolean_type* do_get_ptr(const boolean_type*) const noexcept
  423. {
  424. return is_bool() ? &data().boolean : nullptr;
  425. }
  426. inline integer_type* do_get_ptr(integer_type*) noexcept
  427. {
  428. return is_integer() ? &data().integer : nullptr;
  429. }
  430. inline const integer_type* do_get_ptr(const integer_type*) const noexcept
  431. {
  432. return is_integer() ? &data().integer : nullptr;
  433. }
  434. inline float_type* do_get_ptr(float_type*) noexcept
  435. {
  436. return is_floating() ? &data().floating : nullptr;
  437. }
  438. inline const float_type* do_get_ptr(const float_type*) const noexcept
  439. {
  440. return is_floating() ? &data().floating : nullptr;
  441. }
  442. inline string_type* do_get_ptr(string_type*) noexcept
  443. {
  444. return is_string() ? data().string : nullptr;
  445. }
  446. inline const string_type* do_get_ptr(const string_type*) const noexcept
  447. {
  448. return is_string() ? data().string : nullptr;
  449. }
  450. inline array_type* do_get_ptr(array_type*) noexcept
  451. {
  452. return is_array() ? data().vector : nullptr;
  453. }
  454. inline const array_type* do_get_ptr(const array_type*) const noexcept
  455. {
  456. return is_array() ? data().vector : nullptr;
  457. }
  458. inline object_type* do_get_ptr(object_type*) noexcept
  459. {
  460. return is_object() ? data().object : nullptr;
  461. }
  462. inline const object_type* do_get_ptr(const object_type*) const noexcept
  463. {
  464. return is_object() ? data().object : nullptr;
  465. }
  466. public:
  467. // get_ptr
  468. template <typename _Ty, typename = typename std::enable_if<std::is_pointer<_Ty>::value>::type>
  469. auto get_ptr() const -> decltype(std::declval<const basic_value&>().do_get_ptr(std::declval<_Ty>()))
  470. {
  471. return do_get_ptr(static_cast<_Ty>(nullptr));
  472. }
  473. template <typename _Ty, typename = typename std::enable_if<std::is_pointer<_Ty>::value>::type>
  474. auto get_ptr() -> decltype(std::declval<basic_value&>().do_get_ptr(std::declval<_Ty>()))
  475. {
  476. return do_get_ptr(static_cast<_Ty>(nullptr));
  477. }
  478. private:
  479. // get reference value
  480. template <typename _RefTy, typename _ValTy, typename _PtrTy = typename std::add_pointer<_RefTy>::type>
  481. static auto do_get_ref(_ValTy& c) -> decltype(c.template get_ptr<_PtrTy>(), std::declval<_RefTy>())
  482. {
  483. auto* ptr = c.template get_ptr<_PtrTy>();
  484. if (ptr != nullptr)
  485. {
  486. return *ptr;
  487. }
  488. throw configor_type_error(std::string("incompatible reference type for get, actual type is ")
  489. + to_string(c.type()));
  490. }
  491. // get value
  492. template <typename _Ty, typename = typename std::enable_if<std::is_same<basic_value, _Ty>::value>::type>
  493. _Ty do_get(detail::priority<3>) const
  494. {
  495. return *this;
  496. }
  497. template <typename _Ty, typename = typename std::enable_if<std::is_pointer<_Ty>::value>::type>
  498. auto do_get(detail::priority<2>) const noexcept
  499. -> decltype(std::declval<const basic_value&>().do_get_ptr(std::declval<_Ty>()))
  500. {
  501. return do_get_ptr(static_cast<_Ty>(nullptr));
  502. }
  503. template <typename _Ty,
  504. typename = typename std::enable_if<detail::has_non_default_from_value<basic_value, _Ty>::value>::type>
  505. _Ty do_get(detail::priority<1>) const
  506. {
  507. return binder_type<_Ty>::from_value(*this);
  508. }
  509. template <typename _Ty,
  510. typename = typename std::enable_if<std::is_default_constructible<_Ty>::value
  511. && detail::has_from_value<basic_value, _Ty>::value>::type>
  512. _Ty do_get(detail::priority<0>) const
  513. {
  514. _Ty value{};
  515. binder_type<_Ty>::from_value(*this, value);
  516. return value;
  517. }
  518. // get value by reference
  519. template <typename _Ty, typename = typename std::enable_if<std::is_same<basic_value, _Ty>::value>::type>
  520. _Ty& do_get(_Ty& value, detail::priority<3>) const
  521. {
  522. return (value = *this);
  523. }
  524. template <typename _Ty, typename = typename std::enable_if<std::is_pointer<_Ty>::value>::type>
  525. auto do_get(_Ty& value, detail::priority<2>) const noexcept
  526. -> decltype(std::declval<const basic_value&>().do_get_ptr(std::declval<_Ty>()))
  527. {
  528. return (value = do_get_ptr(static_cast<_Ty>(nullptr)));
  529. }
  530. template <typename _Ty, typename = typename std::enable_if<detail::has_from_value<basic_value, _Ty>::value>::type>
  531. _Ty& do_get(_Ty& value, detail::priority<1>) const
  532. {
  533. binder_type<_Ty>::from_value(*this, value);
  534. return value;
  535. }
  536. template <typename _Ty,
  537. typename = typename std::enable_if<detail::has_non_default_from_value<basic_value, _Ty>::value>::type>
  538. _Ty& do_get(_Ty& value, detail::priority<0>) const
  539. {
  540. value = binder_type<_Ty>::from_value(*this);
  541. return value;
  542. }
  543. public:
  544. // get
  545. template <typename _Ty, typename _UTy = typename detail::remove_cvref<_Ty>::type,
  546. typename = typename std::enable_if<!std::is_reference<_Ty>::value>::type>
  547. auto get() const -> decltype(std::declval<const basic_value&>().template do_get<_UTy>(detail::priority<3>{}))
  548. {
  549. return do_get<_UTy>(detail::priority<3>{});
  550. }
  551. template <typename _Ty, typename = typename std::enable_if<std::is_pointer<_Ty>::value>::type>
  552. auto get() -> decltype(std::declval<basic_value&>().template get_ptr<_Ty>())
  553. {
  554. return get_ptr<_Ty>();
  555. }
  556. template <typename _Ty, typename std::enable_if<std::is_reference<_Ty>::value, int>::type = 0>
  557. auto get() -> decltype(basic_value::template do_get_ref<_Ty>(std::declval<basic_value&>()))
  558. {
  559. return do_get_ref<_Ty>(*this);
  560. }
  561. template <typename _Ty,
  562. typename std::enable_if<std::is_reference<_Ty>::value
  563. && std::is_const<typename std::remove_reference<_Ty>::type>::value,
  564. int>::type = 0>
  565. auto get() const -> decltype(basic_value::template do_get_ref<_Ty>(std::declval<const basic_value&>()))
  566. {
  567. return do_get_ref<_Ty>(*this);
  568. }
  569. template <typename _Ty>
  570. auto get(_Ty& value) const
  571. -> decltype(std::declval<const basic_value&>().template do_get<_Ty>(std::declval<_Ty&>(),
  572. detail::priority<3>{}),
  573. bool{})
  574. {
  575. try
  576. {
  577. do_get<_Ty>(value, detail::priority<3>{});
  578. return true;
  579. }
  580. catch (...)
  581. {
  582. }
  583. return false;
  584. }
  585. template <typename _Ty, typename = typename std::enable_if<detail::is_value_getable<basic_value, _Ty>::value
  586. && !std::is_pointer<_Ty>::value
  587. && !std::is_reference<_Ty>::value>::type>
  588. inline operator _Ty() const
  589. {
  590. return get<_Ty>();
  591. }
  592. public:
  593. // swap function
  594. inline void swap(basic_value& rhs)
  595. {
  596. std::swap(type_, rhs.type_);
  597. std::swap(data_, rhs.data_);
  598. }
  599. // operator= functions
  600. basic_value& operator=(const basic_value& rhs)
  601. {
  602. if (this != &rhs)
  603. {
  604. basic_value tmp{ rhs };
  605. this->swap(tmp);
  606. }
  607. return *this;
  608. }
  609. basic_value& operator=(basic_value&& rhs)
  610. {
  611. if (this != &rhs)
  612. {
  613. basic_value old{ std::move(*this) };
  614. this->swap(rhs);
  615. }
  616. return *this;
  617. }
  618. // operator[] functions
  619. basic_value& operator[](const size_type index)
  620. {
  621. if (is_null())
  622. {
  623. *this = value_constant::array;
  624. }
  625. if (!is_array())
  626. {
  627. throw configor_invalid_key("operator[] called on a non-array object");
  628. }
  629. if (index >= data().vector->size())
  630. {
  631. data().vector->insert(data().vector->end(), index - data().vector->size() + 1, basic_value());
  632. }
  633. return (*data().vector)[index];
  634. }
  635. inline basic_value& operator[](const size_type index) const
  636. {
  637. return at(index);
  638. }
  639. basic_value& operator[](const typename object_type::key_type& key)
  640. {
  641. if (is_null())
  642. {
  643. *this = value_constant::object;
  644. }
  645. if (!is_object())
  646. {
  647. throw configor_invalid_key("operator[] called on a non-object type");
  648. }
  649. return (*data().object)[key];
  650. }
  651. inline basic_value& operator[](const typename object_type::key_type& key) const
  652. {
  653. return at(key);
  654. }
  655. basic_value& at(const size_type index) const
  656. {
  657. if (!is_array())
  658. {
  659. throw configor_invalid_key("operator[] called on a non-array type");
  660. }
  661. if (index >= data().vector->size())
  662. {
  663. throw std::out_of_range("operator[] index out of range");
  664. }
  665. return (*data().vector)[index];
  666. }
  667. template <typename _CharTy>
  668. basic_value& operator[](_CharTy* key)
  669. {
  670. if (is_null())
  671. {
  672. *this = value_constant::object;
  673. }
  674. if (!is_object())
  675. {
  676. throw configor_invalid_key("operator[] called on a non-object object");
  677. }
  678. return (*data().object)[key];
  679. }
  680. template <typename _CharTy>
  681. inline basic_value& operator[](_CharTy* key) const
  682. {
  683. return at(key);
  684. }
  685. basic_value& at(const typename object_type::key_type& key) const
  686. {
  687. if (!is_object())
  688. {
  689. throw configor_invalid_key("operator[] called on a non-object object");
  690. }
  691. auto iter = data().object->find(key);
  692. if (iter == data().object->end())
  693. {
  694. throw std::out_of_range("operator[] key out of range");
  695. }
  696. return iter->second;
  697. }
  698. template <typename _CharTy>
  699. basic_value& at(_CharTy* key) const
  700. {
  701. if (!is_object())
  702. {
  703. throw configor_invalid_key("operator[] called on a non-object object");
  704. }
  705. auto iter = data().object->find(key);
  706. if (iter == data().object->end())
  707. {
  708. throw std::out_of_range("operator[] key out of range");
  709. }
  710. return iter->second;
  711. }
  712. public:
  713. // eq functions
  714. friend bool operator==(const basic_value& lhs, const basic_value& rhs)
  715. {
  716. if (lhs.type() == rhs.type())
  717. {
  718. switch (lhs.type())
  719. {
  720. case value_constant::array:
  721. return (*lhs.data().vector == *rhs.data().vector);
  722. case value_constant::object:
  723. return (*lhs.data().object == *rhs.data().object);
  724. case value_constant::null:
  725. return true;
  726. case value_constant::string:
  727. return *lhs.data().string == *rhs.data().string;
  728. case value_constant::boolean:
  729. return lhs.data().boolean == rhs.data().boolean;
  730. case value_constant::integer:
  731. return lhs.data().integer == rhs.data().integer;
  732. case value_constant::floating:
  733. return lhs.data().floating == rhs.data().floating;
  734. default:
  735. return false;
  736. }
  737. }
  738. else if (lhs.type() == value_constant::integer && rhs.type() == value_constant::floating)
  739. {
  740. return static_cast<float_type>(lhs.data().integer) == rhs.data().floating;
  741. }
  742. else if (lhs.type() == value_constant::floating && rhs.type() == value_constant::integer)
  743. {
  744. return lhs.data().floating == static_cast<float_type>(rhs.data().integer);
  745. }
  746. return false;
  747. }
  748. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  749. friend inline bool operator==(const basic_value& lhs, _ScalarTy rhs)
  750. {
  751. return lhs == basic_value(rhs);
  752. }
  753. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  754. friend inline bool operator==(_ScalarTy lhs, const basic_value& rhs)
  755. {
  756. return basic_value(lhs) == rhs;
  757. }
  758. // ne functions
  759. friend inline bool operator!=(const basic_value& lhs, const basic_value& rhs)
  760. {
  761. return !(lhs == rhs);
  762. }
  763. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  764. friend inline bool operator!=(const basic_value& lhs, _ScalarTy rhs)
  765. {
  766. return lhs != basic_value(rhs);
  767. }
  768. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  769. friend inline bool operator!=(_ScalarTy lhs, const basic_value& rhs)
  770. {
  771. return basic_value(lhs) != rhs;
  772. }
  773. // lt functions
  774. friend bool operator<(const basic_value& lhs, const basic_value& rhs)
  775. {
  776. const auto lhs_type = lhs.type();
  777. const auto rhs_type = rhs.type();
  778. if (lhs_type == rhs_type)
  779. {
  780. switch (lhs_type)
  781. {
  782. case value_constant::array:
  783. return (*lhs.data().vector) < (*rhs.data().vector);
  784. case value_constant::object:
  785. return (*lhs.data().object) < (*rhs.data().object);
  786. case value_constant::null:
  787. return false;
  788. case value_constant::string:
  789. return (*lhs.data().string) < (*rhs.data().string);
  790. case value_constant::boolean:
  791. return (lhs.data().boolean < rhs.data().boolean);
  792. case value_constant::integer:
  793. return (lhs.data().integer < rhs.data().integer);
  794. case value_constant::floating:
  795. return (lhs.data().floating < rhs.data().floating);
  796. default:
  797. return false;
  798. }
  799. }
  800. else if (lhs_type == value_constant::integer && rhs_type == value_constant::floating)
  801. {
  802. return (static_cast<float_type>(lhs.data().integer) < rhs.data().floating);
  803. }
  804. else if (lhs_type == value_constant::floating && rhs_type == value_constant::integer)
  805. {
  806. return (lhs.data().floating < static_cast<float_type>(rhs.data().integer));
  807. }
  808. return false;
  809. }
  810. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  811. friend inline bool operator<(const basic_value& lhs, _ScalarTy rhs)
  812. {
  813. return lhs < basic_value(rhs);
  814. }
  815. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  816. friend inline bool operator<(_ScalarTy lhs, const basic_value& rhs)
  817. {
  818. return basic_value(lhs) < rhs;
  819. }
  820. // lte functions
  821. friend inline bool operator<=(const basic_value& lhs, const basic_value& rhs)
  822. {
  823. return !(rhs < lhs);
  824. }
  825. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  826. friend inline bool operator<=(const basic_value& lhs, _ScalarTy rhs)
  827. {
  828. return lhs <= basic_value(rhs);
  829. }
  830. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  831. friend inline bool operator<=(_ScalarTy lhs, const basic_value& rhs)
  832. {
  833. return basic_value(lhs) <= rhs;
  834. }
  835. // gt functions
  836. friend inline bool operator>(const basic_value& lhs, const basic_value& rhs)
  837. {
  838. return rhs < lhs;
  839. }
  840. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  841. friend inline bool operator>(const basic_value& lhs, _ScalarTy rhs)
  842. {
  843. return lhs > basic_value(rhs);
  844. }
  845. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  846. friend inline bool operator>(_ScalarTy lhs, const basic_value& rhs)
  847. {
  848. return basic_value(lhs) > rhs;
  849. }
  850. // gte functions
  851. friend inline bool operator>=(const basic_value& lhs, const basic_value& rhs)
  852. {
  853. return !(lhs < rhs);
  854. }
  855. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  856. friend inline bool operator>=(const basic_value& lhs, _ScalarTy rhs)
  857. {
  858. return lhs >= basic_value(rhs);
  859. }
  860. template <typename _ScalarTy, typename = typename std::enable_if<std::is_scalar<_ScalarTy>::value>::type>
  861. friend inline bool operator>=(_ScalarTy lhs, const basic_value& rhs)
  862. {
  863. return basic_value(lhs) >= rhs;
  864. }
  865. private:
  866. value_constant::type type_;
  867. data_type data_;
  868. };
  869. namespace detail
  870. {
  871. template <typename _ValTy>
  872. class value_constructor
  873. {
  874. public:
  875. using value_type = _ValTy;
  876. template <typename _Ty>
  877. using allocator_type = typename value_type::template allocator_type<_Ty>;
  878. template <value_constant::type _Ty>
  879. using type_constant = std::integral_constant<value_constant::type, _Ty>;
  880. template <value_constant::type _Ty, typename... _Args>
  881. static void reset(value_type& v, _Args&&... args)
  882. {
  883. destroy(v);
  884. v.type(_Ty);
  885. construct<_Ty>(v, std::forward<_Args>(args)...);
  886. }
  887. template <value_constant::type _Ty, typename... _Args>
  888. static inline void construct(value_type& v, _Args&&... args)
  889. {
  890. construct(type_constant<_Ty>{}, v, std::forward<_Args>(args)...);
  891. }
  892. static void destroy(value_type& v)
  893. {
  894. switch (v.type())
  895. {
  896. case value_constant::object:
  897. destroy<typename value_type::object_type>(v.data().object);
  898. break;
  899. case value_constant::array:
  900. destroy<typename value_type::array_type>(v.data().vector);
  901. break;
  902. case value_constant::string:
  903. destroy<typename value_type::string_type>(v.data().string);
  904. break;
  905. default:
  906. break;
  907. }
  908. }
  909. private:
  910. template <typename... _Args>
  911. static inline void construct(type_constant<value_constant::object>, value_type& v, _Args&&... args)
  912. {
  913. v.data().object = create_data<typename value_type::object_type>(std::forward<_Args>(args)...);
  914. }
  915. template <typename... _Args>
  916. static inline void construct(type_constant<value_constant::array>, value_type& v, _Args&&... args)
  917. {
  918. v.data().vector = create_data<typename value_type::array_type>(std::forward<_Args>(args)...);
  919. }
  920. template <typename... _Args>
  921. static inline void construct(type_constant<value_constant::string>, value_type& v, _Args&&... args)
  922. {
  923. v.data().string = create_data<typename value_type::string_type>(std::forward<_Args>(args)...);
  924. }
  925. template <typename... _Args>
  926. static inline void construct(type_constant<value_constant::integer>, value_type& v, _Args&&... args)
  927. {
  928. v.data().integer = typename value_type::integer_type{ std::forward<_Args>(args)... };
  929. }
  930. template <typename... _Args>
  931. static inline void construct(type_constant<value_constant::floating>, value_type& v, _Args&&... args)
  932. {
  933. v.data().floating = typename value_type::float_type{ std::forward<_Args>(args)... };
  934. }
  935. template <typename... _Args>
  936. static inline void construct(type_constant<value_constant::boolean>, value_type& v, _Args&&... args)
  937. {
  938. v.data().boolean = typename value_type::boolean_type{ std::forward<_Args>(args)... };
  939. }
  940. template <typename... _Args>
  941. static inline void construct(type_constant<value_constant::null>, value_type& v, _Args&&... args)
  942. {
  943. ((void)v);
  944. }
  945. template <typename _Ty, typename... _Args>
  946. static _Ty* create_data(_Args&&... args)
  947. {
  948. using allocator_traits = std::allocator_traits<allocator_type<_Ty>>;
  949. static allocator_type<_Ty> allocator;
  950. auto ptr = allocator_traits::allocate(allocator, 1);
  951. allocator_traits::construct(allocator, ptr, std::forward<_Args>(args)...);
  952. return ptr;
  953. }
  954. template <typename _Ty>
  955. static void destroy(_Ty* ptr)
  956. {
  957. using allocator_traits = std::allocator_traits<allocator_type<_Ty>>;
  958. static allocator_type<_Ty> allocator;
  959. allocator_traits::destroy(allocator, ptr);
  960. allocator_traits::deallocate(allocator, ptr, 1);
  961. }
  962. };
  963. template <typename _ValTy>
  964. class value_maker
  965. {
  966. public:
  967. using value_type = _ValTy;
  968. struct object
  969. {
  970. using pair_type = std::pair<typename value_type::string_type, value_type>;
  971. object(std::initializer_list<pair_type> list)
  972. : list_(list)
  973. {
  974. }
  975. operator value_type() const
  976. {
  977. value_type v{ value_constant::object };
  978. std::for_each(list_.begin(), list_.end(),
  979. [&](const pair_type& pair) { v.data().object->emplace(pair.first, pair.second); });
  980. return v;
  981. }
  982. private:
  983. std::initializer_list<pair_type> list_;
  984. };
  985. struct array
  986. {
  987. array(std::initializer_list<value_type> list)
  988. : list_(list)
  989. {
  990. }
  991. operator value_type() const
  992. {
  993. value_type v{ value_constant::array };
  994. v.data().vector->reserve(list_.size());
  995. v.data().vector->assign(list_.begin(), list_.end());
  996. return v;
  997. }
  998. private:
  999. std::initializer_list<value_type> list_;
  1000. };
  1001. };
  1002. } // namespace detail
  1003. template <typename _ValTy>
  1004. inline _ValTy make_object(std::initializer_list<std::pair<typename _ValTy::string_type, _ValTy>> list)
  1005. {
  1006. return typename detail::value_maker<_ValTy>::object{ list };
  1007. }
  1008. template <typename _ValTy>
  1009. inline _ValTy make_array(std::initializer_list<_ValTy> list)
  1010. {
  1011. return typename detail::value_maker<_ValTy>::array{ list };
  1012. }
  1013. } // namespace configor