LCOV - code coverage report
Current view: top level - json/impl - serializer.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 97.8 % 182 178 4
Test Date: 2026-03-05 09:04:27 Functions: 96.9 % 64 62 2

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2024 Dmitry Arkhipov (grisumbras@yandex.ru)
       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_HPP
      11                 : #define BOOST_JSON_IMPL_SERIALIZER_HPP
      12                 : 
      13                 : #include <boost/describe/enum_to_string.hpp>
      14                 : #include <boost/json/conversion.hpp>
      15                 : #include <cstddef>
      16                 : 
      17                 : namespace boost {
      18                 : namespace json {
      19                 : namespace detail {
      20                 : 
      21                 : enum class writer::state : char
      22                 : {
      23                 :     str1, str2, str3, esc1, utf1,
      24                 :     utf2, utf3, utf4, utf5,
      25                 :     lit,
      26                 :     arr1, arr2, arr3, arr4,
      27                 :     obj1, obj2, obj3, obj4, obj5, obj6
      28                 : };
      29                 : 
      30                 : bool
      31 HIT       11258 : writer::
      32                 : suspend(state st)
      33                 : {
      34           11258 :     st_.push(st);
      35           11257 :     return false;
      36                 : }
      37                 : 
      38                 : template<class U, class T>
      39                 : bool
      40           11875 : writer::
      41                 : suspend(state st, U u, T const* pt)
      42                 : {
      43           11875 :     st_.push(pt);
      44           11874 :     st_.push(u);
      45           11874 :     st_.push(st);
      46           11874 :     return false;
      47                 : }
      48                 : 
      49                 : template<class T, bool StackEmpty>
      50                 : bool
      51                 : write_impl(writer& w, stream& ss);
      52                 : 
      53                 : template<class T, bool StackEmpty>
      54                 : BOOST_FORCEINLINE
      55                 : bool
      56                 : write_impl(null_like_conversion_tag, writer& w, stream& ss)
      57                 : {
      58                 : #if defined(_MSC_VER)
      59                 : # pragma warning( push )
      60                 : # pragma warning( disable : 4127 )
      61                 : #endif
      62              14 :     if( StackEmpty || w.st_.empty() )
      63              20 :         return write_null(w, ss);
      64                 : #if defined(_MSC_VER)
      65                 : # pragma warning( pop )
      66                 : #endif
      67              14 :     return resume_buffer(w, ss);
      68                 : }
      69                 : 
      70                 : template<class T, bool StackEmpty>
      71                 : BOOST_FORCEINLINE
      72                 : bool
      73                 : write_impl(bool_conversion_tag, writer& w, stream& ss)
      74                 : {
      75 MIS           0 :     BOOST_ASSERT( w.p_ );
      76 HIT          97 :     auto const t = *reinterpret_cast<T const*>(w.p_);
      77                 : 
      78                 : #if defined(_MSC_VER)
      79                 : # pragma warning( push )
      80                 : # pragma warning( disable : 4127 )
      81                 : #endif
      82              61 :     if( StackEmpty || w.st_.empty() )
      83                 : #if defined(_MSC_VER)
      84                 : # pragma warning( pop )
      85                 : #endif
      86                 :     {
      87              67 :         if( t )
      88              58 :             return write_true(w, ss);
      89                 :         else
      90               9 :             return write_false(w, ss);
      91                 :     }
      92                 : 
      93              30 :     return resume_buffer(w, ss);
      94                 : }
      95                 : 
      96                 : template<class T, bool StackEmpty>
      97                 : BOOST_FORCEINLINE
      98                 : bool
      99                 : write_impl(integral_conversion_tag, writer& w, stream& ss0)
     100                 : {
     101                 : #if defined(_MSC_VER)
     102                 : # pragma warning( push )
     103                 : # pragma warning( disable : 4127 )
     104                 : #endif
     105             200 :     if( StackEmpty || w.st_.empty() )
     106                 : #if defined(_MSC_VER)
     107                 : # pragma warning( pop )
     108                 : #endif
     109                 :     {
     110               6 :         auto const& t = *reinterpret_cast<T const*>(w.p_);
     111                 : 
     112                 : #if defined(__clang__)
     113                 : # pragma clang diagnostic push
     114                 : # pragma clang diagnostic ignored "-Wsign-compare"
     115                 : #elif defined(__GNUC__)
     116                 : # pragma GCC diagnostic push
     117                 : # pragma GCC  diagnostic ignored "-Wsign-compare"
     118                 : #elif defined(_MSC_VER)
     119                 : # pragma warning( push )
     120                 : # pragma warning( disable : 4018 )
     121                 : # pragma warning( disable : 4127 )
     122                 : #endif
     123                 : 
     124             134 :         if( t < 0 )
     125                 :         {
     126                 :             // T is obviously signed, so this comparison is safe
     127               6 :             if( t >= (std::numeric_limits<std::int64_t>::min)() )
     128                 :             {
     129               6 :                 std::int64_t i = t;
     130               6 :                 return write_int64(w, ss0, i);
     131                 :             }
     132                 :         }
     133             334 :         else if( t <= (std::numeric_limits<std::uint64_t>::max)() )
     134                 :         {
     135             334 :             std::uint64_t u = t;
     136             334 :             return write_uint64(w, ss0, u);
     137                 :         }
     138                 : #if defined(__clang__)
     139                 : # pragma clang diagnostic pop
     140                 : #elif defined(__GNUC__)
     141                 : # pragma GCC diagnostic pop
     142                 : #elif defined(_MSC_VER)
     143                 : # pragma warning( pop )
     144                 : #endif
     145                 : 
     146                 : #if defined(_MSC_VER)
     147                 : # pragma warning( push )
     148                 : # pragma warning( disable : 4244 )
     149                 : #endif
     150 MIS           0 :         double d = t;
     151               0 :         return write_double(w, ss0, d);
     152                 : #if defined(_MSC_VER)
     153                 : # pragma warning( pop )
     154                 : #endif
     155                 :     }
     156                 : 
     157 HIT          66 :     return resume_buffer(w, ss0);
     158                 : }
     159                 : 
     160                 : template<class T, bool StackEmpty>
     161                 : BOOST_FORCEINLINE
     162                 : bool
     163                 : write_impl(floating_point_conversion_tag, writer& w, stream& ss0)
     164                 : {
     165                 : #if defined(_MSC_VER)
     166                 : # pragma warning( push )
     167                 : # pragma warning( disable : 4127 )
     168                 : #endif
     169              10 :     if( StackEmpty || w.st_.empty() )
     170                 : #if defined(_MSC_VER)
     171                 : # pragma warning( pop )
     172                 : #endif
     173                 :     {
     174              10 :         double d = *reinterpret_cast<T const*>(w.p_);
     175              10 :         return write_double(w, ss0, d);
     176                 :     }
     177                 : 
     178              10 :     return resume_buffer(w, ss0);
     179                 : }
     180                 : 
     181                 : template<class T, bool StackEmpty>
     182                 : BOOST_FORCEINLINE
     183                 : bool
     184                 : write_impl(string_like_conversion_tag, writer& w, stream& ss0)
     185                 : {
     186                 : #if defined(_MSC_VER)
     187                 : # pragma warning( push )
     188                 : # pragma warning( disable : 4127 )
     189                 : #endif
     190             112 :     if( StackEmpty || w.st_.empty() )
     191                 : #if defined(_MSC_VER)
     192                 : # pragma warning( pop )
     193                 : #endif
     194                 :     {
     195 MIS           0 :         string_view const sv = *reinterpret_cast<T const*>(w.p_);
     196 HIT          91 :         w.cs0_ = { sv.data(), sv.size() };
     197              91 :         return write_string(w, ss0);
     198                 :     }
     199                 : 
     200             112 :     return resume_string(w, ss0);
     201                 : }
     202                 : 
     203                 : template<class T, bool StackEmpty>
     204                 : BOOST_FORCEINLINE
     205                 : bool
     206                 : write_impl(sequence_conversion_tag, writer& w, stream& ss0)
     207                 : {
     208                 :     using It = iterator_type<T const>;
     209                 :     using Elem = value_type<T>;
     210                 : 
     211                 :     T const* pt;
     212            6080 :     local_stream ss(ss0);
     213              37 :     It it;
     214              17 :     It end;
     215                 : #if defined(_MSC_VER)
     216                 : # pragma warning( push )
     217                 : # pragma warning( disable : 4127 )
     218                 : #endif
     219            2656 :     if(StackEmpty || w.st_.empty())
     220                 :     {
     221                 : #if defined(_MSC_VER)
     222                 : # pragma warning( pop )
     223                 : #endif
     224            3424 :         BOOST_ASSERT( w.p_ );
     225            3424 :         pt = reinterpret_cast<T const*>(w.p_);
     226            3424 :         it = std::begin(*pt);
     227            6848 :         end = std::end(*pt);
     228                 :     }
     229                 :     else
     230                 :     {
     231                 :         writer::state st;
     232            2656 :         w.st_.pop(st);
     233            2656 :         w.st_.pop(it);
     234            2656 :         w.st_.pop(pt);
     235            2656 :         end = std::end(*pt);
     236            2656 :         switch(st)
     237                 :         {
     238              70 :         default:
     239              70 :         case writer::state::arr1: goto do_arr1;
     240            2314 :         case writer::state::arr2: goto do_arr2;
     241              40 :         case writer::state::arr3: goto do_arr3;
     242             232 :         case writer::state::arr4: goto do_arr4;
     243                 :             break;
     244                 :         }
     245                 :     }
     246            3494 : do_arr1:
     247            3494 :     if(BOOST_JSON_LIKELY(ss))
     248            3424 :         ss.append('[');
     249                 :     else
     250              70 :         return w.suspend(writer::state::arr1, it, pt);
     251            3424 :     if(it == end)
     252             507 :         goto do_arr4;
     253                 :     for(;;)
     254                 :     {
     255            4070 :         w.p_ = std::addressof(*it);
     256            6384 : do_arr2:
     257            6384 :         if( !write_impl<Elem, StackEmpty>(w, ss) )
     258            2315 :             return w.suspend(writer::state::arr2, it, pt);
     259            4069 :         if(BOOST_JSON_UNLIKELY( ++it == end ))
     260            2916 :             break;
     261            1153 : do_arr3:
     262            1193 :         if(BOOST_JSON_LIKELY(ss))
     263            1153 :             ss.append(',');
     264                 :         else
     265              40 :             return w.suspend(writer::state::arr3, it, pt);
     266                 :     }
     267            3655 : do_arr4:
     268            3655 :     if(BOOST_JSON_LIKELY(ss))
     269            3423 :         ss.append(']');
     270                 :     else
     271             232 :         return w.suspend(writer::state::arr4, it, pt);
     272            3423 :     return true;
     273            6080 : }
     274                 : 
     275                 : template<class T, bool StackEmpty>
     276                 : BOOST_FORCEINLINE
     277                 : bool
     278                 : write_impl(map_like_conversion_tag, writer& w, stream& ss0)
     279                 : {
     280                 :     using It = iterator_type<T const>;
     281                 :     using Mapped = mapped_type<T>;
     282                 : 
     283                 :     T const* pt;
     284           27292 :     local_stream ss(ss0);
     285              96 :     It it;
     286              96 :     It end;
     287                 : #if defined(_MSC_VER)
     288                 : # pragma warning( push )
     289                 : # pragma warning( disable : 4127 )
     290                 : #endif
     291            9120 :     if(StackEmpty || w.st_.empty())
     292                 : #if defined(_MSC_VER)
     293                 : # pragma warning( pop )
     294                 : #endif
     295                 :     {
     296           18172 :         BOOST_ASSERT( w.p_ );
     297           18172 :         pt = reinterpret_cast<T const*>(w.p_);
     298           18172 :         it = std::begin(*pt);
     299           36344 :         end = std::end(*pt);
     300                 :     }
     301                 :     else
     302                 :     {
     303                 :         writer::state st;
     304            9120 :         w.st_.pop(st);
     305            9120 :         w.st_.pop(it);
     306            9120 :         w.st_.pop(pt);
     307            9120 :         end = std::end(*pt);
     308            9120 :         switch(st)
     309                 :         {
     310              12 :         default:
     311              12 :         case writer::state::obj1: goto do_obj1;
     312             296 :         case writer::state::obj2: goto do_obj2;
     313              50 :         case writer::state::obj3: goto do_obj3;
     314            8700 :         case writer::state::obj4: goto do_obj4;
     315              16 :         case writer::state::obj5: goto do_obj5;
     316              46 :         case writer::state::obj6: goto do_obj6;
     317                 :             break;
     318                 :         }
     319                 :     }
     320           18184 : do_obj1:
     321           18184 :     if(BOOST_JSON_LIKELY( ss ))
     322           18172 :         ss.append('{');
     323                 :     else
     324              12 :         return w.suspend(writer::state::obj1, it, pt);
     325           18172 :     if(BOOST_JSON_UNLIKELY( it == end ))
     326             563 :         goto do_obj6;
     327            2133 :     for(;;)
     328                 :     {
     329                 :         {
     330                 :             using std::get;
     331           19742 :             string_view const sv = get<0>(*it);
     332           19742 :             w.cs0_ = { sv.data(), sv.size() };
     333                 :         }
     334                 :         if( true )
     335                 :         {
     336           19742 :             if(BOOST_JSON_UNLIKELY( !write_string(w, ss) ))
     337             173 :                 return w.suspend(writer::state::obj2, it, pt);
     338                 :         }
     339                 :         else
     340                 :         {
     341             296 : do_obj2:
     342             296 :             if(BOOST_JSON_UNLIKELY( !resume_string(w, ss) ))
     343             123 :                 return w.suspend(writer::state::obj2, it, pt);
     344                 :         }
     345             173 : do_obj3:
     346           19792 :         if(BOOST_JSON_LIKELY(ss))
     347           19742 :             ss.append(':');
     348                 :         else
     349              50 :             return w.suspend(writer::state::obj3, it, pt);
     350           28442 : do_obj4:
     351                 :         {
     352                 :             using std::get;
     353           28442 :             w.p_ = std::addressof( get<1>(*it) );
     354                 :         }
     355           28442 :         if(BOOST_JSON_UNLIKELY(( !write_impl<Mapped, StackEmpty>(w, ss) )))
     356            8700 :             return w.suspend(writer::state::obj4, it, pt);
     357           19742 :         ++it;
     358           19742 :         if(BOOST_JSON_UNLIKELY(it == end))
     359           17609 :             break;
     360            2133 : do_obj5:
     361            2149 :         if(BOOST_JSON_LIKELY(ss))
     362            2133 :             ss.append(',');
     363                 :         else
     364              16 :             return w.suspend(writer::state::obj5, it, pt);
     365                 :     }
     366           18218 : do_obj6:
     367           18218 :     if(BOOST_JSON_LIKELY( ss ))
     368                 :     {
     369           18172 :         ss.append('}');
     370           18172 :         return true;
     371                 :     }
     372              46 :     return w.suspend(writer::state::obj6, it, pt);
     373           27292 : }
     374                 : 
     375                 : template< class T, bool StackEmpty >
     376                 : struct serialize_tuple_elem_helper
     377                 : {
     378                 :     writer& w;
     379                 :     stream& ss;
     380                 :     T const* pt;
     381                 : 
     382                 :     template< std::size_t I >
     383                 :     bool
     384             258 :     operator()( std::integral_constant<std::size_t, I> ) const
     385                 :     {
     386                 :         using std::get;
     387             258 :         w.p_ = std::addressof( get<I>(*pt) );
     388                 : 
     389                 :         using Elem = tuple_element_t<I, T>;
     390             258 :         return write_impl<Elem, StackEmpty>(w, ss);
     391                 :     }
     392                 : };
     393                 : 
     394                 : template<class T, bool StackEmpty>
     395                 : BOOST_FORCEINLINE
     396                 : bool
     397                 : write_impl(tuple_conversion_tag, writer& w, stream& ss0)
     398                 : {
     399                 :     T const* pt;
     400             174 :     local_stream ss(ss0);
     401                 :     std::size_t cur;
     402              64 :     constexpr std::size_t N = std::tuple_size<T>::value;
     403                 : #if defined(_MSC_VER)
     404                 : # pragma warning( push )
     405                 : # pragma warning( disable : 4127 )
     406                 : #endif
     407             110 :     if(StackEmpty || w.st_.empty())
     408                 :     {
     409                 : #if defined(_MSC_VER)
     410                 : # pragma warning( pop )
     411                 : #endif
     412              76 :         BOOST_ASSERT( w.p_ );
     413              76 :         pt = reinterpret_cast<T const*>(w.p_);
     414              76 :         cur = 0;
     415                 :     }
     416                 :     else
     417                 :     {
     418                 :         writer::state st;
     419              98 :         w.st_.pop(st);
     420              98 :         w.st_.pop(cur);
     421              98 :         w.st_.pop(pt);
     422              98 :         switch(st)
     423                 :         {
     424               2 :         default:
     425               2 :         case writer::state::arr1: goto do_arr1;
     426              82 :         case writer::state::arr2: goto do_arr2;
     427               8 :         case writer::state::arr3: goto do_arr3;
     428               6 :         case writer::state::arr4: goto do_arr4;
     429                 :             break;
     430                 :         }
     431                 :     }
     432              78 : do_arr1:
     433              78 :     if(BOOST_JSON_LIKELY(ss))
     434              76 :         ss.append('[');
     435                 :     else
     436               2 :         return w.suspend(writer::state::arr1, cur, pt);
     437             100 :     for(;;)
     438                 :     {
     439             258 : do_arr2:
     440                 :         {
     441             258 :             bool const stop = !mp11::mp_with_index<N>(
     442                 :                 cur,
     443                 :                 serialize_tuple_elem_helper<T, StackEmpty>{w, ss, pt});
     444             258 :             if(BOOST_JSON_UNLIKELY( stop ))
     445              82 :                 return w.suspend(writer::state::arr2, cur, pt);
     446                 :         }
     447             176 :         if(BOOST_JSON_UNLIKELY( ++cur == N ))
     448              76 :             break;
     449             100 : do_arr3:
     450             108 :         if(BOOST_JSON_LIKELY(ss))
     451             100 :             ss.append(',');
     452                 :         else
     453               8 :             return w.suspend(writer::state::arr3, cur, pt);
     454                 :     }
     455              82 : do_arr4:
     456              82 :     if(BOOST_JSON_LIKELY(ss))
     457              76 :         ss.append(']');
     458                 :     else
     459               6 :         return w.suspend(writer::state::arr4, cur, pt);
     460              76 :     return true;
     461             174 : }
     462                 : 
     463                 : template< class T, bool StackEmpty >
     464                 : struct serialize_struct_elem_helper
     465                 : {
     466                 :     writer& w;
     467                 :     local_stream& ss;
     468                 :     T const* pt;
     469                 :     writer::state st;
     470                 : 
     471                 :     template< std::size_t I >
     472                 :     writer::state
     473                 :     operator()( std::integral_constant<std::size_t, I> ) const
     474                 :     {
     475                 :         using Ds = described_members<T>;
     476                 :         using D = mp11::mp_at_c<Ds, I>;
     477                 :         using M = described_member_t<T, D>;
     478                 : 
     479                 :         switch(st)
     480                 :         {
     481                 :         case writer::state::obj2: goto do_obj2;
     482                 :         case writer::state::obj3: goto do_obj3;
     483                 :         case writer::state::obj4: goto do_obj4;
     484                 :         default: break;
     485                 :         }
     486                 : 
     487                 :         {
     488                 :             string_view const sv = D::name;
     489                 :             w.cs0_ = { sv.data(), sv.size() };
     490                 :         }
     491                 :         if( true )
     492                 :         {
     493                 :             if(BOOST_JSON_UNLIKELY( !write_string(w, ss) ))
     494                 :                 return writer::state::obj2;
     495                 :         }
     496                 :         else
     497                 :         {
     498                 : do_obj2:
     499                 :             if(BOOST_JSON_UNLIKELY( !resume_string(w, ss) ))
     500                 :                 return writer::state::obj2;
     501                 :         }
     502                 : do_obj3:
     503                 :         if(BOOST_JSON_LIKELY(ss))
     504                 :             ss.append(':');
     505                 :         else
     506                 :             return writer::state::obj3;
     507                 : do_obj4:
     508                 :         w.p_ = std::addressof( pt->* D::pointer );
     509                 :         if(BOOST_JSON_UNLIKELY((
     510                 :                 !write_impl<M, StackEmpty>(w, ss) )))
     511                 :             return writer::state::obj4;
     512                 : 
     513                 :         return writer::state{};
     514                 :     }
     515                 : };
     516                 : 
     517                 : template<class T, bool StackEmpty>
     518                 : BOOST_FORCEINLINE
     519                 : bool
     520                 : write_impl(described_class_conversion_tag, writer& w, stream& ss0)
     521                 : {
     522                 :     using Ds = described_members<T>;
     523                 : 
     524                 :     T const* pt;
     525                 :     local_stream ss(ss0);
     526                 :     std::size_t cur;
     527                 :     constexpr std::size_t N = mp11::mp_size<Ds>::value;
     528                 :     writer::state st;
     529                 : #if defined(_MSC_VER)
     530                 : # pragma warning( push )
     531                 : # pragma warning( disable : 4127 )
     532                 : #endif
     533                 :     if(StackEmpty || w.st_.empty())
     534                 : #if defined(_MSC_VER)
     535                 : # pragma warning( pop )
     536                 : #endif
     537                 :     {
     538                 :         BOOST_ASSERT( w.p_ );
     539                 :         pt = reinterpret_cast<T const*>(w.p_);
     540                 :         cur = 0;
     541                 :     }
     542                 :     else
     543                 :     {
     544                 :         w.st_.pop(st);
     545                 :         w.st_.pop(cur);
     546                 :         w.st_.pop(pt);
     547                 :         switch(st)
     548                 :         {
     549                 :         default:
     550                 :         case writer::state::obj1: goto do_obj1;
     551                 :         case writer::state::obj2: // fall through
     552                 :         case writer::state::obj3: // fall through
     553                 :         case writer::state::obj4: goto do_obj2;
     554                 :         case writer::state::obj5: goto do_obj5;
     555                 :         case writer::state::obj6: goto do_obj6;
     556                 :             break;
     557                 :         }
     558                 :     }
     559                 : do_obj1:
     560                 :     if(BOOST_JSON_LIKELY( ss ))
     561                 :         ss.append('{');
     562                 :     else
     563                 :         return w.suspend(writer::state::obj1, cur, pt);
     564                 :     if(BOOST_JSON_UNLIKELY( cur == N ))
     565                 :         goto do_obj6;
     566                 :     for(;;)
     567                 :     {
     568                 :         st = {};
     569                 : do_obj2:
     570                 :         st = mp11::mp_with_index<N>(
     571                 :             cur,
     572                 :             serialize_struct_elem_helper<T, StackEmpty>{w, ss, pt, st});
     573                 :         if(BOOST_JSON_UNLIKELY( st != writer::state{} ))
     574                 :             return w.suspend(st, cur, pt);
     575                 :         ++cur;
     576                 :         if(BOOST_JSON_UNLIKELY(cur == N))
     577                 :             break;
     578                 : do_obj5:
     579                 :         if(BOOST_JSON_LIKELY(ss))
     580                 :             ss.append(',');
     581                 :         else
     582                 :             return w.suspend(writer::state::obj5, cur, pt);
     583                 :     }
     584                 : do_obj6:
     585                 :     if(BOOST_JSON_LIKELY( ss ))
     586                 :     {
     587                 :         ss.append('}');
     588                 :         return true;
     589                 :     }
     590                 :     return w.suspend(writer::state::obj6, cur, pt);
     591                 : }
     592                 : 
     593                 : template<class T, bool StackEmpty>
     594                 : BOOST_FORCEINLINE
     595                 : bool
     596                 : write_impl(described_enum_conversion_tag, writer& w, stream& ss)
     597                 : {
     598                 : #ifdef BOOST_DESCRIBE_CXX14
     599                 :     using Integer = typename std::underlying_type<T>::type;
     600                 : 
     601                 : #if defined(_MSC_VER)
     602                 : # pragma warning( push )
     603                 : # pragma warning( disable : 4127 )
     604                 : #endif
     605                 :     if(StackEmpty || w.st_.empty())
     606                 : #if defined(_MSC_VER)
     607                 : # pragma warning( pop )
     608                 : #endif
     609                 :     {
     610                 :         BOOST_ASSERT( w.p_ );
     611                 :         T const* pt = reinterpret_cast<T const*>(w.p_);
     612                 :         char const* const name = describe::enum_to_string(*pt, nullptr);
     613                 :         if( name )
     614                 :         {
     615                 :             string_view const sv = name;
     616                 :             w.cs0_ = { sv.data(), sv.size() };
     617                 :             return write_string(w, ss);
     618                 :         }
     619                 :         else
     620                 :         {
     621                 :             Integer n = static_cast<Integer>(*pt);
     622                 :             w.p_ = &n;
     623                 :             return write_impl<Integer, true>(w, ss);
     624                 :         }
     625                 :     }
     626                 :     else
     627                 :     {
     628                 :         writer::state st;
     629                 :         w.st_.peek(st);
     630                 :         if( st == writer::state::lit )
     631                 :             return write_impl<Integer, false>(w, ss);
     632                 :         else
     633                 :             return resume_string(w, ss);
     634                 :     }
     635                 : #else // BOOST_DESCRIBE_CXX14
     636                 :     (void)w;
     637                 :     (void)ss;
     638                 :     static_assert(
     639                 :         !std::is_same<T, T>::value,
     640                 :         "described enums require C++14 support");
     641                 :     return false;
     642                 : #endif // BOOST_DESCRIBE_CXX14
     643                 : }
     644                 : 
     645                 : template< class T, bool StackEmpty >
     646                 : struct serialize_variant_elem_helper
     647                 : {
     648                 :     writer& w;
     649                 :     stream& ss;
     650                 : 
     651                 :     template<class Elem>
     652                 :     bool
     653                 :     operator()(Elem const& x) const
     654                 :     {
     655                 :         w.p_ = std::addressof(x);
     656                 :         return write_impl<Elem, true>(w, ss);
     657                 :     }
     658                 : };
     659                 : 
     660                 : template< class T >
     661                 : struct serialize_variant_elem_helper<T, false>
     662                 : {
     663                 :     writer& w;
     664                 :     stream& ss;
     665                 : 
     666                 :     template< std::size_t I >
     667                 :     bool
     668                 :     operator()( std::integral_constant<std::size_t, I> ) const
     669                 :     {
     670                 :         using std::get;
     671                 :         using Elem = remove_cvref<decltype(get<I>(
     672                 :             std::declval<T const&>() ))>;
     673                 :         return write_impl<Elem, false>(w, ss);
     674                 :     }
     675                 : };
     676                 : 
     677                 : template<class T, bool StackEmpty>
     678                 : BOOST_FORCEINLINE
     679                 : bool
     680                 : write_impl(variant_conversion_tag, writer& w, stream& ss)
     681                 : {
     682                 :     T const* pt;
     683                 : 
     684                 :     using Index = remove_cvref<decltype( pt->index() )>;
     685                 : 
     686                 : #if defined(_MSC_VER)
     687                 : # pragma warning( push )
     688                 : # pragma warning( disable : 4127 )
     689                 : #endif
     690                 :     if(StackEmpty || w.st_.empty())
     691                 : #if defined(_MSC_VER)
     692                 : # pragma warning( pop )
     693                 : #endif
     694                 :     {
     695                 :         BOOST_ASSERT( w.p_ );
     696                 :         pt = reinterpret_cast<T const*>(w.p_);
     697                 :         if(BOOST_JSON_LIKELY((
     698                 :                 visit(serialize_variant_elem_helper<T, true>{w, ss}, *pt))))
     699                 :             return true;
     700                 : 
     701                 :         Index const ix = pt->index();
     702                 :         w.st_.push(ix);
     703                 :         return false;
     704                 :     }
     705                 :     else
     706                 :     {
     707                 :         Index ix;
     708                 :         w.st_.pop(ix);
     709                 : 
     710                 :         constexpr std::size_t N = mp11::mp_size<T>::value;
     711                 :         if(BOOST_JSON_LIKELY(( mp11::mp_with_index<N>(
     712                 :                 ix,
     713                 :                 serialize_variant_elem_helper<T, false>{w, ss}))))
     714                 :             return true;
     715                 : 
     716                 :         w.st_.push(ix);
     717                 :         return false;
     718                 :     }
     719                 : }
     720                 : 
     721                 : template<class T, bool StackEmpty>
     722                 : BOOST_FORCEINLINE
     723                 : bool
     724                 : write_impl(optional_conversion_tag, writer& w, stream& ss)
     725                 : {
     726                 :     using Elem = value_result_type<T>;
     727                 : 
     728                 :     bool done;
     729                 :     bool has_value;
     730                 : 
     731                 : #if defined(_MSC_VER)
     732                 : # pragma warning( push )
     733                 : # pragma warning( disable : 4127 )
     734                 : #endif
     735                 :     if(StackEmpty || w.st_.empty())
     736                 : #if defined(_MSC_VER)
     737                 : # pragma warning( pop )
     738                 : #endif
     739                 :     {
     740                 :         BOOST_ASSERT( w.p_ );
     741                 :         T const* pt = reinterpret_cast<T const*>(w.p_);
     742                 :         has_value = static_cast<bool>(*pt);
     743                 :         if( has_value )
     744                 :         {
     745                 :             w.p_ = std::addressof( *(*pt) );
     746                 :             done = write_impl<Elem, true>(w, ss);
     747                 :         }
     748                 :         else
     749                 :         {
     750                 :             w.p_ = nullptr;
     751                 :             done = write_impl<std::nullptr_t, true>(w, ss);;
     752                 :         }
     753                 :     }
     754                 :     else
     755                 :     {
     756                 :         w.st_.pop(has_value);
     757                 : 
     758                 :         if( has_value )
     759                 :             done = write_impl<Elem, false>(w, ss);
     760                 :         else
     761                 :             done = write_impl<std::nullptr_t, false>(w, ss);
     762                 :     }
     763                 : 
     764                 :     if(BOOST_JSON_UNLIKELY( !done ))
     765                 :         w.st_.push(has_value);
     766                 : 
     767                 :     return done;
     768                 : }
     769                 : 
     770                 : template<class T, bool StackEmpty>
     771                 : BOOST_FORCEINLINE
     772                 : bool
     773                 : write_impl(path_conversion_tag, writer& w, stream& ss)
     774                 : {
     775                 : #if defined(_MSC_VER)
     776                 : # pragma warning( push )
     777                 : # pragma warning( disable : 4127 )
     778                 : #endif
     779                 :     if(StackEmpty || w.st_.empty())
     780                 : #if defined(_MSC_VER)
     781                 : # pragma warning( pop )
     782                 : #endif
     783                 :     {
     784                 :         BOOST_ASSERT( w.p_ );
     785                 :         T const* pt = reinterpret_cast<T const*>(w.p_);
     786                 : 
     787                 :         std::string const s = pt->generic_string();
     788                 :         w.cs0_ = { s.data(), s.size() };
     789                 :         if(BOOST_JSON_LIKELY( write_string(w, ss) ))
     790                 :             return true;
     791                 : 
     792                 :         std::size_t const used = w.cs0_.used( s.data() );
     793                 :         w.st_.push( used );
     794                 :         w.st_.push( std::move(s) );
     795                 :         return false;
     796                 :     }
     797                 :     else
     798                 :     {
     799                 :         std::string s;
     800                 :         std::size_t used;
     801                 :         w.st_.pop( s );
     802                 :         w.st_.pop( used );
     803                 : 
     804                 :         w.cs0_ = { s.data(), s.size() };
     805                 :         w.cs0_.skip(used);
     806                 : 
     807                 :         if(BOOST_JSON_LIKELY( resume_string(w, ss) ))
     808                 :             return true;
     809                 : 
     810                 :         used = w.cs0_.used( s.data() );
     811                 :         w.st_.push( used );
     812                 :         w.st_.push( std::move(s) );
     813                 :         return false;
     814                 :     }
     815                 : }
     816                 : 
     817                 : template<class T, bool StackEmpty>
     818                 : bool
     819           35616 : write_impl(writer& w, stream& ss)
     820                 : {
     821                 :     using cat = detail::generic_conversion_category<T, detail::no_context>;
     822           35615 :     return write_impl<T, StackEmpty>( cat(), w, ss );
     823                 : }
     824                 : 
     825                 : } // namespace detail
     826                 : 
     827                 : template<class T>
     828                 : void
     829             219 : serializer::reset(T const* p) noexcept
     830                 : {
     831                 :     BOOST_STATIC_ASSERT( !std::is_pointer<T>::value );
     832                 :     BOOST_STATIC_ASSERT( std::is_object<T>::value );
     833                 : 
     834             219 :     p_ = p;
     835             219 :     fn0_ = &detail::write_impl<T, true>;
     836             219 :     fn1_ = &detail::write_impl<T, false>;
     837             219 :     st_.clear();
     838             219 :     done_ = false;
     839             219 : }
     840                 : 
     841                 : } // namespace json
     842                 : } // namespace boost
     843                 : 
     844                 : #endif // BOOST_JSON_IMPL_SERIALIZER_HPP
        

Generated by: LCOV version 2.3