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