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