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