impl/serialize.ipp

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