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