1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_IMPL_SERIALIZE_IPP
10  
#ifndef BOOST_JSON_IMPL_SERIALIZE_IPP
11  
#define BOOST_JSON_IMPL_SERIALIZE_IPP
11  
#define BOOST_JSON_IMPL_SERIALIZE_IPP
12  

12  

13  
#include <boost/json/serialize.hpp>
13  
#include <boost/json/serialize.hpp>
14  
#include <boost/json/serializer.hpp>
14  
#include <boost/json/serializer.hpp>
15  
#include <ostream>
15  
#include <ostream>
16  

16  

17  
namespace boost {
17  
namespace boost {
18  
namespace json {
18  
namespace json {
19  

19  

20  
namespace {
20  
namespace {
21  

21  

22  
int serialize_xalloc = std::ios::xalloc();
22  
int serialize_xalloc = std::ios::xalloc();
23  

23  

24  
enum class serialize_stream_flags : long
24  
enum class serialize_stream_flags : long
25  
{
25  
{
26  
    allow_infinity_and_nan = 1,
26  
    allow_infinity_and_nan = 1,
27  
};
27  
};
28  

28  

29  
std::underlying_type<serialize_stream_flags>::type
29  
std::underlying_type<serialize_stream_flags>::type
30  
to_bitmask( serialize_options const& opts )
30  
to_bitmask( serialize_options const& opts )
31  
{
31  
{
32  
    using E = serialize_stream_flags;
32  
    using E = serialize_stream_flags;
33  
    using I = std::underlying_type<E>::type;
33  
    using I = std::underlying_type<E>::type;
34  
    return (opts.allow_infinity_and_nan
34  
    return (opts.allow_infinity_and_nan
35  
        ? static_cast<I>(E::allow_infinity_and_nan) : 0);
35  
        ? static_cast<I>(E::allow_infinity_and_nan) : 0);
36  
}
36  
}
37  

37  

38  
serialize_options
38  
serialize_options
39  
get_stream_flags( std::ostream& os )
39  
get_stream_flags( std::ostream& os )
40  
{
40  
{
41  
    auto const flags = os.iword(serialize_xalloc);
41  
    auto const flags = os.iword(serialize_xalloc);
42  

42  

43  
    serialize_options opts;
43  
    serialize_options opts;
44  
    using E = serialize_stream_flags;
44  
    using E = serialize_stream_flags;
45  
    using I = std::underlying_type<E>::type;
45  
    using I = std::underlying_type<E>::type;
46  
    opts.allow_infinity_and_nan =
46  
    opts.allow_infinity_and_nan =
47  
        flags & static_cast<I>(E::allow_infinity_and_nan);
47  
        flags & static_cast<I>(E::allow_infinity_and_nan);
48  
    return opts;
48  
    return opts;
49  
}
49  
}
50  

50  

51  
} // namespace
51  
} // namespace
52  

52  

53  
namespace detail {
53  
namespace detail {
54  

54  

55  
void
55  
void
56  
serialize_impl(
56  
serialize_impl(
57  
    std::string& s,
57  
    std::string& s,
58  
    serializer& sr)
58  
    serializer& sr)
59  
{
59  
{
60  
    // serialize to a small buffer to avoid
60  
    // serialize to a small buffer to avoid
61  
    // the first few allocations in std::string
61  
    // the first few allocations in std::string
62  
    char buf[BOOST_JSON_STACK_BUFFER_SIZE];
62  
    char buf[BOOST_JSON_STACK_BUFFER_SIZE];
63  
    string_view sv;
63  
    string_view sv;
64  
    sv = sr.read(buf);
64  
    sv = sr.read(buf);
65  
    if(sr.done())
65  
    if(sr.done())
66  
    {
66  
    {
67  
        // fast path
67  
        // fast path
68  
        s.append(
68  
        s.append(
69  
            sv.data(), sv.size());
69  
            sv.data(), sv.size());
70  
        return;
70  
        return;
71  
    }
71  
    }
72  
    std::size_t len = sv.size();
72  
    std::size_t len = sv.size();
73  
    s.reserve(len * 2);
73  
    s.reserve(len * 2);
74  
    s.resize(s.capacity());
74  
    s.resize(s.capacity());
75  
    BOOST_ASSERT(
75  
    BOOST_ASSERT(
76  
        s.size() >= len * 2);
76  
        s.size() >= len * 2);
77  
    std::memcpy(&s[0],
77  
    std::memcpy(&s[0],
78  
        sv.data(), sv.size());
78  
        sv.data(), sv.size());
79  
    auto const lim =
79  
    auto const lim =
80  
        s.max_size() / 2;
80  
        s.max_size() / 2;
81  
    for(;;)
81  
    for(;;)
82  
    {
82  
    {
83  
        sv = sr.read(
83  
        sv = sr.read(
84  
            &s[0] + len,
84  
            &s[0] + len,
85  
            s.size() - len);
85  
            s.size() - len);
86  
        len += sv.size();
86  
        len += sv.size();
87  
        if(sr.done())
87  
        if(sr.done())
88  
            break;
88  
            break;
89  
        // growth factor 2x
89  
        // growth factor 2x
90  
        if(s.size() < lim)
90  
        if(s.size() < lim)
91  
            s.resize(s.size() * 2);
91  
            s.resize(s.size() * 2);
92  
        else
92  
        else
93  
            s.resize(2 * lim);
93  
            s.resize(2 * lim);
94  
    }
94  
    }
95  
    s.resize(len);
95  
    s.resize(len);
96  
}
96  
}
97  

97  

98  
} // namespace detail
98  
} // namespace detail
99  

99  

100  
std::string
100  
std::string
101  
serialize(
101  
serialize(
102  
    value const& jv,
102  
    value const& jv,
103  
    serialize_options const& opts)
103  
    serialize_options const& opts)
104  
{
104  
{
105  
    unsigned char buf[256];
105  
    unsigned char buf[256];
106  
    serializer sr(
106  
    serializer sr(
107  
        storage_ptr(),
107  
        storage_ptr(),
108  
        buf,
108  
        buf,
109  
        sizeof(buf),
109  
        sizeof(buf),
110  
        opts);
110  
        opts);
111  
    sr.reset(&jv);
111  
    sr.reset(&jv);
112  
    std::string s;
112  
    std::string s;
113  
    serialize_impl(s, sr);
113  
    serialize_impl(s, sr);
114  
    return s;
114  
    return s;
115  
}
115  
}
116  

116  

117  
std::string
117  
std::string
118  
serialize(
118  
serialize(
119  
    array const& arr,
119  
    array const& arr,
120  
    serialize_options const& opts)
120  
    serialize_options const& opts)
121  
{
121  
{
122  
    unsigned char buf[256];
122  
    unsigned char buf[256];
123  
    serializer sr(
123  
    serializer sr(
124  
        storage_ptr(),
124  
        storage_ptr(),
125  
        buf,
125  
        buf,
126  
        sizeof(buf),
126  
        sizeof(buf),
127  
        opts);
127  
        opts);
128  
    std::string s;
128  
    std::string s;
129  
    sr.reset(&arr);
129  
    sr.reset(&arr);
130  
    serialize_impl(s, sr);
130  
    serialize_impl(s, sr);
131  
    return s;
131  
    return s;
132  
}
132  
}
133  

133  

134  
std::string
134  
std::string
135  
serialize(
135  
serialize(
136  
    object const& obj,
136  
    object const& obj,
137  
    serialize_options const& opts)
137  
    serialize_options const& opts)
138  
{
138  
{
139  
    unsigned char buf[256];
139  
    unsigned char buf[256];
140  
    serializer sr(
140  
    serializer sr(
141  
        storage_ptr(),
141  
        storage_ptr(),
142  
        buf,
142  
        buf,
143  
        sizeof(buf),
143  
        sizeof(buf),
144  
        opts);
144  
        opts);
145  
    std::string s;
145  
    std::string s;
146  
    sr.reset(&obj);
146  
    sr.reset(&obj);
147  
    serialize_impl(s, sr);
147  
    serialize_impl(s, sr);
148  
    return s;
148  
    return s;
149  
}
149  
}
150  

150  

151  
std::string
151  
std::string
152  
serialize(
152  
serialize(
153  
    string const& str,
153  
    string const& str,
154  
    serialize_options const& opts)
154  
    serialize_options const& opts)
155  
{
155  
{
156  
    return serialize( str.subview(), opts );
156  
    return serialize( str.subview(), opts );
157  
}
157  
}
158  

158  

159  
// this is here for key_value_pair::key()
159  
// this is here for key_value_pair::key()
160  
std::string
160  
std::string
161  
serialize(
161  
serialize(
162  
    string_view sv,
162  
    string_view sv,
163  
    serialize_options const& opts)
163  
    serialize_options const& opts)
164  
{
164  
{
165  
    unsigned char buf[256];
165  
    unsigned char buf[256];
166  
    serializer sr(
166  
    serializer sr(
167  
        storage_ptr(),
167  
        storage_ptr(),
168  
        buf,
168  
        buf,
169  
        sizeof(buf),
169  
        sizeof(buf),
170  
        opts);
170  
        opts);
171  
    std::string s;
171  
    std::string s;
172  
    sr.reset(sv);
172  
    sr.reset(sv);
173  
    serialize_impl(s, sr);
173  
    serialize_impl(s, sr);
174  
    return s;
174  
    return s;
175  
}
175  
}
176  

176  

177  
//----------------------------------------------------------
177  
//----------------------------------------------------------
178  

178  

179  
// tag::example_operator_lt_lt[]
179  
// tag::example_operator_lt_lt[]
180  
// Serialize a value into an output stream
180  
// Serialize a value into an output stream
181  

181  

182  
std::ostream&
182  
std::ostream&
183  
operator<<( std::ostream& os, value const& jv )
183  
operator<<( std::ostream& os, value const& jv )
184  
{
184  
{
185  
    // Create a serializer
185  
    // Create a serializer
186  
    serializer sr( get_stream_flags(os) );
186  
    serializer sr( get_stream_flags(os) );
187  

187  

188  
    // Set the serializer up for our value
188  
    // Set the serializer up for our value
189  
    sr.reset( &jv );
189  
    sr.reset( &jv );
190  

190  

191  
    // Loop until all output is produced.
191  
    // Loop until all output is produced.
192  
    while( ! sr.done() )
192  
    while( ! sr.done() )
193  
    {
193  
    {
194  
        // Use a local buffer to avoid allocation.
194  
        // Use a local buffer to avoid allocation.
195  
        char buf[ BOOST_JSON_STACK_BUFFER_SIZE ];
195  
        char buf[ BOOST_JSON_STACK_BUFFER_SIZE ];
196  

196  

197  
        // Fill our buffer with serialized characters and write it to the output stream.
197  
        // Fill our buffer with serialized characters and write it to the output stream.
198  
        os << sr.read( buf );
198  
        os << sr.read( buf );
199  
    }
199  
    }
200  

200  

201  
    return os;
201  
    return os;
202  
}
202  
}
203  
// end::example_operator_lt_lt[]
203  
// end::example_operator_lt_lt[]
204  

204  

205  
static
205  
static
206  
void
206  
void
207  
to_ostream(
207  
to_ostream(
208  
    std::ostream& os,
208  
    std::ostream& os,
209  
    serializer& sr)
209  
    serializer& sr)
210  
{
210  
{
211  
    while(! sr.done())
211  
    while(! sr.done())
212  
    {
212  
    {
213  
        char buf[BOOST_JSON_STACK_BUFFER_SIZE];
213  
        char buf[BOOST_JSON_STACK_BUFFER_SIZE];
214  
        auto s = sr.read(buf);
214  
        auto s = sr.read(buf);
215  
        os.write(s.data(), s.size());
215  
        os.write(s.data(), s.size());
216  
    }
216  
    }
217  
}
217  
}
218  

218  

219  
std::ostream&
219  
std::ostream&
220  
operator<<(
220  
operator<<(
221  
    std::ostream& os,
221  
    std::ostream& os,
222  
    array const& arr)
222  
    array const& arr)
223  
{
223  
{
224  
    serializer sr( get_stream_flags(os) );
224  
    serializer sr( get_stream_flags(os) );
225  
    sr.reset(&arr);
225  
    sr.reset(&arr);
226  
    to_ostream(os, sr);
226  
    to_ostream(os, sr);
227  
    return os;
227  
    return os;
228  
}
228  
}
229  

229  

230  
std::ostream&
230  
std::ostream&
231  
operator<<(
231  
operator<<(
232  
    std::ostream& os,
232  
    std::ostream& os,
233  
    object const& obj)
233  
    object const& obj)
234  
{
234  
{
235  
    serializer sr( get_stream_flags(os) );
235  
    serializer sr( get_stream_flags(os) );
236  
    sr.reset(&obj);
236  
    sr.reset(&obj);
237  
    to_ostream(os, sr);
237  
    to_ostream(os, sr);
238  
    return os;
238  
    return os;
239  
}
239  
}
240  

240  

241  
std::ostream&
241  
std::ostream&
242  
operator<<(
242  
operator<<(
243  
    std::ostream& os,
243  
    std::ostream& os,
244  
    string const& str)
244  
    string const& str)
245  
{
245  
{
246  
    serializer sr( get_stream_flags(os) );
246  
    serializer sr( get_stream_flags(os) );
247  
    sr.reset(&str);
247  
    sr.reset(&str);
248  
    to_ostream(os, sr);
248  
    to_ostream(os, sr);
249  
    return os;
249  
    return os;
250  
}
250  
}
251  

251  

252  
std::ostream&
252  
std::ostream&
253  
operator<<( std::ostream& os, serialize_options const& opts )
253  
operator<<( std::ostream& os, serialize_options const& opts )
254  
{
254  
{
255  
    os.iword(serialize_xalloc) = to_bitmask(opts);
255  
    os.iword(serialize_xalloc) = to_bitmask(opts);
256  
    return os;
256  
    return os;
257  
}
257  
}
258  

258  

259  
} // namespace json
259  
} // namespace json
260  
} // namespace boost
260  
} // namespace boost
261  

261  

262  
#endif
262  
#endif