serializer.hpp 8.9 KB

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