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