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