/src/boost/boost/json/impl/serialize.ipp
Line | Count | Source (jump to first uncovered line) |
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 | | |
10 | | #ifndef BOOST_JSON_IMPL_SERIALIZE_IPP |
11 | | #define BOOST_JSON_IMPL_SERIALIZE_IPP |
12 | | |
13 | | #include <boost/json/serialize.hpp> |
14 | | #include <boost/json/serializer.hpp> |
15 | | #include <ostream> |
16 | | |
17 | | namespace boost { |
18 | | namespace json { |
19 | | |
20 | | namespace { |
21 | | |
22 | | int serialize_xalloc = std::ios::xalloc(); |
23 | | |
24 | | enum class serialize_stream_flags : long |
25 | | { |
26 | | allow_infinity_and_nan = 1, |
27 | | }; |
28 | | |
29 | | std::underlying_type<serialize_stream_flags>::type |
30 | | to_bitmask( serialize_options const& opts ) |
31 | 0 | { |
32 | 0 | using E = serialize_stream_flags; |
33 | 0 | using I = std::underlying_type<E>::type; |
34 | 0 | return (opts.allow_infinity_and_nan |
35 | 0 | ? static_cast<I>(E::allow_infinity_and_nan) : 0); |
36 | 0 | } |
37 | | |
38 | | serialize_options |
39 | | get_stream_flags( std::ostream& os ) |
40 | 0 | { |
41 | 0 | auto const flags = os.iword(serialize_xalloc); |
42 | |
|
43 | 0 | serialize_options opts; |
44 | 0 | using E = serialize_stream_flags; |
45 | 0 | using I = std::underlying_type<E>::type; |
46 | 0 | opts.allow_infinity_and_nan = |
47 | 0 | flags & static_cast<I>(E::allow_infinity_and_nan); |
48 | 0 | return opts; |
49 | 0 | } |
50 | | |
51 | | } // namespace |
52 | | |
53 | | namespace detail { |
54 | | |
55 | | void |
56 | | serialize_impl( |
57 | | std::string& s, |
58 | | serializer& sr) |
59 | 7.46k | { |
60 | | // serialize to a small buffer to avoid |
61 | | // the first few allocations in std::string |
62 | 7.46k | char buf[BOOST_JSON_STACK_BUFFER_SIZE]; |
63 | 7.46k | string_view sv; |
64 | 7.46k | sv = sr.read(buf); |
65 | 7.46k | if(sr.done()) |
66 | 6.72k | { |
67 | | // fast path |
68 | 6.72k | s.append( |
69 | 6.72k | sv.data(), sv.size()); |
70 | 6.72k | return; |
71 | 6.72k | } |
72 | 747 | std::size_t len = sv.size(); |
73 | 747 | s.reserve(len * 2); |
74 | 747 | s.resize(s.capacity()); |
75 | 747 | BOOST_ASSERT( |
76 | 747 | s.size() >= len * 2); |
77 | 747 | std::memcpy(&s[0], |
78 | 747 | sv.data(), sv.size()); |
79 | 747 | auto const lim = |
80 | 747 | s.max_size() / 2; |
81 | 747 | for(;;) |
82 | 2.49k | { |
83 | 2.49k | sv = sr.read( |
84 | 2.49k | &s[0] + len, |
85 | 2.49k | s.size() - len); |
86 | 2.49k | len += sv.size(); |
87 | 2.49k | if(sr.done()) |
88 | 747 | break; |
89 | | // growth factor 2x |
90 | 1.75k | if(s.size() < lim) |
91 | 1.75k | s.resize(s.size() * 2); |
92 | 0 | else |
93 | 0 | s.resize(2 * lim); |
94 | 1.75k | } |
95 | 747 | s.resize(len); |
96 | 747 | } |
97 | | |
98 | | } // namespace detail |
99 | | |
100 | | std::string |
101 | | serialize( |
102 | | value const& jv, |
103 | | serialize_options const& opts) |
104 | 7.46k | { |
105 | 7.46k | unsigned char buf[256]; |
106 | 7.46k | serializer sr( |
107 | 7.46k | storage_ptr(), |
108 | 7.46k | buf, |
109 | 7.46k | sizeof(buf), |
110 | 7.46k | opts); |
111 | 7.46k | sr.reset(&jv); |
112 | 7.46k | std::string s; |
113 | 7.46k | serialize_impl(s, sr); |
114 | 7.46k | return s; |
115 | 7.46k | } |
116 | | |
117 | | std::string |
118 | | serialize( |
119 | | array const& arr, |
120 | | serialize_options const& opts) |
121 | 0 | { |
122 | 0 | unsigned char buf[256]; |
123 | 0 | serializer sr( |
124 | 0 | storage_ptr(), |
125 | 0 | buf, |
126 | 0 | sizeof(buf), |
127 | 0 | opts); |
128 | 0 | std::string s; |
129 | 0 | sr.reset(&arr); |
130 | 0 | serialize_impl(s, sr); |
131 | 0 | return s; |
132 | 0 | } |
133 | | |
134 | | std::string |
135 | | serialize( |
136 | | object const& obj, |
137 | | serialize_options const& opts) |
138 | 0 | { |
139 | 0 | unsigned char buf[256]; |
140 | 0 | serializer sr( |
141 | 0 | storage_ptr(), |
142 | 0 | buf, |
143 | 0 | sizeof(buf), |
144 | 0 | opts); |
145 | 0 | std::string s; |
146 | 0 | sr.reset(&obj); |
147 | 0 | serialize_impl(s, sr); |
148 | 0 | return s; |
149 | 0 | } |
150 | | |
151 | | std::string |
152 | | serialize( |
153 | | string const& str, |
154 | | serialize_options const& opts) |
155 | 0 | { |
156 | 0 | return serialize( str.subview(), opts ); |
157 | 0 | } |
158 | | |
159 | | // this is here for key_value_pair::key() |
160 | | std::string |
161 | | serialize( |
162 | | string_view sv, |
163 | | serialize_options const& opts) |
164 | 0 | { |
165 | 0 | unsigned char buf[256]; |
166 | 0 | serializer sr( |
167 | 0 | storage_ptr(), |
168 | 0 | buf, |
169 | 0 | sizeof(buf), |
170 | 0 | opts); |
171 | 0 | std::string s; |
172 | 0 | sr.reset(sv); |
173 | 0 | serialize_impl(s, sr); |
174 | 0 | return s; |
175 | 0 | } |
176 | | |
177 | | //---------------------------------------------------------- |
178 | | |
179 | | // tag::example_operator_lt_lt[] |
180 | | // Serialize a value into an output stream |
181 | | |
182 | | std::ostream& |
183 | | operator<<( std::ostream& os, value const& jv ) |
184 | 0 | { |
185 | | // Create a serializer |
186 | 0 | serializer sr( get_stream_flags(os) ); |
187 | | |
188 | | // Set the serializer up for our value |
189 | 0 | sr.reset( &jv ); |
190 | | |
191 | | // Loop until all output is produced. |
192 | 0 | while( ! sr.done() ) |
193 | 0 | { |
194 | | // Use a local buffer to avoid allocation. |
195 | 0 | char buf[ BOOST_JSON_STACK_BUFFER_SIZE ]; |
196 | | |
197 | | // Fill our buffer with serialized characters and write it to the output stream. |
198 | 0 | os << sr.read( buf ); |
199 | 0 | } |
200 | |
|
201 | 0 | return os; |
202 | 0 | } |
203 | | // end::example_operator_lt_lt[] |
204 | | |
205 | | static |
206 | | void |
207 | | to_ostream( |
208 | | std::ostream& os, |
209 | | serializer& sr) |
210 | 0 | { |
211 | 0 | while(! sr.done()) |
212 | 0 | { |
213 | 0 | char buf[BOOST_JSON_STACK_BUFFER_SIZE]; |
214 | 0 | auto s = sr.read(buf); |
215 | 0 | os.write(s.data(), s.size()); |
216 | 0 | } |
217 | 0 | } |
218 | | |
219 | | std::ostream& |
220 | | operator<<( |
221 | | std::ostream& os, |
222 | | array const& arr) |
223 | 0 | { |
224 | 0 | serializer sr( get_stream_flags(os) ); |
225 | 0 | sr.reset(&arr); |
226 | 0 | to_ostream(os, sr); |
227 | 0 | return os; |
228 | 0 | } |
229 | | |
230 | | std::ostream& |
231 | | operator<<( |
232 | | std::ostream& os, |
233 | | object const& obj) |
234 | 0 | { |
235 | 0 | serializer sr( get_stream_flags(os) ); |
236 | 0 | sr.reset(&obj); |
237 | 0 | to_ostream(os, sr); |
238 | 0 | return os; |
239 | 0 | } |
240 | | |
241 | | std::ostream& |
242 | | operator<<( |
243 | | std::ostream& os, |
244 | | string const& str) |
245 | 0 | { |
246 | 0 | serializer sr( get_stream_flags(os) ); |
247 | 0 | sr.reset(&str); |
248 | 0 | to_ostream(os, sr); |
249 | 0 | return os; |
250 | 0 | } |
251 | | |
252 | | std::ostream& |
253 | | operator<<( std::ostream& os, serialize_options const& opts ) |
254 | 0 | { |
255 | 0 | os.iword(serialize_xalloc) = to_bitmask(opts); |
256 | 0 | return os; |
257 | 0 | } |
258 | | |
259 | | } // namespace json |
260 | | } // namespace boost |
261 | | |
262 | | #endif |