1#ifndef SIMDJSON_SERIALIZATION_H
2#define SIMDJSON_SERIALIZATION_H
3
4#include "simdjson/common_defs.h"
5#include "simdjson/dom/document.h"
6#include "simdjson/error.h"
7#include "simdjson/internal/dom_parser_implementation.h"
8#include "simdjson/internal/tape_ref.h"
9#include "simdjson/padded_string.h"
10#include "simdjson/portability.h"
11#include <vector>
12
13namespace simdjson {
14
15/**
16 * The string_builder template and mini_formatter class
17 * are not part of our public API and are subject to change
18 * at any time!
19 */
20namespace internal {
21
22class mini_formatter;
23
24/**
25 * @private The string_builder template allows us to construct
26 * a string from a document element. It is parametrized
27 * by a "formatter" which handles the details. Thus
28 * the string_builder template could support both minification
29 * and prettification, and various other tradeoffs.
30 */
31template <class formatter = mini_formatter>
32class string_builder {
33public:
34 /** Construct an initially empty builder, would print the empty string **/
35 string_builder() = default;
36 /** Append an element to the builder (to be printed) **/
37 inline void append(simdjson::dom::element value);
38 /** Append an array to the builder (to be printed) **/
39 inline void append(simdjson::dom::array value);
40 /** Append an object to the builder (to be printed) **/
41 inline void append(simdjson::dom::object value);
42 /** Reset the builder (so that it would print the empty string) **/
43 simdjson_inline void clear();
44 /**
45 * Get access to the string. The string_view is owned by the builder
46 * and it is invalid to use it after the string_builder has been
47 * destroyed.
48 * However you can make a copy of the string_view on memory that you
49 * own.
50 */
51 simdjson_inline std::string_view str() const;
52 /** Append a key_value_pair to the builder (to be printed) **/
53 simdjson_inline void append(simdjson::dom::key_value_pair value);
54private:
55 formatter format{};
56};
57
58/**
59 * @private This is the class that we expect to use with the string_builder
60 * template. It tries to produce a compact version of the JSON element
61 * as quickly as possible.
62 */
63class mini_formatter {
64public:
65 mini_formatter() = default;
66 /** Add a comma **/
67 simdjson_inline void comma();
68 /** Start an array, prints [ **/
69 simdjson_inline void start_array();
70 /** End an array, prints ] **/
71 simdjson_inline void end_array();
72 /** Start an array, prints { **/
73 simdjson_inline void start_object();
74 /** Start an array, prints } **/
75 simdjson_inline void end_object();
76 /** Prints a true **/
77 simdjson_inline void true_atom();
78 /** Prints a false **/
79 simdjson_inline void false_atom();
80 /** Prints a null **/
81 simdjson_inline void null_atom();
82 /** Prints a number **/
83 simdjson_inline void number(int64_t x);
84 /** Prints a number **/
85 simdjson_inline void number(uint64_t x);
86 /** Prints a number **/
87 simdjson_inline void number(double x);
88 /** Prints a key (string + colon) **/
89 simdjson_inline void key(std::string_view unescaped);
90 /** Prints a string. The string is escaped as needed. **/
91 simdjson_inline void string(std::string_view unescaped);
92 /** Clears out the content. **/
93 simdjson_inline void clear();
94 /**
95 * Get access to the buffer, it is owned by the instance, but
96 * the user can make a copy.
97 **/
98 simdjson_inline std::string_view str() const;
99
100private:
101 // implementation details (subject to change)
102 /** Prints one character **/
103 simdjson_inline void one_char(char c);
104 /** Backing buffer **/
105 std::vector<char> buffer{}; // not ideal!
106};
107
108} // internal
109
110namespace dom {
111
112/**
113 * Print JSON to an output stream.
114 *
115 * @param out The output stream.
116 * @param value The element.
117 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
118 */
119inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
120 simdjson::internal::string_builder<> sb;
121 sb.append(value);
122 return (out << sb.str());
123}
124#if SIMDJSON_EXCEPTIONS
125inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
126 if (x.error()) { throw simdjson::simdjson_error(x.error()); }
127 return (out << x.value());
128}
129#endif
130/**
131 * Print JSON to an output stream.
132 *
133 * @param out The output stream.
134 * @param value The array.
135 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
136 */
137inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
138 simdjson::internal::string_builder<> sb;
139 sb.append(value);
140 return (out << sb.str());
141}
142#if SIMDJSON_EXCEPTIONS
143inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
144 if (x.error()) { throw simdjson::simdjson_error(x.error()); }
145 return (out << x.value());
146}
147#endif
148/**
149 * Print JSON to an output stream.
150 *
151 * @param out The output stream.
152 * @param value The object.
153 * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
154 */
155inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
156 simdjson::internal::string_builder<> sb;
157 sb.append(value);
158 return (out << sb.str());
159}
160#if SIMDJSON_EXCEPTIONS
161inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
162 if (x.error()) { throw simdjson::simdjson_error(x.error()); }
163 return (out << x.value());
164}
165#endif
166} // namespace dom
167
168/**
169 * Converts JSON to a string.
170 *
171 * dom::parser parser;
172 * element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
173 * cout << to_string(doc) << endl; // prints [1,2,3]
174 *
175 */
176template <class T>
177std::string to_string(T x) {
178 // in C++, to_string is standard: http://www.cplusplus.com/reference/string/to_string/
179 // Currently minify and to_string are identical but in the future, they may
180 // differ.
181 simdjson::internal::string_builder<> sb;
182 sb.append(x);
183 std::string_view answer = sb.str();
184 return std::string(answer.data(), answer.size());
185}
186#if SIMDJSON_EXCEPTIONS
187template <class T>
188std::string to_string(simdjson_result<T> x) {
189 if (x.error()) { throw simdjson_error(x.error()); }
190 return to_string(x.value());
191}
192#endif
193
194/**
195 * Minifies a JSON element or document, printing the smallest possible valid JSON.
196 *
197 * dom::parser parser;
198 * element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
199 * cout << minify(doc) << endl; // prints [1,2,3]
200 *
201 */
202template <class T>
203std::string minify(T x) {
204 return to_string(x);
205}
206
207#if SIMDJSON_EXCEPTIONS
208template <class T>
209std::string minify(simdjson_result<T> x) {
210 if (x.error()) { throw simdjson_error(x.error()); }
211 return to_string(x.value());
212}
213#endif
214
215
216} // namespace simdjson
217
218
219#endif
220