95.96% Lines (95/99)
100.00% Functions (14/14)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 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 | |||||
| HITCBC | 30 | 2 | to_bitmask( serialize_options const& opts ) | 30 | 2 | 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; | |||||
| HITCBC | 34 | 2 | return (opts.allow_infinity_and_nan | 34 | 2 | return (opts.allow_infinity_and_nan | ||
| HITCBC | 35 | 2 | ? static_cast<I>(E::allow_infinity_and_nan) : 0); | 35 | 2 | ? static_cast<I>(E::allow_infinity_and_nan) : 0); | ||
| 36 | } | 36 | } | |||||
| 37 | 37 | |||||||
| 38 | serialize_options | 38 | serialize_options | |||||
| HITCBC | 39 | 9 | get_stream_flags( std::ostream& os ) | 39 | 9 | get_stream_flags( std::ostream& os ) | ||
| 40 | { | 40 | { | |||||
| HITCBC | 41 | 9 | auto const flags = os.iword(serialize_xalloc); | 41 | 9 | auto const flags = os.iword(serialize_xalloc); | ||
| 42 | 42 | |||||||
| HITCBC | 43 | 9 | serialize_options opts; | 43 | 9 | 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; | |||||
| HITCBC | 46 | 9 | opts.allow_infinity_and_nan = | 46 | 9 | opts.allow_infinity_and_nan = | ||
| HITCBC | 47 | 9 | flags & static_cast<I>(E::allow_infinity_and_nan); | 47 | 9 | flags & static_cast<I>(E::allow_infinity_and_nan); | ||
| HITCBC | 48 | 9 | return opts; | 48 | 9 | return opts; | ||
| 49 | } | 49 | } | |||||
| 50 | 50 | |||||||
| 51 | } // namespace | 51 | } // namespace | |||||
| 52 | 52 | |||||||
| 53 | namespace detail { | 53 | namespace detail { | |||||
| 54 | 54 | |||||||
| 55 | void | 55 | void | |||||
| HITCBC | 56 | 18893 | serialize_impl( | 56 | 18893 | 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]; | |||||
| HITCBC | 63 | 18893 | string_view sv; | 63 | 18893 | string_view sv; | ||
| HITCBC | 64 | 18893 | sv = sr.read(buf); | 64 | 18893 | sv = sr.read(buf); | ||
| HITCBC | 65 | 18893 | if(sr.done()) | 65 | 18893 | if(sr.done()) | ||
| 66 | { | 66 | { | |||||
| 67 | // fast path | 67 | // fast path | |||||
| HITCBC | 68 | 10885 | s.append( | 68 | 10885 | s.append( | ||
| 69 | sv.data(), sv.size()); | 69 | sv.data(), sv.size()); | |||||
| HITCBC | 70 | 10885 | return; | 70 | 10885 | return; | ||
| 71 | } | 71 | } | |||||
| HITCBC | 72 | 8008 | std::size_t len = sv.size(); | 72 | 8008 | std::size_t len = sv.size(); | ||
| HITCBC | 73 | 8008 | s.reserve(len * 2); | 73 | 8008 | s.reserve(len * 2); | ||
| HITCBC | 74 | 8008 | s.resize(s.capacity()); | 74 | 8008 | s.resize(s.capacity()); | ||
| HITCBC | 75 | 8008 | BOOST_ASSERT( | 75 | 8008 | BOOST_ASSERT( | ||
| 76 | s.size() >= len * 2); | 76 | s.size() >= len * 2); | |||||
| HITCBC | 77 | 16016 | std::memcpy(&s[0], | 77 | 16016 | std::memcpy(&s[0], | ||
| HITCBC | 78 | 8008 | sv.data(), sv.size()); | 78 | 8008 | sv.data(), sv.size()); | ||
| 79 | auto const lim = | 79 | auto const lim = | |||||
| HITCBC | 80 | 8008 | s.max_size() / 2; | 80 | 8008 | s.max_size() / 2; | ||
| 81 | for(;;) | 81 | for(;;) | |||||
| 82 | { | 82 | { | |||||
| MISUBC | 83 | ✗ | sv = sr.read( | 83 | ✗ | sv = sr.read( | ||
| HITCBC | 84 | 8008 | &s[0] + len, | 84 | 8008 | &s[0] + len, | ||
| HITCBC | 85 | 8008 | s.size() - len); | 85 | 8008 | s.size() - len); | ||
| HITCBC | 86 | 8008 | len += sv.size(); | 86 | 8008 | len += sv.size(); | ||
| HITCBC | 87 | 8008 | if(sr.done()) | 87 | 8008 | if(sr.done()) | ||
| HITCBC | 88 | 8008 | break; | 88 | 8008 | break; | ||
| 89 | // growth factor 2x | 89 | // growth factor 2x | |||||
| MISUBC | 90 | ✗ | if(s.size() < lim) | 90 | ✗ | if(s.size() < lim) | ||
| MISUBC | 91 | ✗ | s.resize(s.size() * 2); | 91 | ✗ | s.resize(s.size() * 2); | ||
| 92 | else | 92 | else | |||||
| MISUBC | 93 | ✗ | s.resize(2 * lim); | 93 | ✗ | s.resize(2 * lim); | ||
| 94 | } | 94 | } | |||||
| HITCBC | 95 | 8008 | s.resize(len); | 95 | 8008 | s.resize(len); | ||
| 96 | } | 96 | } | |||||
| 97 | 97 | |||||||
| 98 | } // namespace detail | 98 | } // namespace detail | |||||
| 99 | 99 | |||||||
| 100 | std::string | 100 | std::string | |||||
| HITCBC | 101 | 18801 | serialize( | 101 | 18801 | 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( | |||||
| HITCBC | 107 | 37602 | storage_ptr(), | 107 | 37602 | storage_ptr(), | ||
| 108 | buf, | 108 | buf, | |||||
| 109 | sizeof(buf), | 109 | sizeof(buf), | |||||
| HITCBC | 110 | 18801 | opts); | 110 | 18801 | opts); | ||
| HITCBC | 111 | 18801 | sr.reset(&jv); | 111 | 18801 | sr.reset(&jv); | ||
| HITCBC | 112 | 18801 | std::string s; | 112 | 18801 | std::string s; | ||
| HITCBC | 113 | 18801 | serialize_impl(s, sr); | 113 | 18801 | serialize_impl(s, sr); | ||
| HITCBC | 114 | 37602 | return s; | 114 | 37602 | return s; | ||
| HITCBC | 115 | 18801 | } | 115 | 18801 | } | ||
| 116 | 116 | |||||||
| 117 | std::string | 117 | std::string | |||||
| HITCBC | 118 | 2 | serialize( | 118 | 2 | 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( | |||||
| HITCBC | 124 | 4 | storage_ptr(), | 124 | 4 | storage_ptr(), | ||
| 125 | buf, | 125 | buf, | |||||
| 126 | sizeof(buf), | 126 | sizeof(buf), | |||||
| HITCBC | 127 | 2 | opts); | 127 | 2 | opts); | ||
| HITCBC | 128 | 2 | std::string s; | 128 | 2 | std::string s; | ||
| HITCBC | 129 | 2 | sr.reset(&arr); | 129 | 2 | sr.reset(&arr); | ||
| HITCBC | 130 | 2 | serialize_impl(s, sr); | 130 | 2 | serialize_impl(s, sr); | ||
| HITCBC | 131 | 4 | return s; | 131 | 4 | return s; | ||
| HITCBC | 132 | 2 | } | 132 | 2 | } | ||
| 133 | 133 | |||||||
| 134 | std::string | 134 | std::string | |||||
| HITCBC | 135 | 49 | serialize( | 135 | 49 | 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( | |||||
| HITCBC | 141 | 98 | storage_ptr(), | 141 | 98 | storage_ptr(), | ||
| 142 | buf, | 142 | buf, | |||||
| 143 | sizeof(buf), | 143 | sizeof(buf), | |||||
| HITCBC | 144 | 49 | opts); | 144 | 49 | opts); | ||
| HITCBC | 145 | 49 | std::string s; | 145 | 49 | std::string s; | ||
| HITCBC | 146 | 49 | sr.reset(&obj); | 146 | 49 | sr.reset(&obj); | ||
| HITCBC | 147 | 49 | serialize_impl(s, sr); | 147 | 49 | serialize_impl(s, sr); | ||
| HITCBC | 148 | 98 | return s; | 148 | 98 | return s; | ||
| HITCBC | 149 | 49 | } | 149 | 49 | } | ||
| 150 | 150 | |||||||
| 151 | std::string | 151 | std::string | |||||
| HITCBC | 152 | 1 | serialize( | 152 | 1 | serialize( | ||
| 153 | string const& str, | 153 | string const& str, | |||||
| 154 | serialize_options const& opts) | 154 | serialize_options const& opts) | |||||
| 155 | { | 155 | { | |||||
| HITCBC | 156 | 1 | return serialize( str.subview(), opts ); | 156 | 1 | 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 | |||||
| HITCBC | 161 | 1 | serialize( | 161 | 1 | 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( | |||||
| HITCBC | 167 | 2 | storage_ptr(), | 167 | 2 | storage_ptr(), | ||
| 168 | buf, | 168 | buf, | |||||
| 169 | sizeof(buf), | 169 | sizeof(buf), | |||||
| HITCBC | 170 | 1 | opts); | 170 | 1 | opts); | ||
| HITCBC | 171 | 1 | std::string s; | 171 | 1 | std::string s; | ||
| HITCBC | 172 | 1 | sr.reset(sv); | 172 | 1 | sr.reset(sv); | ||
| HITCBC | 173 | 1 | serialize_impl(s, sr); | 173 | 1 | serialize_impl(s, sr); | ||
| HITCBC | 174 | 2 | return s; | 174 | 2 | return s; | ||
| HITCBC | 175 | 1 | } | 175 | 1 | } | ||
| 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& | |||||
| HITCBC | 183 | 6 | operator<<( std::ostream& os, value const& jv ) | 183 | 6 | operator<<( std::ostream& os, value const& jv ) | ||
| 184 | { | 184 | { | |||||
| 185 | // Create a serializer | 185 | // Create a serializer | |||||
| HITCBC | 186 | 6 | serializer sr( get_stream_flags(os) ); | 186 | 6 | serializer sr( get_stream_flags(os) ); | ||
| 187 | 187 | |||||||
| 188 | // Set the serializer up for our value | 188 | // Set the serializer up for our value | |||||
| HITCBC | 189 | 6 | sr.reset( &jv ); | 189 | 6 | sr.reset( &jv ); | ||
| 190 | 190 | |||||||
| 191 | // Loop until all output is produced. | 191 | // Loop until all output is produced. | |||||
| HITCBC | 192 | 12 | while( ! sr.done() ) | 192 | 12 | 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. | |||||
| HITCBC | 198 | 6 | os << sr.read( buf ); | 198 | 6 | os << sr.read( buf ); | ||
| 199 | } | 199 | } | |||||
| 200 | 200 | |||||||
| HITCBC | 201 | 6 | return os; | 201 | 6 | return os; | ||
| HITCBC | 202 | 6 | } | 202 | 6 | } | ||
| 203 | // end::example_operator_lt_lt[] | 203 | // end::example_operator_lt_lt[] | |||||
| 204 | 204 | |||||||
| 205 | static | 205 | static | |||||
| 206 | void | 206 | void | |||||
| HITCBC | 207 | 3 | to_ostream( | 207 | 3 | to_ostream( | ||
| 208 | std::ostream& os, | 208 | std::ostream& os, | |||||
| 209 | serializer& sr) | 209 | serializer& sr) | |||||
| 210 | { | 210 | { | |||||
| HITCBC | 211 | 6 | while(! sr.done()) | 211 | 6 | while(! sr.done()) | ||
| 212 | { | 212 | { | |||||
| 213 | char buf[BOOST_JSON_STACK_BUFFER_SIZE]; | 213 | char buf[BOOST_JSON_STACK_BUFFER_SIZE]; | |||||
| HITCBC | 214 | 3 | auto s = sr.read(buf); | 214 | 3 | auto s = sr.read(buf); | ||
| HITCBC | 215 | 3 | os.write(s.data(), s.size()); | 215 | 3 | os.write(s.data(), s.size()); | ||
| 216 | } | 216 | } | |||||
| HITCBC | 217 | 3 | } | 217 | 3 | } | ||
| 218 | 218 | |||||||
| 219 | std::ostream& | 219 | std::ostream& | |||||
| HITCBC | 220 | 1 | operator<<( | 220 | 1 | operator<<( | ||
| 221 | std::ostream& os, | 221 | std::ostream& os, | |||||
| 222 | array const& arr) | 222 | array const& arr) | |||||
| 223 | { | 223 | { | |||||
| HITCBC | 224 | 1 | serializer sr( get_stream_flags(os) ); | 224 | 1 | serializer sr( get_stream_flags(os) ); | ||
| HITCBC | 225 | 1 | sr.reset(&arr); | 225 | 1 | sr.reset(&arr); | ||
| HITCBC | 226 | 1 | to_ostream(os, sr); | 226 | 1 | to_ostream(os, sr); | ||
| HITCBC | 227 | 1 | return os; | 227 | 1 | return os; | ||
| HITCBC | 228 | 1 | } | 228 | 1 | } | ||
| 229 | 229 | |||||||
| 230 | std::ostream& | 230 | std::ostream& | |||||
| HITCBC | 231 | 1 | operator<<( | 231 | 1 | operator<<( | ||
| 232 | std::ostream& os, | 232 | std::ostream& os, | |||||
| 233 | object const& obj) | 233 | object const& obj) | |||||
| 234 | { | 234 | { | |||||
| HITCBC | 235 | 1 | serializer sr( get_stream_flags(os) ); | 235 | 1 | serializer sr( get_stream_flags(os) ); | ||
| HITCBC | 236 | 1 | sr.reset(&obj); | 236 | 1 | sr.reset(&obj); | ||
| HITCBC | 237 | 1 | to_ostream(os, sr); | 237 | 1 | to_ostream(os, sr); | ||
| HITCBC | 238 | 1 | return os; | 238 | 1 | return os; | ||
| HITCBC | 239 | 1 | } | 239 | 1 | } | ||
| 240 | 240 | |||||||
| 241 | std::ostream& | 241 | std::ostream& | |||||
| HITCBC | 242 | 1 | operator<<( | 242 | 1 | operator<<( | ||
| 243 | std::ostream& os, | 243 | std::ostream& os, | |||||
| 244 | string const& str) | 244 | string const& str) | |||||
| 245 | { | 245 | { | |||||
| HITCBC | 246 | 1 | serializer sr( get_stream_flags(os) ); | 246 | 1 | serializer sr( get_stream_flags(os) ); | ||
| HITCBC | 247 | 1 | sr.reset(&str); | 247 | 1 | sr.reset(&str); | ||
| HITCBC | 248 | 1 | to_ostream(os, sr); | 248 | 1 | to_ostream(os, sr); | ||
| HITCBC | 249 | 1 | return os; | 249 | 1 | return os; | ||
| HITCBC | 250 | 1 | } | 250 | 1 | } | ||
| 251 | 251 | |||||||
| 252 | std::ostream& | 252 | std::ostream& | |||||
| HITCBC | 253 | 2 | operator<<( std::ostream& os, serialize_options const& opts ) | 253 | 2 | operator<<( std::ostream& os, serialize_options const& opts ) | ||
| 254 | { | 254 | { | |||||
| HITCBC | 255 | 2 | os.iword(serialize_xalloc) = to_bitmask(opts); | 255 | 2 | os.iword(serialize_xalloc) = to_bitmask(opts); | ||
| HITCBC | 256 | 2 | return os; | 256 | 2 | return os; | ||
| 257 | } | 257 | } | |||||
| 258 | 258 | |||||||
| 259 | } // namespace json | 259 | } // namespace json | |||||
| 260 | } // namespace boost | 260 | } // namespace boost | |||||
| 261 | 261 | |||||||
| 262 | #endif | 262 | #endif | |||||