value_ref.ipp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/json
  8. //
  9. #ifndef BOOST_JSON_IMPL_VALUE_REF_IPP
  10. #define BOOST_JSON_IMPL_VALUE_REF_IPP
  11. #include <boost/json/value_ref.hpp>
  12. #include <boost/json/array.hpp>
  13. #include <boost/json/value.hpp>
  14. BOOST_JSON_NS_BEGIN
  15. value_ref::
  16. operator
  17. value() const
  18. {
  19. return make_value({});
  20. }
  21. value
  22. value_ref::
  23. from_init_list(
  24. void const* p,
  25. storage_ptr sp)
  26. {
  27. return make_value(
  28. *reinterpret_cast<
  29. init_list const*>(p),
  30. std::move(sp));
  31. }
  32. bool
  33. value_ref::
  34. is_key_value_pair() const noexcept
  35. {
  36. if(what_ != what::ini)
  37. return false;
  38. if(arg_.init_list_.size() != 2)
  39. return false;
  40. auto const& e =
  41. *arg_.init_list_.begin();
  42. if( e.what_ != what::str &&
  43. e.what_ != what::strfunc)
  44. return false;
  45. return true;
  46. }
  47. bool
  48. value_ref::
  49. maybe_object(
  50. std::initializer_list<
  51. value_ref> init) noexcept
  52. {
  53. for(auto const& e : init)
  54. if(! e.is_key_value_pair())
  55. return false;
  56. return true;
  57. }
  58. string_view
  59. value_ref::
  60. get_string() const noexcept
  61. {
  62. BOOST_ASSERT(
  63. what_ == what::str ||
  64. what_ == what::strfunc);
  65. if (what_ == what::strfunc)
  66. return *static_cast<const string*>(f_.p);
  67. return arg_.str_;
  68. }
  69. value
  70. value_ref::
  71. make_value(
  72. storage_ptr sp) const
  73. {
  74. switch(what_)
  75. {
  76. default:
  77. case what::str:
  78. return string(
  79. arg_.str_,
  80. std::move(sp));
  81. case what::ini:
  82. return make_value(
  83. arg_.init_list_,
  84. std::move(sp));
  85. case what::func:
  86. return f_.f(f_.p,
  87. std::move(sp));
  88. case what::strfunc:
  89. return f_.f(f_.p,
  90. std::move(sp));
  91. case what::cfunc:
  92. return cf_.f(cf_.p,
  93. std::move(sp));
  94. }
  95. }
  96. value
  97. value_ref::
  98. make_value(
  99. std::initializer_list<
  100. value_ref> init,
  101. storage_ptr sp)
  102. {
  103. if(maybe_object(init))
  104. return make_object(
  105. init, std::move(sp));
  106. return make_array(
  107. init, std::move(sp));
  108. }
  109. object
  110. value_ref::
  111. make_object(
  112. std::initializer_list<value_ref> init,
  113. storage_ptr sp)
  114. {
  115. object obj(std::move(sp));
  116. obj.reserve(init.size());
  117. for(auto const& e : init)
  118. obj.emplace(
  119. e.arg_.init_list_.begin()[0].get_string(),
  120. e.arg_.init_list_.begin()[1].make_value(
  121. obj.storage()));
  122. return obj;
  123. }
  124. array
  125. value_ref::
  126. make_array(
  127. std::initializer_list<
  128. value_ref> init,
  129. storage_ptr sp)
  130. {
  131. array arr(std::move(sp));
  132. arr.reserve(init.size());
  133. for(auto const& e : init)
  134. arr.emplace_back(
  135. e.make_value(
  136. arr.storage()));
  137. return arr;
  138. }
  139. void
  140. value_ref::
  141. write_array(
  142. value* dest,
  143. std::initializer_list<
  144. value_ref> init,
  145. storage_ptr const& sp)
  146. {
  147. struct undo
  148. {
  149. value* const base;
  150. value* pos;
  151. ~undo()
  152. {
  153. if(pos)
  154. while(pos > base)
  155. (--pos)->~value();
  156. }
  157. };
  158. undo u{dest, dest};
  159. for(auto const& e : init)
  160. {
  161. ::new(u.pos) value(
  162. e.make_value(sp));
  163. ++u.pos;
  164. }
  165. u.pos = nullptr;
  166. }
  167. BOOST_JSON_NS_END
  168. #endif