serializer.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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/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 @ref memory_resource
  124. to use when producing partial output.
  125. Shared ownership of the memory resource
  126. is retained until the serializer is
  127. destroyed.
  128. @param buf An optional static buffer to
  129. use for temporary storage when producing
  130. partial output.
  131. @param buf_size The number of bytes of
  132. valid memory pointed to by `buf`.
  133. @param opts The options for the serializer. If this parameter
  134. is omitted, the serializer will output only standard JSON.
  135. */
  136. BOOST_JSON_DECL
  137. serializer(
  138. storage_ptr sp,
  139. unsigned char* buf = nullptr,
  140. std::size_t buf_size = 0,
  141. serialize_options const& opts = {}) noexcept;
  142. /** Returns `true` if the serialization is complete
  143. This function returns `true` when all of the
  144. characters in the serialized representation of
  145. the value have been read.
  146. @par Complexity
  147. Constant.
  148. @par Exception Safety
  149. No-throw guarantee.
  150. */
  151. bool
  152. done() const noexcept
  153. {
  154. return done_;
  155. }
  156. /** Reset the serializer for a new element
  157. This function prepares the serializer to emit
  158. a new serialized JSON representing `*p`.
  159. Any internally allocated memory is
  160. preserved and re-used for the new output.
  161. @param p A pointer to the element to serialize.
  162. Ownership is not transferred; The caller is
  163. responsible for ensuring that the lifetime of
  164. `*p` extends until it is no longer needed.
  165. */
  166. /** @{ */
  167. BOOST_JSON_DECL
  168. void
  169. reset(value const* p) noexcept;
  170. BOOST_JSON_DECL
  171. void
  172. reset(array const* p) noexcept;
  173. BOOST_JSON_DECL
  174. void
  175. reset(object const* p) noexcept;
  176. BOOST_JSON_DECL
  177. void
  178. reset(string const* p) noexcept;
  179. /** @} */
  180. /** Reset the serializer for a new string
  181. This function prepares the serializer to emit
  182. a new serialized JSON representing the string.
  183. Any internally allocated memory is
  184. preserved and re-used for the new output.
  185. @param sv The characters representing the string.
  186. Ownership is not transferred; The caller is
  187. responsible for ensuring that the lifetime of
  188. the characters reference by `sv` extends
  189. until it is no longer needed.
  190. */
  191. BOOST_JSON_DECL
  192. void
  193. reset(string_view sv) noexcept;
  194. /** Read the next buffer of serialized JSON
  195. This function attempts to fill the caller
  196. provided buffer starting at `dest` with
  197. up to `size` characters of the serialized
  198. JSON that represents the value. If the
  199. buffer is not large enough, multiple calls
  200. may be required.
  201. \n
  202. If serialization completes during this call;
  203. that is, that all of the characters belonging
  204. to the serialized value have been written to
  205. caller-provided buffers, the function
  206. @ref done will return `true`.
  207. @par Preconditions
  208. @code
  209. this->done() == false
  210. @endcode
  211. @par Complexity
  212. Linear in `size`.
  213. @par Exception Safety
  214. Basic guarantee.
  215. Calls to `memory_resource::allocate` may throw.
  216. @return A @ref string_view containing the
  217. characters written, which may be less than
  218. `size`.
  219. @param dest A pointer to valid memory of at
  220. least `size` bytes.
  221. @param size The maximum number of characters
  222. to write to the memory pointed to by `dest`.
  223. */
  224. BOOST_JSON_DECL
  225. string_view
  226. read(char* dest, std::size_t size);
  227. /** Read the next buffer of serialized JSON
  228. This function allows reading into a
  229. character array, with a deduced maximum size.
  230. @par Preconditions
  231. @code
  232. this->done() == false
  233. @endcode
  234. @par Effects
  235. @code
  236. return this->read( dest, N );
  237. @endcode
  238. @par Complexity
  239. Linear in `N`.
  240. @par Exception Safety
  241. Basic guarantee.
  242. Calls to `memory_resource::allocate` may throw.
  243. @return A @ref string_view containing the
  244. characters written, which may be less than
  245. `size`.
  246. @param dest The character array to write to.
  247. */
  248. template<std::size_t N>
  249. string_view
  250. read(char(&dest)[N])
  251. {
  252. return read(dest, N);
  253. }
  254. #ifndef BOOST_JSON_DOCS
  255. // Safety net for accidental buffer overflows
  256. template<std::size_t N>
  257. string_view
  258. read(char(&dest)[N], std::size_t n)
  259. {
  260. // If this goes off, check your parameters
  261. // closely, chances are you passed an array
  262. // thinking it was a pointer.
  263. BOOST_ASSERT(n <= N);
  264. return read(dest, n);
  265. }
  266. #endif
  267. };
  268. } // namespace json
  269. } // namespace boost
  270. #endif