LCOV - code coverage report
Current view: top level - json/impl - serializer.ipp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 99.8 % 442 441
Test Date: 2025-12-23 17:21:58 Functions: 100.0 % 28 28

            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/json/serializer.hpp>
      14              : #include <boost/json/detail/format.hpp>
      15              : #include <boost/json/detail/sse2.hpp>
      16              : #include <ostream>
      17              : 
      18              : #ifdef _MSC_VER
      19              : #pragma warning(push)
      20              : #pragma warning(disable: 4127) // conditional expression is constant
      21              : #endif
      22              : 
      23              : namespace boost {
      24              : namespace json {
      25              : 
      26              : enum class serializer::state : char
      27              : {
      28              :     nul1, nul2, nul3, nul4,
      29              :     tru1, tru2, tru3, tru4,
      30              :     fal1, fal2, fal3, fal4, fal5,
      31              :     str1, str2, str3, esc1, utf1,
      32              :     utf2, utf3, utf4, utf5,
      33              :     num,
      34              :     arr1, arr2, arr3, arr4,
      35              :     obj1, obj2, obj3, obj4, obj5, obj6
      36              : };
      37              : 
      38              : //----------------------------------------------------------
      39              : 
      40        18855 : serializer::
      41              : serializer(
      42              :     storage_ptr sp,
      43              :     unsigned char* buf,
      44              :     std::size_t buf_size,
      45        18855 :     serialize_options const& opts) noexcept
      46        18855 :     : st_(
      47        18855 :         std::move(sp),
      48              :         buf,
      49              :         buf_size)
      50        18855 :     , opts_(opts)
      51              : {
      52        18855 : }
      53              : 
      54              : bool
      55         9505 : serializer::
      56              : suspend(state st)
      57              : {
      58         9505 :     st_.push(st);
      59         9504 :     return false;
      60              : }
      61              : 
      62              : bool
      63         1319 : serializer::
      64              : suspend(
      65              :     state st,
      66              :     array::const_iterator it,
      67              :     array const* pa)
      68              : {
      69         1319 :     st_.push(pa);
      70         1318 :     st_.push(it);
      71         1318 :     st_.push(st);
      72         1318 :     return false;
      73              : }
      74              : 
      75              : bool
      76         8534 : serializer::
      77              : suspend(
      78              :     state st,
      79              :     object::const_iterator it,
      80              :     object const* po)
      81              : {
      82         8534 :     st_.push(po);
      83         8534 :     st_.push(it);
      84         8534 :     st_.push(st);
      85         8534 :     return false;
      86              : }
      87              : 
      88              : template<bool StackEmpty>
      89              : bool
      90           75 : serializer::
      91              : write_null(stream& ss0)
      92              : {
      93           75 :     local_stream ss(ss0);
      94           36 :     if(! StackEmpty && ! st_.empty())
      95              :     {
      96              :         state st;
      97           36 :         st_.pop(st);
      98           36 :         switch(st)
      99              :         {
     100            7 :         default:
     101            7 :         case state::nul1: goto do_nul1;
     102           10 :         case state::nul2: goto do_nul2;
     103            9 :         case state::nul3: goto do_nul3;
     104           10 :         case state::nul4: goto do_nul4;
     105              :         }
     106              :     }
     107           39 : do_nul1:
     108           46 :     if(BOOST_JSON_LIKELY(ss))
     109           39 :         ss.append('n');
     110              :     else
     111            7 :         return suspend(state::nul1);
     112           49 : do_nul2:
     113           49 :     if(BOOST_JSON_LIKELY(ss))
     114           38 :         ss.append('u');
     115              :     else
     116           11 :         return suspend(state::nul2);
     117           47 : do_nul3:
     118           47 :     if(BOOST_JSON_LIKELY(ss))
     119           38 :         ss.append('l');
     120              :     else
     121            9 :         return suspend(state::nul3);
     122           48 : do_nul4:
     123           48 :     if(BOOST_JSON_LIKELY(ss))
     124           38 :         ss.append('l');
     125              :     else
     126           10 :         return suspend(state::nul4);
     127           38 :     return true;
     128           75 : }
     129              : 
     130              : template<bool StackEmpty>
     131              : bool
     132           28 : serializer::
     133              : write_true(stream& ss0)
     134              : {
     135           28 :     local_stream ss(ss0);
     136           14 :     if(! StackEmpty && ! st_.empty())
     137              :     {
     138              :         state st;
     139           14 :         st_.pop(st);
     140           14 :         switch(st)
     141              :         {
     142            2 :         default:
     143            2 :         case state::tru1: goto do_tru1;
     144            4 :         case state::tru2: goto do_tru2;
     145            4 :         case state::tru3: goto do_tru3;
     146            4 :         case state::tru4: goto do_tru4;
     147              :         }
     148              :     }
     149           14 : do_tru1:
     150           16 :     if(BOOST_JSON_LIKELY(ss))
     151           14 :         ss.append('t');
     152              :     else
     153            2 :         return suspend(state::tru1);
     154           18 : do_tru2:
     155           18 :     if(BOOST_JSON_LIKELY(ss))
     156           14 :         ss.append('r');
     157              :     else
     158            4 :         return suspend(state::tru2);
     159           18 : do_tru3:
     160           18 :     if(BOOST_JSON_LIKELY(ss))
     161           14 :         ss.append('u');
     162              :     else
     163            4 :         return suspend(state::tru3);
     164           18 : do_tru4:
     165           18 :     if(BOOST_JSON_LIKELY(ss))
     166           14 :         ss.append('e');
     167              :     else
     168            4 :         return suspend(state::tru4);
     169           14 :     return true;
     170           28 : }
     171              : 
     172              : template<bool StackEmpty>
     173              : bool
     174           36 : serializer::
     175              : write_false(stream& ss0)
     176              : {
     177           36 :     local_stream ss(ss0);
     178           18 :     if(! StackEmpty && ! st_.empty())
     179              :     {
     180              :         state st;
     181           18 :         st_.pop(st);
     182           18 :         switch(st)
     183              :         {
     184            2 :         default:
     185            2 :         case state::fal1: goto do_fal1;
     186            4 :         case state::fal2: goto do_fal2;
     187            4 :         case state::fal3: goto do_fal3;
     188            4 :         case state::fal4: goto do_fal4;
     189            4 :         case state::fal5: goto do_fal5;
     190              :         }
     191              :     }
     192           18 : do_fal1:
     193           20 :     if(BOOST_JSON_LIKELY(ss))
     194           18 :         ss.append('f');
     195              :     else
     196            2 :         return suspend(state::fal1);
     197           22 : do_fal2:
     198           22 :     if(BOOST_JSON_LIKELY(ss))
     199           18 :         ss.append('a');
     200              :     else
     201            4 :         return suspend(state::fal2);
     202           22 : do_fal3:
     203           22 :     if(BOOST_JSON_LIKELY(ss))
     204           18 :         ss.append('l');
     205              :     else
     206            4 :         return suspend(state::fal3);
     207           22 : do_fal4:
     208           22 :     if(BOOST_JSON_LIKELY(ss))
     209           18 :         ss.append('s');
     210              :     else
     211            4 :         return suspend(state::fal4);
     212           22 : do_fal5:
     213           22 :     if(BOOST_JSON_LIKELY(ss))
     214           18 :         ss.append('e');
     215              :     else
     216            4 :         return suspend(state::fal5);
     217           18 :     return true;
     218           36 : }
     219              : 
     220              : template<bool StackEmpty>
     221              : bool
     222        42923 : serializer::
     223              : write_string(stream& ss0)
     224              : {
     225        42923 :     local_stream ss(ss0);
     226        42923 :     local_const_stream cs(cs0_);
     227         8968 :     if(! StackEmpty && ! st_.empty())
     228              :     {
     229              :         state st;
     230         8839 :         st_.pop(st);
     231         8839 :         switch(st)
     232              :         {
     233           78 :         default:
     234           78 :         case state::str1: goto do_str1;
     235          130 :         case state::str2: goto do_str2;
     236         8485 :         case state::str3: goto do_str3;
     237           26 :         case state::esc1: goto do_esc1;
     238           24 :         case state::utf1: goto do_utf1;
     239           24 :         case state::utf2: goto do_utf2;
     240           24 :         case state::utf3: goto do_utf3;
     241           24 :         case state::utf4: goto do_utf4;
     242           24 :         case state::utf5: goto do_utf5;
     243              :         }
     244              :     }
     245              :     static constexpr char hex[] = "0123456789abcdef";
     246              :     static constexpr char esc[] =
     247              :         "uuuuuuuubtnufruuuuuuuuuuuuuuuuuu"
     248              :         "\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"
     249              :         "\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"
     250              :         "\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"
     251              :         "\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"
     252              :         "\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"
     253              :         "\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"
     254              :         "\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";
     255              : 
     256              :     // opening quote
     257        34084 : do_str1:
     258        34162 :     if(BOOST_JSON_LIKELY(ss))
     259        34084 :         ss.append('\x22'); // '"'
     260              :     else
     261           78 :         return suspend(state::str1);
     262              : 
     263              :     // fast loop,
     264              :     // copy unescaped
     265        34214 : do_str2:
     266        34214 :     if(BOOST_JSON_LIKELY(ss))
     267              :     {
     268        34094 :         std::size_t n = cs.remain();
     269        34094 :         if(BOOST_JSON_LIKELY(n > 0))
     270              :         {
     271        34054 :             if(ss.remain() > n)
     272        25559 :                 n = detail::count_unescaped(
     273              :                     cs.data(), n);
     274              :             else
     275         8495 :                 n = detail::count_unescaped(
     276              :                     cs.data(), ss.remain());
     277        34054 :             if(n > 0)
     278              :             {
     279        25199 :                 ss.append(cs.data(), n);
     280        25199 :                 cs.skip(n);
     281        25199 :                 if(! ss)
     282           10 :                     return suspend(state::str2);
     283              :             }
     284              :         }
     285              :         else
     286              :         {
     287           40 :             ss.append('\x22'); // '"'
     288           40 :             return true;
     289              :         }
     290              :     }
     291              :     else
     292              :     {
     293          120 :         return suspend(state::str2);
     294              :     }
     295              : 
     296              :     // slow loop,
     297              :     // handle escapes
     298        42675 : do_str3:
     299     31458087 :     while(BOOST_JSON_LIKELY(ss))
     300              :     {
     301     31449602 :         if(BOOST_JSON_LIKELY(cs))
     302              :         {
     303     31415558 :             auto const ch = *cs;
     304     31415558 :             auto const c = esc[static_cast<
     305              :                 unsigned char>(ch)];
     306     31415558 :             ++cs;
     307     31415558 :             if(! c)
     308              :             {
     309     31414880 :                 ss.append(ch);
     310              :             }
     311          678 :             else if(c != 'u')
     312              :             {
     313          350 :                 ss.append('\\');
     314          350 :                 if(BOOST_JSON_LIKELY(ss))
     315              :                 {
     316          324 :                     ss.append(c);
     317              :                 }
     318              :                 else
     319              :                 {
     320           26 :                     buf_[0] = c;
     321           26 :                     return suspend(
     322           26 :                         state::esc1);
     323              :                 }
     324              :             }
     325              :             else
     326              :             {
     327          328 :                 if(BOOST_JSON_LIKELY(
     328              :                     ss.remain() >= 6))
     329              :                 {
     330          208 :                     ss.append("\\u00", 4);
     331          208 :                     ss.append(hex[static_cast<
     332          208 :                         unsigned char>(ch) >> 4]);
     333          208 :                     ss.append(hex[static_cast<
     334          208 :                         unsigned char>(ch) & 15]);
     335              :                 }
     336              :                 else
     337              :                 {
     338          120 :                     ss.append('\\');
     339          120 :                     buf_[0] = hex[static_cast<
     340          120 :                         unsigned char>(ch) >> 4];
     341          120 :                     buf_[1] = hex[static_cast<
     342          120 :                         unsigned char>(ch) & 15];
     343          120 :                     goto do_utf1;
     344              :                 }
     345              :             }
     346              :         }
     347              :         else
     348              :         {
     349        34044 :             ss.append('\x22'); // '"'
     350        34044 :             return true;
     351              :         }
     352              :     }
     353         8485 :     return suspend(state::str3);
     354              : 
     355           26 : do_esc1:
     356           26 :     if(BOOST_JSON_LIKELY(ss))
     357           26 :         ss.append(buf_[0]);
     358              :     else
     359            0 :         return suspend(state::esc1);
     360           26 :     goto do_str3;
     361              : 
     362          144 : do_utf1:
     363          144 :     if(BOOST_JSON_LIKELY(ss))
     364          120 :         ss.append('u');
     365              :     else
     366           24 :         return suspend(state::utf1);
     367          144 : do_utf2:
     368          144 :     if(BOOST_JSON_LIKELY(ss))
     369          120 :         ss.append('0');
     370              :     else
     371           24 :         return suspend(state::utf2);
     372          144 : do_utf3:
     373          144 :     if(BOOST_JSON_LIKELY(ss))
     374          120 :         ss.append('0');
     375              :     else
     376           24 :         return suspend(state::utf3);
     377          144 : do_utf4:
     378          144 :     if(BOOST_JSON_LIKELY(ss))
     379          120 :         ss.append(buf_[0]);
     380              :     else
     381           24 :         return suspend(state::utf4);
     382          144 : do_utf5:
     383          144 :     if(BOOST_JSON_LIKELY(ss))
     384          120 :         ss.append(buf_[1]);
     385              :     else
     386           24 :         return suspend(state::utf5);
     387          120 :     goto do_str3;
     388        42923 : }
     389              : 
     390              : template<bool StackEmpty>
     391              : bool
     392         4222 : serializer::
     393              : write_number(stream& ss0)
     394              : {
     395         4222 :     local_stream ss(ss0);
     396          596 :     if(StackEmpty || st_.empty())
     397              :     {
     398         3626 :         switch(jv_->kind())
     399              :         {
     400         3111 :         default:
     401              :         case kind::int64:
     402         3111 :             if(BOOST_JSON_LIKELY(
     403              :                 ss.remain() >=
     404              :                     detail::max_number_chars))
     405              :             {
     406         2559 :                 ss.advance(detail::format_int64(
     407         2559 :                     ss.data(), jv_->get_int64()));
     408         2559 :                 return true;
     409              :             }
     410          552 :             cs0_ = { buf_, detail::format_int64(
     411          552 :                 buf_, jv_->get_int64()) };
     412          552 :             break;
     413              : 
     414           88 :         case kind::uint64:
     415           88 :             if(BOOST_JSON_LIKELY(
     416              :                 ss.remain() >=
     417              :                     detail::max_number_chars))
     418              :             {
     419           33 :                 ss.advance(detail::format_uint64(
     420           33 :                     ss.data(), jv_->get_uint64()));
     421           33 :                 return true;
     422              :             }
     423           55 :             cs0_ = { buf_, detail::format_uint64(
     424           55 :                 buf_, jv_->get_uint64()) };
     425           55 :             break;
     426              : 
     427          427 :         case kind::double_:
     428          427 :             if(BOOST_JSON_LIKELY(
     429              :                 ss.remain() >=
     430              :                     detail::max_number_chars))
     431              :             {
     432          286 :                 ss.advance(
     433          286 :                     detail::format_double(
     434              :                         ss.data(),
     435          286 :                         jv_->get_double(),
     436          286 :                         opts_.allow_infinity_and_nan));
     437          286 :                 return true;
     438              :             }
     439          141 :             cs0_ = { buf_, detail::format_double(
     440          141 :                 buf_, jv_->get_double(), opts_.allow_infinity_and_nan) };
     441          141 :             break;
     442              :         }
     443              :     }
     444              :     else
     445              :     {
     446              :         state st;
     447          596 :         st_.pop(st);
     448          596 :         BOOST_ASSERT(
     449              :             st == state::num);
     450              :     }
     451         1344 :     auto const n = ss.remain();
     452         1344 :     if(n < cs0_.remain())
     453              :     {
     454          597 :         ss.append(cs0_.data(), n);
     455          597 :         cs0_.skip(n);
     456          597 :         return suspend(state::num);
     457              :     }
     458          747 :     ss.append(
     459              :         cs0_.data(), cs0_.remain());
     460          747 :     return true;
     461         4222 : }
     462              : 
     463              : template<bool StackEmpty>
     464              : bool
     465         4606 : serializer::
     466              : write_array(stream& ss0)
     467              : {
     468              :     array const* pa;
     469         4606 :     local_stream ss(ss0);
     470              :     array::const_iterator it;
     471              :     array::const_iterator end;
     472         1318 :     if(StackEmpty || st_.empty())
     473              :     {
     474         3288 :         pa = pa_;
     475         3288 :         it = pa->begin();
     476         3288 :         end = pa->end();
     477              :     }
     478              :     else
     479              :     {
     480              :         state st;
     481         1318 :         st_.pop(st);
     482         1318 :         st_.pop(it);
     483         1318 :         st_.pop(pa);
     484         1318 :         end = pa->end();
     485         1318 :         switch(st)
     486              :         {
     487           35 :         default:
     488           35 :         case state::arr1: goto do_arr1;
     489         1152 :         case state::arr2: goto do_arr2;
     490           16 :         case state::arr3: goto do_arr3;
     491          115 :         case state::arr4: goto do_arr4;
     492              :             break;
     493              :         }
     494              :     }
     495         3323 : do_arr1:
     496         3323 :     if(BOOST_JSON_LIKELY(ss))
     497         3288 :         ss.append('[');
     498              :     else
     499           35 :         return suspend(
     500           35 :             state::arr1, it, pa);
     501         3288 :     if(it == end)
     502          495 :         goto do_arr4;
     503              :     for(;;)
     504              :     {
     505         2793 : do_arr2:
     506         5007 :         jv_ = &*it;
     507         5007 :         if(! write_value<StackEmpty>(ss))
     508         1153 :             return suspend(
     509         1152 :                 state::arr2, it, pa);
     510         3854 :         if(BOOST_JSON_UNLIKELY(
     511              :             ++it == end))
     512         2792 :             break;
     513         1062 : do_arr3:
     514         1078 :         if(BOOST_JSON_LIKELY(ss))
     515         1062 :             ss.append(',');
     516              :         else
     517           16 :             return suspend(
     518           16 :                 state::arr3, it, pa);
     519              :     }
     520         3402 : do_arr4:
     521         3402 :     if(BOOST_JSON_LIKELY(ss))
     522         3287 :         ss.append(']');
     523              :     else
     524          115 :         return suspend(
     525          115 :             state::arr4, it, pa);
     526         3287 :     return true;
     527         4606 : }
     528              : 
     529              : template<bool StackEmpty>
     530              : bool
     531        26645 : serializer::
     532              : write_object(stream& ss0)
     533              : {
     534              :     object const* po;
     535        26645 :     local_stream ss(ss0);
     536              :     object::const_iterator it;
     537              :     object::const_iterator end;
     538         8534 :     if(StackEmpty || st_.empty())
     539              :     {
     540        18111 :         po = po_;
     541        18111 :         it = po->begin();
     542        18111 :         end = po->end();
     543              :     }
     544              :     else
     545              :     {
     546              :         state st;
     547         8534 :         st_.pop(st);
     548         8534 :         st_.pop(it);
     549         8534 :         st_.pop(po);
     550         8534 :         end = po->end();
     551         8534 :         switch(st)
     552              :         {
     553            6 :         default:
     554            6 :         case state::obj1: goto do_obj1;
     555          133 :         case state::obj2: goto do_obj2;
     556           20 :         case state::obj3: goto do_obj3;
     557         8349 :         case state::obj4: goto do_obj4;
     558            4 :         case state::obj5: goto do_obj5;
     559           22 :         case state::obj6: goto do_obj6;
     560              :             break;
     561              :         }
     562              :     }
     563        18117 : do_obj1:
     564        18117 :     if(BOOST_JSON_LIKELY(ss))
     565        18111 :         ss.append('{');
     566              :     else
     567            6 :         return suspend(
     568            6 :             state::obj1, it, po);
     569        18111 :     if(BOOST_JSON_UNLIKELY(
     570              :         it == end))
     571          557 :         goto do_obj6;
     572              :     for(;;)
     573              :     {
     574        39076 :         cs0_ = {
     575        19538 :             it->key().data(),
     576        39076 :             it->key().size() };
     577        19671 : do_obj2:
     578        19671 :         if(BOOST_JSON_UNLIKELY(
     579              :             ! write_string<StackEmpty>(ss)))
     580          133 :             return suspend(
     581          133 :                 state::obj2, it, po);
     582        19538 : do_obj3:
     583        19558 :         if(BOOST_JSON_LIKELY(ss))
     584        19538 :             ss.append(':');
     585              :         else
     586           20 :             return suspend(
     587           20 :                 state::obj3, it, po);
     588        27887 : do_obj4:
     589        27887 :         jv_ = &it->value();
     590        27887 :         if(BOOST_JSON_UNLIKELY(
     591              :             ! write_value<StackEmpty>(ss)))
     592         8349 :             return suspend(
     593         8349 :                 state::obj4, it, po);
     594        19538 :         ++it;
     595        19538 :         if(BOOST_JSON_UNLIKELY(it == end))
     596        17554 :             break;
     597         1984 : do_obj5:
     598         1988 :         if(BOOST_JSON_LIKELY(ss))
     599         1984 :             ss.append(',');
     600              :         else
     601            4 :             return suspend(
     602            4 :                 state::obj5, it, po);
     603              :     }
     604        18133 : do_obj6:
     605        18133 :     if(BOOST_JSON_LIKELY(ss))
     606              :     {
     607        18111 :         ss.append('}');
     608        18111 :         return true;
     609              :     }
     610           22 :     return suspend(
     611           22 :         state::obj6, it, po);
     612        26645 : }
     613              : 
     614              : template<bool StackEmpty>
     615              : bool
     616        63352 : serializer::
     617              : write_value(stream& ss)
     618              : {
     619        19638 :     if(StackEmpty || st_.empty())
     620              :     {
     621        44132 :         auto const& jv(*jv_);
     622        44132 :         switch(jv.kind())
     623              :         {
     624        18060 :         default:
     625              :         case kind::object:
     626        18060 :             po_ = &jv.get_object();
     627        18060 :             return write_object<true>(ss);
     628              : 
     629         3283 :         case kind::array:
     630         3283 :             pa_ = &jv.get_array();
     631         3283 :             return write_array<true>(ss);
     632              : 
     633        14543 :         case kind::string:
     634              :         {
     635        14543 :             auto const& js = jv.get_string();
     636        14543 :             cs0_ = { js.data(), js.size() };
     637        14543 :             return write_string<true>(ss);
     638              :         }
     639              : 
     640         3626 :         case kind::int64:
     641              :         case kind::uint64:
     642              :         case kind::double_:
     643         3626 :             return write_number<true>(ss);
     644              : 
     645          298 :         case kind::bool_:
     646          298 :             if(jv.get_bool())
     647              :             {
     648          135 :                 if(BOOST_JSON_LIKELY(
     649              :                     ss.remain() >= 4))
     650              :                 {
     651          121 :                     ss.append("true", 4);
     652          121 :                     return true;
     653              :                 }
     654           14 :                 return write_true<true>(ss);
     655              :             }
     656              :             else
     657              :             {
     658          163 :                 if(BOOST_JSON_LIKELY(
     659              :                     ss.remain() >= 5))
     660              :                 {
     661          145 :                     ss.append("false", 5);
     662          145 :                     return true;
     663              :                 }
     664           18 :                 return write_false<true>(ss);
     665              :             }
     666              : 
     667         4322 :         case kind::null:
     668         4322 :             if(BOOST_JSON_LIKELY(
     669              :                 ss.remain() >= 4))
     670              :             {
     671         4288 :                 ss.append("null", 4);
     672         4288 :                 return true;
     673              :             }
     674           34 :             return write_null<true>(ss);
     675              :         }
     676              :     }
     677              :     else
     678              :     {
     679              :         state st;
     680        19220 :         st_.peek(st);
     681        19220 :         switch(st)
     682              :         {
     683           34 :         default:
     684              :         case state::nul1: case state::nul2:
     685              :         case state::nul3: case state::nul4:
     686           34 :             return write_null<StackEmpty>(ss);
     687              : 
     688           14 :         case state::tru1: case state::tru2:
     689              :         case state::tru3: case state::tru4:
     690           14 :             return write_true<StackEmpty>(ss);
     691              : 
     692           18 :         case state::fal1: case state::fal2:
     693              :         case state::fal3: case state::fal4:
     694              :         case state::fal5:
     695           18 :             return write_false<StackEmpty>(ss);
     696              : 
     697         8706 :         case state::str1: case state::str2:
     698              :         case state::str3: case state::esc1:
     699              :         case state::utf1: case state::utf2:
     700              :         case state::utf3: case state::utf4:
     701              :         case state::utf5:
     702         8706 :             return write_string<StackEmpty>(ss);
     703              : 
     704          596 :         case state::num:
     705          596 :             return write_number<StackEmpty>(ss);
     706              : 
     707         1318 :         case state::arr1: case state::arr2:
     708              :         case state::arr3: case state::arr4:
     709         1318 :             return write_array<StackEmpty>(ss);
     710              : 
     711         8534 :         case state::obj1: case state::obj2:
     712              :         case state::obj3: case state::obj4:
     713              :         case state::obj5: case state::obj6:
     714         8534 :             return write_object<StackEmpty>(ss);
     715              :         }
     716              :     }
     717              : }
     718              : 
     719              : string_view
     720        30524 : serializer::
     721              : read_some(
     722              :     char* dest, std::size_t size)
     723              : {
     724              :     // If this goes off it means you forgot
     725              :     // to call reset() before seriailzing a
     726              :     // new value, or you never checked done()
     727              :     // to see if you should stop.
     728        30524 :     BOOST_ASSERT(! done_);
     729              : 
     730        30524 :     stream ss(dest, size);
     731        30524 :     if(st_.empty())
     732        20803 :         (this->*fn0_)(ss);
     733              :     else
     734         9721 :         (this->*fn1_)(ss);
     735        30522 :     if(st_.empty())
     736              :     {
     737        20801 :         done_ = true;
     738        20801 :         jv_ = nullptr;
     739              :     }
     740        30522 :     return string_view(
     741        30522 :         dest, ss.used(dest));
     742              : }
     743              : 
     744              : //----------------------------------------------------------
     745              : 
     746         1948 : serializer::
     747         1948 : serializer( serialize_options const& opts ) noexcept
     748         1948 :     : opts_(opts)
     749              : {
     750              :     // ensure room for \uXXXX escape plus one
     751              :     BOOST_STATIC_ASSERT(
     752              :         sizeof(serializer::buf_) >= 7);
     753         1948 : }
     754              : 
     755              : void
     756        20739 : serializer::
     757              : reset(value const* p) noexcept
     758              : {
     759        20739 :     pv_ = p;
     760        20739 :     fn0_ = &serializer::write_value<true>;
     761        20739 :     fn1_ = &serializer::write_value<false>;
     762              : 
     763        20739 :     jv_ = p;
     764        20739 :     st_.clear();
     765        20739 :     done_ = false;
     766        20739 : }
     767              : 
     768              : void
     769            5 : serializer::
     770              : reset(array const* p) noexcept
     771              : {
     772            5 :     pa_ = p;
     773            5 :     fn0_ = &serializer::write_array<true>;
     774            5 :     fn1_ = &serializer::write_array<false>;
     775            5 :     st_.clear();
     776            5 :     done_ = false;
     777            5 : }
     778              : 
     779              : void
     780           51 : serializer::
     781              : reset(object const* p) noexcept
     782              : {
     783           51 :     po_ = p;
     784           51 :     fn0_ = &serializer::write_object<true>;
     785           51 :     fn1_ = &serializer::write_object<false>;
     786           51 :     st_.clear();
     787           51 :     done_ = false;
     788           51 : }
     789              : 
     790              : void
     791            2 : serializer::
     792              : reset(string const* p) noexcept
     793              : {
     794            2 :     cs0_ = { p->data(), p->size() };
     795            2 :     fn0_ = &serializer::write_string<true>;
     796            2 :     fn1_ = &serializer::write_string<false>;
     797            2 :     st_.clear();
     798            2 :     done_ = false;
     799            2 : }
     800              : 
     801              : void
     802            1 : serializer::
     803              : reset(string_view sv) noexcept
     804              : {
     805            1 :     cs0_ = { sv.data(), sv.size() };
     806            1 :     fn0_ = &serializer::write_string<true>;
     807            1 :     fn1_ = &serializer::write_string<false>;
     808            1 :     st_.clear();
     809            1 :     done_ = false;
     810            1 : }
     811              : 
     812              : string_view
     813        30524 : serializer::
     814              : read(char* dest, std::size_t size)
     815              : {
     816        30524 :     if(! jv_)
     817              :     {
     818           64 :         static value const null;
     819           64 :         jv_ = &null;
     820              :     }
     821        30524 :     return read_some(dest, size);
     822              : }
     823              : 
     824              : } // namespace json
     825              : } // namespace boost
     826              : 
     827              : #ifdef _MSC_VER
     828              : #pragma warning(pop)
     829              : #endif
     830              : 
     831              : #endif
        

Generated by: LCOV version 2.1