LCOV - code coverage report
Current view: top level - json/impl - serializer.ipp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 285 285
Test Date: 2026-08-12 16:16:43 Functions: 100.0 % 37 37

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       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)
       6                 : //
       7                 : // Official repository: https://github.com/boostorg/json
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_JSON_IMPL_SERIALIZER_IPP
      11                 : #define BOOST_JSON_IMPL_SERIALIZER_IPP
      12                 : 
      13                 : #include <boost/charconv/to_chars.hpp>
      14                 : #include <boost/core/detail/static_assert.hpp>
      15                 : #include <boost/json/serializer.hpp>
      16                 : #include <boost/json/detail/format.hpp>
      17                 : #include <boost/json/detail/sse2.hpp>
      18                 : 
      19                 : #ifdef _MSC_VER
      20                 : #pragma warning(push)
      21                 : #pragma warning(disable: 4127) // conditional expression is constant
      22                 : #endif
      23                 : 
      24                 : namespace {
      25                 : 
      26                 : std::size_t
      27                 : BOOST_NOINLINE
      28 HIT          15 : format_special(char* dest, double d, bool allow_infinity_and_nan) noexcept
      29                 : {
      30              15 :     if( std::isinf(d) )
      31                 :     {
      32              10 :         if( std::signbit(d) )
      33                 :         {
      34               5 :             if( allow_infinity_and_nan )
      35                 :             {
      36               2 :                 std::memcpy(dest, "-Infinity", 9);
      37               2 :                 return 9;
      38                 :             }
      39                 :             else
      40                 :             {
      41               3 :                 std::memcpy(dest, "-1e99999", 8);
      42               3 :                 return 8;
      43                 :             }
      44                 :         }
      45                 :         else
      46                 :         {
      47               5 :             if( allow_infinity_and_nan )
      48                 :             {
      49               2 :                 std::memcpy(dest, "Infinity", 8);
      50               2 :                 return 8;
      51                 :             }
      52                 :             else
      53                 :             {
      54               3 :                 std::memcpy(dest, "1e99999", 7);
      55               3 :                 return 7;
      56                 :             }
      57                 :         }
      58                 :     }
      59                 :     else
      60                 :     {
      61               5 :         BOOST_ASSERT( std::isnan(d) );
      62               5 :         if( allow_infinity_and_nan )
      63                 :         {
      64               2 :             std::memcpy(dest, "NaN", 3);
      65               2 :             return 3;
      66                 :         }
      67                 :         else
      68                 :         {
      69               3 :             std::memcpy(dest, "null", 4);
      70               3 :             return 4;
      71                 :         }
      72                 :     }
      73                 : }
      74                 : 
      75                 : } // namespace
      76                 : 
      77                 : namespace boost {
      78                 : namespace json {
      79                 : namespace detail {
      80                 : 
      81                 : struct int64_formatter
      82                 : {
      83                 :     std::int64_t i;
      84                 : 
      85                 :     std::size_t
      86            3188 :     operator()(char* dst) const noexcept
      87                 :     {
      88            3188 :         return format_int64(dst, i);
      89                 :     }
      90                 : };
      91                 : 
      92                 : struct uint64_formatter
      93                 : {
      94                 :     std::uint64_t u;
      95                 : 
      96                 :     std::size_t
      97             425 :     operator()(char* dst) const noexcept
      98                 :     {
      99             425 :         return format_uint64(dst, u);
     100                 :     }
     101                 : };
     102                 : 
     103                 : struct double_formatter
     104                 : {
     105                 :     double d;
     106                 :     bool allow_infinity_and_nan;
     107                 : 
     108                 :     std::size_t
     109             534 :     operator()(char* dst) const noexcept
     110                 :     {
     111             534 :         if(BOOST_JSON_UNLIKELY( !std::isfinite(d)) )
     112                 :         {
     113              15 :             return format_special(dst, d, allow_infinity_and_nan);
     114                 :         }
     115                 : 
     116             519 :         auto const result = boost::charconv::to_chars(
     117                 :             dst,
     118                 :             dst + detail::max_number_chars,
     119             519 :             d,
     120                 :             boost::charconv::chars_format::scientific);
     121             519 :         BOOST_ASSERT( result.ec == std::errc() );
     122             519 :         return result.ptr - dst;
     123                 :     }
     124                 : };
     125                 : 
     126           21302 : writer::
     127                 : writer(
     128                 :     storage_ptr sp,
     129                 :     unsigned char* buf,
     130                 :     std::size_t buf_size,
     131           21302 :     serialize_options const& opts) noexcept
     132           21302 :     : st_(
     133           21302 :         std::move(sp),
     134                 :         buf,
     135                 :         buf_size)
     136           21302 :     , opts_(opts)
     137                 : {
     138                 :     // ensure room for \uXXXX escape plus one
     139                 :     BOOST_CORE_STATIC_ASSERT( sizeof(buf_) >= 7 );
     140           21302 : }
     141                 : 
     142                 : bool
     143                 : BOOST_FORCEINLINE
     144                 : write_buffer(writer& w, stream& ss0)
     145                 : {
     146            1558 :     local_stream ss(ss0);
     147            2744 :     auto const n = ss.remain();
     148            2744 :     if( n < w.cs0_.remain() )
     149                 :     {
     150            1448 :         ss.append(w.cs0_.data(), n);
     151            1448 :         w.cs0_.skip(n);
     152            1448 :         return w.suspend(writer::state::lit);
     153                 :     }
     154            1296 :     ss.append( w.cs0_.data(), w.cs0_.remain() );
     155            1296 :     return true;
     156            2744 : }
     157                 : 
     158                 : template< class F >
     159                 : bool
     160            4147 : write_buffer(writer& w, stream& ss0, F f)
     161                 : {
     162            4147 :     BOOST_ASSERT( w.st_.empty() );
     163                 : 
     164            4147 :     local_stream ss(ss0);
     165            4147 :     if(BOOST_JSON_LIKELY( ss.remain() >= detail::max_number_chars ))
     166                 :     {
     167            2961 :         ss.advance( f(ss.data()) );
     168            2961 :         return true;
     169                 :     }
     170                 : 
     171            1186 :     w.cs0_ = { w.buf_, f(w.buf_) };
     172            1186 :     return write_buffer(w, ss);
     173            4147 : }
     174                 : 
     175                 : template<literals Lit>
     176                 : bool
     177            4725 : write_literal(writer& w, stream& ss)
     178                 : {
     179            4725 :     constexpr std::size_t index = literal_index(Lit);
     180            4725 :     constexpr char const* literal = literal_strings[index];
     181            4725 :     constexpr std::size_t sz = literal_sizes[index];
     182                 : 
     183            4725 :     std::size_t const n = ss.remain();
     184            4725 :     if(BOOST_JSON_LIKELY( n >= sz ))
     185                 :     {
     186            4613 :         ss.append( literal, sz );
     187            4613 :         return true;
     188                 :     }
     189                 : 
     190             112 :     ss.append(literal, n);
     191                 : 
     192             112 :     w.cs0_ = {literal + n, sz - n};
     193             112 :     return w.suspend(writer::state::lit);
     194                 : }
     195                 : 
     196                 : bool
     197             197 : write_true(writer& w, stream& ss)
     198                 : {
     199             197 :     return write_literal<literals::true_>(w, ss);
     200                 : }
     201                 : 
     202                 : bool
     203             176 : write_false(writer& w, stream& ss)
     204                 : {
     205             176 :     return write_literal<literals::false_>(w, ss);
     206                 : }
     207                 : 
     208                 : bool
     209            4352 : write_null(writer& w, stream& ss)
     210                 : {
     211            4352 :     return write_literal<literals::null>(w, ss);
     212                 : }
     213                 : 
     214                 : bool
     215            3188 : write_int64(writer& w, stream& ss0, std::int64_t i)
     216                 : {
     217            3188 :     return write_buffer( w, ss0, int64_formatter{i} );
     218                 : }
     219                 : 
     220                 : bool
     221             425 : write_uint64(writer& w, stream& ss0, std::uint64_t u)
     222                 : {
     223             425 :     return write_buffer( w, ss0, uint64_formatter{u} );
     224                 : }
     225                 : 
     226                 : bool
     227             534 : write_double(writer& w, stream& ss0, double d)
     228                 : {
     229            1068 :     return write_buffer(
     230             534 :         w, ss0, double_formatter{d, w.opts_.allow_infinity_and_nan} );
     231                 : }
     232                 : 
     233                 : bool
     234            1558 : resume_buffer(writer& w, stream& ss0)
     235                 : {
     236            1558 :     BOOST_ASSERT( !w.st_.empty() );
     237                 :     writer::state st;
     238            1558 :     w.st_.pop(st);
     239            1558 :     BOOST_ASSERT(st == writer::state::lit);
     240                 : 
     241            3116 :     return write_buffer(w, ss0);
     242                 : }
     243                 : 
     244                 : template<bool StackEmpty>
     245                 : bool
     246           44285 : do_write_string(writer& w, stream& ss0)
     247                 : {
     248           44285 :     local_stream ss(ss0);
     249           44285 :     local_const_stream cs(w.cs0_);
     250            9812 :     if(! StackEmpty && ! w.st_.empty())
     251                 :     {
     252                 :         writer::state st;
     253            9812 :         w.st_.pop(st);
     254            9812 :         switch(st)
     255                 :         {
     256             170 :         default:
     257             170 :         case writer::state::str1: goto do_str1;
     258             268 :         case writer::state::str2: goto do_str2;
     259            9082 :         case writer::state::str3: goto do_str3;
     260              52 :         case writer::state::esc1: goto do_esc1;
     261              48 :         case writer::state::utf1: goto do_utf1;
     262              48 :         case writer::state::utf2: goto do_utf2;
     263              48 :         case writer::state::utf3: goto do_utf3;
     264              48 :         case writer::state::utf4: goto do_utf4;
     265              48 :         case writer::state::utf5: goto do_utf5;
     266                 :         }
     267                 :     }
     268                 :     static constexpr char hex[] = "0123456789abcdef";
     269                 :     static constexpr char esc[] =
     270                 :         "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu"
     271                 :         "\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     272                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0"
     273                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     274                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     275                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     276                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     277                 :         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
     278                 : 
     279                 :     // opening quote
     280           34473 : do_str1:
     281           34643 :     if(BOOST_JSON_LIKELY(ss))
     282           34473 :         ss.append('\x22'); // '"'
     283                 :     else
     284             170 :         return w.suspend(writer::state::str1);
     285                 : 
     286                 :     // fast loop,
     287                 :     // copy unescaped
     288           34741 : do_str2:
     289           34741 :     if(BOOST_JSON_LIKELY(ss))
     290                 :     {
     291           34485 :         std::size_t n = cs.remain();
     292           34485 :         if(BOOST_JSON_LIKELY(n > 0))
     293                 :         {
     294           34441 :             if(ss.remain() > n)
     295           25766 :                 n = detail::count_unescaped(
     296                 :                     cs.data(), n);
     297                 :             else
     298            8675 :                 n = detail::count_unescaped(
     299                 :                     cs.data(), ss.remain());
     300           34441 :             if(n > 0)
     301                 :             {
     302           25225 :                 ss.append(cs.data(), n);
     303           25225 :                 cs.skip(n);
     304           25225 :                 if(! ss)
     305              12 :                     return w.suspend(writer::state::str2);
     306                 :             }
     307                 :         }
     308                 :         else
     309                 :         {
     310              44 :             ss.append('\x22'); // '"'
     311              44 :             return true;
     312                 :         }
     313                 :     }
     314                 :     else
     315                 :     {
     316             256 :         return w.suspend(writer::state::str2);
     317                 :     }
     318                 : 
     319                 :     // slow loop,
     320                 :     // handle escapes
     321           43707 : do_str3:
     322        31461016 :     while(BOOST_JSON_LIKELY(ss))
     323                 :     {
     324        31451934 :         if(BOOST_JSON_LIKELY(cs))
     325                 :         {
     326        31417505 :             auto const ch = *cs;
     327        31417505 :             auto const c = esc[static_cast<
     328                 :                 unsigned char>(ch)];
     329        31417505 :             ++cs;
     330        31417505 :             if(! c)
     331                 :             {
     332        31416777 :                 ss.append(ch);
     333                 :             }
     334             728 :             else if(c != 'u')
     335                 :             {
     336             376 :                 ss.append('\\');
     337             376 :                 if(BOOST_JSON_LIKELY(ss))
     338                 :                 {
     339             324 :                     ss.append(c);
     340                 :                 }
     341                 :                 else
     342                 :                 {
     343              52 :                     w.buf_[0] = c;
     344              52 :                     return w.suspend(
     345              52 :                         writer::state::esc1);
     346                 :                 }
     347                 :             }
     348                 :             else
     349                 :             {
     350             352 :                 if(BOOST_JSON_LIKELY(
     351                 :                     ss.remain() >= 6))
     352                 :                 {
     353             208 :                     ss.append("\\u00", 4);
     354             208 :                     ss.append(hex[static_cast<
     355             208 :                         unsigned char>(ch) >> 4]);
     356             208 :                     ss.append(hex[static_cast<
     357             208 :                         unsigned char>(ch) & 15]);
     358                 :                 }
     359                 :                 else
     360                 :                 {
     361             144 :                     ss.append('\\');
     362             144 :                     w.buf_[0] = hex[static_cast<
     363             144 :                         unsigned char>(ch) >> 4];
     364             144 :                     w.buf_[1] = hex[static_cast<
     365             144 :                         unsigned char>(ch) & 15];
     366             144 :                     goto do_utf1;
     367                 :                 }
     368                 :             }
     369                 :         }
     370                 :         else
     371                 :         {
     372           34429 :             ss.append('\x22'); // '"'
     373           34429 :             return true;
     374                 :         }
     375                 :     }
     376            9082 :     return w.suspend(writer::state::str3);
     377                 : 
     378              52 : do_esc1:
     379              52 :     BOOST_ASSERT(ss);
     380              52 :     ss.append(w.buf_[0]);
     381              52 :     goto do_str3;
     382                 : 
     383             192 : do_utf1:
     384             192 :     if(BOOST_JSON_LIKELY(ss))
     385             144 :         ss.append('u');
     386                 :     else
     387              48 :         return w.suspend(writer::state::utf1);
     388             192 : do_utf2:
     389             192 :     if(BOOST_JSON_LIKELY(ss))
     390             144 :         ss.append('0');
     391                 :     else
     392              48 :         return w.suspend(writer::state::utf2);
     393             192 : do_utf3:
     394             192 :     if(BOOST_JSON_LIKELY(ss))
     395             144 :         ss.append('0');
     396                 :     else
     397              48 :         return w.suspend(writer::state::utf3);
     398             192 : do_utf4:
     399             192 :     if(BOOST_JSON_LIKELY(ss))
     400             144 :         ss.append(w.buf_[0]);
     401                 :     else
     402              48 :         return w.suspend(writer::state::utf4);
     403             192 : do_utf5:
     404             192 :     if(BOOST_JSON_LIKELY(ss))
     405             144 :         ss.append(w.buf_[1]);
     406                 :     else
     407              48 :         return w.suspend(writer::state::utf5);
     408             144 :     goto do_str3;
     409           44285 : }
     410                 : 
     411                 : bool
     412           19827 : write_string(writer& w, stream& ss0)
     413                 : {
     414           19827 :     return do_write_string<true>(w, ss0);
     415                 : }
     416                 : 
     417                 : bool
     418             408 : resume_string(writer& w, stream& ss0)
     419                 : {
     420             408 :     return do_write_string<false>(w, ss0);
     421                 : }
     422                 : 
     423                 : template<bool StackEmpty>
     424                 : bool
     425                 : write_value(writer& w, stream& ss);
     426                 : 
     427                 : template< class T, bool StackEmpty >
     428                 : BOOST_FORCEINLINE
     429                 : bool
     430                 : write_impl(no_conversion_tag, writer& w, stream& ss)
     431                 : {
     432           34575 :     return write_value<StackEmpty>(w, ss);
     433                 : }
     434                 : 
     435                 : template<bool StackEmpty>
     436                 : bool
     437            6080 : write_array(writer& w, stream& ss)
     438                 : {
     439            6079 :     return write_impl<array, StackEmpty>(sequence_conversion_tag(), w, ss);
     440                 : }
     441                 : 
     442                 : template<bool StackEmpty>
     443                 : bool
     444           27194 : write_object(writer& w, stream& ss)
     445                 : {
     446           27194 :     return write_impl<object, StackEmpty>(map_like_conversion_tag(), w, ss);
     447                 : }
     448                 : 
     449                 : template<bool StackEmpty>
     450                 : bool
     451           67131 : write_value(writer& w, stream& ss)
     452                 : {
     453           23041 :     if(StackEmpty || w.st_.empty())
     454                 :     {
     455           44571 :         BOOST_ASSERT( w.p_ );
     456           44571 :         auto const pv = reinterpret_cast<value const*>(w.p_);
     457           44571 :         switch(pv->kind())
     458                 :         {
     459           18083 :         default:
     460                 :         case kind::object:
     461           18083 :             w.p_ = &pv->get_object();
     462           18083 :             return write_object<true>(w, ss);
     463                 : 
     464            3413 :         case kind::array:
     465            3413 :             w.p_ = &pv->get_array();
     466            3413 :             return write_array<true>(w, ss);
     467                 : 
     468           14643 :         case kind::string:
     469                 :         {
     470           14643 :             auto const& js = pv->get_string();
     471           14643 :             w.cs0_ = { js.data(), js.size() };
     472           14643 :             return do_write_string<true>(w, ss);
     473                 :         }
     474                 : 
     475            3182 :         case kind::int64:
     476            3182 :             return write_int64( w, ss, pv->get_int64() );
     477              91 :         case kind::uint64:
     478              91 :             return write_uint64( w, ss, pv->get_uint64() );
     479             522 :         case kind::double_:
     480             522 :             return write_double( w, ss, pv->get_double() );
     481                 : 
     482             306 :         case kind::bool_:
     483             306 :             if( pv->get_bool() )
     484             139 :                 return write_true(w, ss);
     485                 :             else
     486             167 :                 return write_false(w, ss);
     487                 : 
     488            4331 :         case kind::null:
     489            4331 :             return write_null(w, ss);
     490                 :         }
     491                 :     }
     492                 :     else
     493                 :     {
     494                 :         writer::state st;
     495           22560 :         w.st_.peek(st);
     496           22560 :         switch(st)
     497                 :         {
     498            1434 :         default:
     499                 :         case writer::state::lit:
     500            1434 :             return resume_buffer(w, ss);
     501                 : 
     502            9404 :         case writer::state::str1: case writer::state::str2:
     503                 :         case writer::state::str3: case writer::state::esc1:
     504                 :         case writer::state::utf1: case writer::state::utf2:
     505                 :         case writer::state::utf3: case writer::state::utf4:
     506                 :         case writer::state::utf5:
     507            9404 :             return do_write_string<false>(w, ss);
     508                 : 
     509            2662 :         case writer::state::arr1: case writer::state::arr2:
     510                 :         case writer::state::arr3: case writer::state::arr4:
     511            2662 :             return write_array<StackEmpty>(w, ss);
     512                 : 
     513            9060 :         case writer::state::obj1: case writer::state::obj2:
     514                 :         case writer::state::obj3: case writer::state::obj4:
     515                 :         case writer::state::obj5: case writer::state::obj6:
     516            9060 :             return write_object<StackEmpty>(w, ss);
     517                 :         }
     518                 :     }
     519                 : }
     520                 : 
     521                 : } // namespace detail
     522                 : 
     523            2405 : serializer::
     524            2405 : serializer(serialize_options const& opts) noexcept
     525            2405 :     : serializer({}, nullptr, 0, opts)
     526            2405 : {}
     527                 : 
     528           21302 : serializer::
     529                 : serializer(
     530                 :     storage_ptr sp,
     531                 :     unsigned char* buf,
     532                 :     std::size_t buf_size,
     533           21302 :     serialize_options const& opts) noexcept
     534           21302 :     : detail::writer(std::move(sp), buf, buf_size, opts)
     535           21302 : {}
     536                 : 
     537                 : void
     538           21016 : serializer::
     539                 : reset(value const* p) noexcept
     540                 : {
     541           21016 :     p_ = p;
     542           21016 :     fn0_ = &detail::write_value<true>;
     543           21016 :     fn1_ = &detail::write_value<false>;
     544           21016 :     st_.clear();
     545           21016 :     done_ = false;
     546           21016 : }
     547                 : 
     548                 : void
     549               5 : serializer::
     550                 : reset(array const* p) noexcept
     551                 : {
     552               5 :     p_ = p;
     553               5 :     fn0_ = &detail::write_array<true>;
     554               5 :     fn1_ = &detail::write_array<false>;
     555               5 :     st_.clear();
     556               5 :     done_ = false;
     557               5 : }
     558                 : 
     559                 : void
     560              51 : serializer::
     561                 : reset(object const* p) noexcept
     562                 : {
     563              51 :     p_ = p;
     564              51 :     fn0_ = &detail::write_object<true>;
     565              51 :     fn1_ = &detail::write_object<false>;
     566              51 :     st_.clear();
     567              51 :     done_ = false;
     568              51 : }
     569                 : 
     570                 : void
     571               2 : serializer::
     572                 : reset(string const* p) noexcept
     573                 : {
     574               2 :     cs0_ = { p->data(), p->size() };
     575               2 :     fn0_ = &detail::do_write_string<true>;
     576               2 :     fn1_ = &detail::do_write_string<false>;
     577               2 :     st_.clear();
     578               2 :     done_ = false;
     579               2 : }
     580                 : 
     581                 : void
     582               1 : serializer::
     583                 : reset(string_view sv) noexcept
     584                 : {
     585               1 :     cs0_ = { sv.data(), sv.size() };
     586               1 :     fn0_ = &detail::do_write_string<true>;
     587               1 :     fn1_ = &detail::do_write_string<false>;
     588               1 :     st_.clear();
     589               1 :     done_ = false;
     590               1 : }
     591                 : 
     592                 : void
     593               6 : serializer::reset(std::nullptr_t) noexcept
     594                 : {
     595               6 :     p_ = nullptr;
     596               6 :     fn0_ = &detail::write_impl<std::nullptr_t, true>;
     597               6 :     fn1_ = &detail::write_impl<std::nullptr_t, false>;
     598               6 :     st_.clear();
     599               6 :     done_ = false;
     600               6 : }
     601                 : 
     602                 : string_view
     603           33154 : serializer::
     604                 : read(char* dest, std::size_t size)
     605                 : {
     606           33154 :     if( !fn0_ )
     607               6 :         reset(nullptr);
     608                 : 
     609           33154 :     if(BOOST_JSON_UNLIKELY(size == 0))
     610               1 :         return {dest, 0};
     611                 : 
     612           33153 :     detail::stream ss(dest, size);
     613           33153 :     if(st_.empty())
     614           21301 :         fn0_(*this, ss);
     615                 :     else
     616           11852 :         fn1_(*this, ss);
     617           33151 :     if(st_.empty())
     618                 :     {
     619           21299 :         done_ = true;
     620           21299 :         fn0_ = nullptr;
     621           21299 :         p_ = nullptr;
     622                 :     }
     623           33151 :     return string_view(
     624           33151 :         dest, ss.used(dest));
     625                 : }
     626                 : 
     627                 : } // namespace json
     628                 : } // namespace boost
     629                 : 
     630                 : #ifdef _MSC_VER
     631                 : #pragma warning(pop)
     632                 : #endif
     633                 : 
     634                 : #endif
        

Generated by: LCOV version 2.3