serializer.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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_SERIALIZER_HPP
  10. #define BOOST_JSON_SERIALIZER_HPP
  11. #include <boost/json/detail/config.hpp>
  12. #include <boost/json/value.hpp>
  13. #include <boost/json/detail/format.hpp>
  14. #include <boost/json/detail/stack.hpp>
  15. #include <boost/json/detail/stream.hpp>
  16. namespace boost {
  17. namespace json {
  18. /** A serializer for JSON.
  19. This class traverses an instance of a library
  20. type and emits serialized JSON text by filling
  21. in one or more caller-provided buffers. To use,
  22. declare a variable and call @ref reset with
  23. a pointer to the variable you want to serialize.
  24. Then call @ref read over and over until
  25. @ref done returns `true`.
  26. @par Example
  27. This demonstrates how the serializer may
  28. be used to print a JSON value to an output
  29. stream.
  30. @code
  31. void print( std::ostream& os, value const& jv)
  32. {
  33. serializer sr;
  34. sr.reset( &jv );
  35. while( ! sr.done() )
  36. {
  37. char buf[ 4000 ];
  38. os << sr.read( buf );
  39. }
  40. }
  41. @endcode
  42. @par Thread Safety
  43. The same instance may not be accessed concurrently.
  44. */
  45. class serializer
  46. {
  47. enum class state : char;
  48. // VFALCO Too many streams
  49. using stream = detail::stream;
  50. using const_stream = detail::const_stream;
  51. using local_stream = detail::local_stream;
  52. using local_const_stream =
  53. detail::local_const_stream;
  54. using fn_t = bool (serializer::*)(stream&);
  55. #ifndef BOOST_JSON_DOCS
  56. union
  57. {
  58. value const* pv_;
  59. array const* pa_;
  60. object const* po_;
  61. };
  62. #endif
  63. fn_t fn0_ = &serializer::write_null<true>;
  64. fn_t fn1_ = &serializer::write_null<false>;
  65. value const* jv_ = nullptr;
  66. detail::stack st_;
  67. const_stream cs0_;
  68. char buf_[detail::max_number_chars + 1];
  69. bool done_ = false;
  70. inline bool suspend(state st);
  71. inline bool suspend(
  72. state st, array::const_iterator it, array const* pa);
  73. inline bool suspend(
  74. state st, object::const_iterator it, object const* po);
  75. template<bool StackEmpty> bool write_null (stream& ss);
  76. template<bool StackEmpty> bool write_true (stream& ss);
  77. template<bool StackEmpty> bool write_false (stream& ss);
  78. template<bool StackEmpty> bool write_string (stream& ss);
  79. template<bool StackEmpty> bool write_number (stream& ss);
  80. template<bool StackEmpty> bool write_array (stream& ss);
  81. template<bool StackEmpty> bool write_object (stream& ss);
  82. template<bool StackEmpty> bool write_value (stream& ss);
  83. inline string_view read_some(char* dest, std::size_t size);
  84. public:
  85. /// Move constructor (deleted)
  86. serializer(serializer&&) = delete;
  87. /** Destructor
  88. All temporary storage is deallocated.
  89. @par Complexity
  90. Constant
  91. @par Exception Safety
  92. No-throw guarantee.
  93. */
  94. BOOST_JSON_DECL
  95. ~serializer() noexcept;
  96. /** Constructor
  97. This constructs a serializer with no value.
  98. The value may be set later by calling @ref reset.
  99. If serialization is attempted with no value,
  100. the output is as if a null value is serialized.
  101. @par Complexity
  102. Constant.
  103. @par Exception Safety
  104. No-throw guarantee.
  105. */
  106. BOOST_JSON_DECL
  107. serializer() noexcept;
  108. /** Constructor
  109. This constructs a serializer with no value.
  110. The value may be set later by calling @ref reset.
  111. If serialization is attempted with no value,
  112. the output is as if a null value is serialized.
  113. @par Complexity
  114. Constant.
  115. @par Exception Safety
  116. No-throw guarantee.
  117. @param sp A pointer to the @ref memory_resource
  118. to use when producing partial output.
  119. Shared ownership of the memory resource
  120. is retained until the serializer is
  121. destroyed.
  122. @param buf An optional static buffer to
  123. use for temporary storage when producing
  124. partial output.
  125. @param buf_size The number of bytes of
  126. valid memory pointed to by `buf`.
  127. */
  128. BOOST_JSON_DECL
  129. serializer(
  130. storage_ptr sp,
  131. unsigned char* buf = nullptr,
  132. std::size_t buf_size = 0) noexcept;
  133. /** Returns `true` if the serialization is complete
  134. This function returns `true` when all of the
  135. characters in the serialized representation of
  136. the value have been read.
  137. @par Complexity
  138. Constant.
  139. @par Exception Safety
  140. No-throw guarantee.
  141. */
  142. bool
  143. done() const noexcept
  144. {
  145. return done_;
  146. }
  147. /** Reset the serializer for a new element
  148. This function prepares the serializer to emit
  149. a new serialized JSON representing `*p`.
  150. Any internally allocated memory is
  151. preserved and re-used for the new output.
  152. @param p A pointer to the element to serialize.
  153. Ownership is not transferred; The caller is
  154. responsible for ensuring that the lifetime of
  155. `*p` extends until it is no longer needed.
  156. */
  157. /** @{ */
  158. BOOST_JSON_DECL
  159. void
  160. reset(value const* p) noexcept;
  161. BOOST_JSON_DECL
  162. void
  163. reset(array const* p) noexcept;
  164. BOOST_JSON_DECL
  165. void
  166. reset(object const* p) noexcept;
  167. BOOST_JSON_DECL
  168. void
  169. reset(string const* p) noexcept;
  170. /** @} */
  171. /** Reset the serializer for a new string
  172. This function prepares the serializer to emit
  173. a new serialized JSON representing the string.
  174. Any internally allocated memory is
  175. preserved and re-used for the new output.
  176. @param sv The characters representing the string.
  177. Ownership is not transferred; The caller is
  178. responsible for ensuring that the lifetime of
  179. the characters reference by `sv` extends
  180. until it is no longer needed.
  181. */
  182. BOOST_JSON_DECL
  183. void
  184. reset(string_view sv) noexcept;
  185. /** Read the next buffer of serialized JSON
  186. This function attempts to fill the caller
  187. provided buffer starting at `dest` with
  188. up to `size` characters of the serialized
  189. JSON that represents the value. If the
  190. buffer is not large enough, multiple calls
  191. may be required.
  192. \n
  193. If serialization completes during this call;
  194. that is, that all of the characters belonging
  195. to the serialized value have been written to
  196. caller-provided buffers, the function
  197. @ref done will return `true`.
  198. @par Preconditions
  199. @code
  200. this->done() == false
  201. @endcode
  202. @par Complexity
  203. Linear in `size`.
  204. @par Exception Safety
  205. Basic guarantee.
  206. Calls to `memory_resource::allocate` may throw.
  207. @return A @ref string_view containing the
  208. characters written, which may be less than
  209. `size`.
  210. @param dest A pointer to valid memory of at
  211. least `size` bytes.
  212. @param size The maximum number of characters
  213. to write to the memory pointed to by `dest`.
  214. */
  215. BOOST_JSON_DECL
  216. string_view
  217. read(char* dest, std::size_t size);
  218. /** Read the next buffer of serialized JSON
  219. This function allows reading into a
  220. character array, with a deduced maximum size.
  221. @par Preconditions
  222. @code
  223. this->done() == false
  224. @endcode
  225. @par Effects
  226. @code
  227. return this->read( dest, N );
  228. @endcode
  229. @par Complexity
  230. Linear in `N`.
  231. @par Exception Safety
  232. Basic guarantee.
  233. Calls to `memory_resource::allocate` may throw.
  234. @return A @ref string_view containing the
  235. characters written, which may be less than
  236. `size`.
  237. @param dest The character array to write to.
  238. */
  239. template<std::size_t N>
  240. string_view
  241. read(char(&dest)[N])
  242. {
  243. return read(dest, N);
  244. }
  245. #ifndef BOOST_JSON_DOCS
  246. // Safety net for accidental buffer overflows
  247. template<std::size_t N>
  248. string_view
  249. read(char(&dest)[N], std::size_t n)
  250. {
  251. // If this goes off, check your parameters
  252. // closely, chances are you passed an array
  253. // thinking it was a pointer.
  254. BOOST_ASSERT(n <= N);
  255. return read(dest, n);
  256. }
  257. #endif
  258. };
  259. } // namespace json
  260. } // namespace boost
  261. #endif