value_ref.ipp 3.4 KB

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