File indexing completed on 2025-09-17 08:34:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_JSON_IMPL_SERIALIZER_HPP
0011 #define BOOST_JSON_IMPL_SERIALIZER_HPP
0012
0013 #include <boost/describe/enum_to_string.hpp>
0014 #include <boost/json/conversion.hpp>
0015 #include <cstddef>
0016
0017 namespace boost {
0018 namespace json {
0019 namespace detail {
0020
0021 enum class writer::state : char
0022 {
0023 str1, str2, str3, esc1, utf1,
0024 utf2, utf3, utf4, utf5,
0025 lit,
0026 arr1, arr2, arr3, arr4,
0027 obj1, obj2, obj3, obj4, obj5, obj6
0028 };
0029
0030 bool
0031 writer::
0032 suspend(state st)
0033 {
0034 st_.push(st);
0035 return false;
0036 }
0037
0038 template<class U, class T>
0039 bool
0040 writer::
0041 suspend(state st, U u, T const* pt)
0042 {
0043 st_.push(pt);
0044 st_.push(u);
0045 st_.push(st);
0046 return false;
0047 }
0048
0049 template<class T, bool StackEmpty>
0050 bool
0051 write_impl(writer& w, stream& ss);
0052
0053 template<class T, bool StackEmpty>
0054 BOOST_FORCEINLINE
0055 bool
0056 write_impl(null_like_conversion_tag, writer& w, stream& ss)
0057 {
0058 #if defined(_MSC_VER)
0059 # pragma warning( push )
0060 # pragma warning( disable : 4127 )
0061 #endif
0062 if( StackEmpty || w.st_.empty() )
0063 return write_null(w, ss);
0064 #if defined(_MSC_VER)
0065 # pragma warning( pop )
0066 #endif
0067 return resume_buffer(w, ss);
0068 }
0069
0070 template<class T, bool StackEmpty>
0071 BOOST_FORCEINLINE
0072 bool
0073 write_impl(bool_conversion_tag, writer& w, stream& ss)
0074 {
0075 BOOST_ASSERT( w.p_ );
0076 auto const t = *reinterpret_cast<T const*>(w.p_);
0077
0078 #if defined(_MSC_VER)
0079 # pragma warning( push )
0080 # pragma warning( disable : 4127 )
0081 #endif
0082 if( StackEmpty || w.st_.empty() )
0083 #if defined(_MSC_VER)
0084 # pragma warning( pop )
0085 #endif
0086 {
0087 if( t )
0088 return write_true(w, ss);
0089 else
0090 return write_false(w, ss);
0091 }
0092
0093 return resume_buffer(w, ss);
0094 }
0095
0096 template<class T, bool StackEmpty>
0097 BOOST_FORCEINLINE
0098 bool
0099 write_impl(integral_conversion_tag, writer& w, stream& ss0)
0100 {
0101 #if defined(_MSC_VER)
0102 # pragma warning( push )
0103 # pragma warning( disable : 4127 )
0104 #endif
0105 if( StackEmpty || w.st_.empty() )
0106 #if defined(_MSC_VER)
0107 # pragma warning( pop )
0108 #endif
0109 {
0110 auto const& t = *reinterpret_cast<T const*>(w.p_);
0111
0112 #if defined(__clang__)
0113 # pragma clang diagnostic push
0114 # pragma clang diagnostic ignored "-Wsign-compare"
0115 #elif defined(__GNUC__)
0116 # pragma GCC diagnostic push
0117 # pragma GCC diagnostic ignored "-Wsign-compare"
0118 #elif defined(_MSC_VER)
0119 # pragma warning( push )
0120 # pragma warning( disable : 4018 )
0121 # pragma warning( disable : 4127 )
0122 #endif
0123
0124 if( t < 0 )
0125 {
0126
0127 if( t >= (std::numeric_limits<std::int64_t>::min)() )
0128 {
0129 std::int64_t i = t;
0130 return write_int64(w, ss0, i);
0131 }
0132 }
0133 else if( t <= (std::numeric_limits<std::uint64_t>::max)() )
0134 {
0135 std::uint64_t u = t;
0136 return write_uint64(w, ss0, u);
0137 }
0138 #if defined(__clang__)
0139 # pragma clang diagnostic pop
0140 #elif defined(__GNUC__)
0141 # pragma GCC diagnostic pop
0142 #elif defined(_MSC_VER)
0143 # pragma warning( pop )
0144 #endif
0145
0146 #if defined(_MSC_VER)
0147 # pragma warning( push )
0148 # pragma warning( disable : 4244 )
0149 #endif
0150 double d = t;
0151 return write_double(w, ss0, d);
0152 #if defined(_MSC_VER)
0153 # pragma warning( pop )
0154 #endif
0155 }
0156
0157 return resume_buffer(w, ss0);
0158 }
0159
0160 template<class T, bool StackEmpty>
0161 BOOST_FORCEINLINE
0162 bool
0163 write_impl(floating_point_conversion_tag, writer& w, stream& ss0)
0164 {
0165 #if defined(_MSC_VER)
0166 # pragma warning( push )
0167 # pragma warning( disable : 4127 )
0168 #endif
0169 if( StackEmpty || w.st_.empty() )
0170 #if defined(_MSC_VER)
0171 # pragma warning( pop )
0172 #endif
0173 {
0174 double d = *reinterpret_cast<T const*>(w.p_);
0175 return write_double(w, ss0, d);
0176 }
0177
0178 return resume_buffer(w, ss0);
0179 }
0180
0181 template<class T, bool StackEmpty>
0182 BOOST_FORCEINLINE
0183 bool
0184 write_impl(string_like_conversion_tag, writer& w, stream& ss0)
0185 {
0186 #if defined(_MSC_VER)
0187 # pragma warning( push )
0188 # pragma warning( disable : 4127 )
0189 #endif
0190 if( StackEmpty || w.st_.empty() )
0191 #if defined(_MSC_VER)
0192 # pragma warning( pop )
0193 #endif
0194 {
0195 string_view const sv = *reinterpret_cast<T const*>(w.p_);
0196 w.cs0_ = { sv.data(), sv.size() };
0197 return write_string(w, ss0);
0198 }
0199
0200 return resume_string(w, ss0);
0201 }
0202
0203 template<class T, bool StackEmpty>
0204 BOOST_FORCEINLINE
0205 bool
0206 write_impl(sequence_conversion_tag, writer& w, stream& ss0)
0207 {
0208 using It = iterator_type<T const>;
0209 using Elem = value_type<T>;
0210
0211 T const* pt;
0212 local_stream ss(ss0);
0213 It it;
0214 It end;
0215 #if defined(_MSC_VER)
0216 # pragma warning( push )
0217 # pragma warning( disable : 4127 )
0218 #endif
0219 if(StackEmpty || w.st_.empty())
0220 {
0221 #if defined(_MSC_VER)
0222 # pragma warning( pop )
0223 #endif
0224 BOOST_ASSERT( w.p_ );
0225 pt = reinterpret_cast<T const*>(w.p_);
0226 it = std::begin(*pt);
0227 end = std::end(*pt);
0228 }
0229 else
0230 {
0231 writer::state st;
0232 w.st_.pop(st);
0233 w.st_.pop(it);
0234 w.st_.pop(pt);
0235 end = std::end(*pt);
0236 switch(st)
0237 {
0238 default:
0239 case writer::state::arr1: goto do_arr1;
0240 case writer::state::arr2: goto do_arr2;
0241 case writer::state::arr3: goto do_arr3;
0242 case writer::state::arr4: goto do_arr4;
0243 break;
0244 }
0245 }
0246 do_arr1:
0247 if(BOOST_JSON_LIKELY(ss))
0248 ss.append('[');
0249 else
0250 return w.suspend(writer::state::arr1, it, pt);
0251 if(it == end)
0252 goto do_arr4;
0253 for(;;)
0254 {
0255 w.p_ = std::addressof(*it);
0256 do_arr2:
0257 if( !write_impl<Elem, StackEmpty>(w, ss) )
0258 return w.suspend(writer::state::arr2, it, pt);
0259 if(BOOST_JSON_UNLIKELY( ++it == end ))
0260 break;
0261 do_arr3:
0262 if(BOOST_JSON_LIKELY(ss))
0263 ss.append(',');
0264 else
0265 return w.suspend(writer::state::arr3, it, pt);
0266 }
0267 do_arr4:
0268 if(BOOST_JSON_LIKELY(ss))
0269 ss.append(']');
0270 else
0271 return w.suspend(writer::state::arr4, it, pt);
0272 return true;
0273 }
0274
0275 template<class T, bool StackEmpty>
0276 BOOST_FORCEINLINE
0277 bool
0278 write_impl(map_like_conversion_tag, writer& w, stream& ss0)
0279 {
0280 using It = iterator_type<T const>;
0281 using Mapped = mapped_type<T>;
0282
0283 T const* pt;
0284 local_stream ss(ss0);
0285 It it;
0286 It end;
0287 #if defined(_MSC_VER)
0288 # pragma warning( push )
0289 # pragma warning( disable : 4127 )
0290 #endif
0291 if(StackEmpty || w.st_.empty())
0292 #if defined(_MSC_VER)
0293 # pragma warning( pop )
0294 #endif
0295 {
0296 BOOST_ASSERT( w.p_ );
0297 pt = reinterpret_cast<T const*>(w.p_);
0298 it = std::begin(*pt);
0299 end = std::end(*pt);
0300 }
0301 else
0302 {
0303 writer::state st;
0304 w.st_.pop(st);
0305 w.st_.pop(it);
0306 w.st_.pop(pt);
0307 end = std::end(*pt);
0308 switch(st)
0309 {
0310 default:
0311 case writer::state::obj1: goto do_obj1;
0312 case writer::state::obj2: goto do_obj2;
0313 case writer::state::obj3: goto do_obj3;
0314 case writer::state::obj4: goto do_obj4;
0315 case writer::state::obj5: goto do_obj5;
0316 case writer::state::obj6: goto do_obj6;
0317 break;
0318 }
0319 }
0320 do_obj1:
0321 if(BOOST_JSON_LIKELY( ss ))
0322 ss.append('{');
0323 else
0324 return w.suspend(writer::state::obj1, it, pt);
0325 if(BOOST_JSON_UNLIKELY( it == end ))
0326 goto do_obj6;
0327 for(;;)
0328 {
0329 {
0330 using std::get;
0331 string_view const sv = get<0>(*it);
0332 w.cs0_ = { sv.data(), sv.size() };
0333 }
0334 if( true )
0335 {
0336 if(BOOST_JSON_UNLIKELY( !write_string(w, ss) ))
0337 return w.suspend(writer::state::obj2, it, pt);
0338 }
0339 else
0340 {
0341 do_obj2:
0342 if(BOOST_JSON_UNLIKELY( !resume_string(w, ss) ))
0343 return w.suspend(writer::state::obj2, it, pt);
0344 }
0345 do_obj3:
0346 if(BOOST_JSON_LIKELY(ss))
0347 ss.append(':');
0348 else
0349 return w.suspend(writer::state::obj3, it, pt);
0350 do_obj4:
0351 {
0352 using std::get;
0353 w.p_ = std::addressof( get<1>(*it) );
0354 }
0355 if(BOOST_JSON_UNLIKELY(( !write_impl<Mapped, StackEmpty>(w, ss) )))
0356 return w.suspend(writer::state::obj4, it, pt);
0357 ++it;
0358 if(BOOST_JSON_UNLIKELY(it == end))
0359 break;
0360 do_obj5:
0361 if(BOOST_JSON_LIKELY(ss))
0362 ss.append(',');
0363 else
0364 return w.suspend(writer::state::obj5, it, pt);
0365 }
0366 do_obj6:
0367 if(BOOST_JSON_LIKELY( ss ))
0368 {
0369 ss.append('}');
0370 return true;
0371 }
0372 return w.suspend(writer::state::obj6, it, pt);
0373 }
0374
0375 template< class T, bool StackEmpty >
0376 struct serialize_tuple_elem_helper
0377 {
0378 writer& w;
0379 stream& ss;
0380 T const* pt;
0381
0382 template< std::size_t I >
0383 bool
0384 operator()( std::integral_constant<std::size_t, I> ) const
0385 {
0386 using std::get;
0387 w.p_ = std::addressof( get<I>(*pt) );
0388
0389 using Elem = tuple_element_t<I, T>;
0390 return write_impl<Elem, StackEmpty>(w, ss);
0391 }
0392 };
0393
0394 template<class T, bool StackEmpty>
0395 BOOST_FORCEINLINE
0396 bool
0397 write_impl(tuple_conversion_tag, writer& w, stream& ss0)
0398 {
0399 T const* pt;
0400 local_stream ss(ss0);
0401 std::size_t cur;
0402 constexpr std::size_t N = std::tuple_size<T>::value;
0403 #if defined(_MSC_VER)
0404 # pragma warning( push )
0405 # pragma warning( disable : 4127 )
0406 #endif
0407 if(StackEmpty || w.st_.empty())
0408 {
0409 #if defined(_MSC_VER)
0410 # pragma warning( pop )
0411 #endif
0412 BOOST_ASSERT( w.p_ );
0413 pt = reinterpret_cast<T const*>(w.p_);
0414 cur = 0;
0415 }
0416 else
0417 {
0418 writer::state st;
0419 w.st_.pop(st);
0420 w.st_.pop(cur);
0421 w.st_.pop(pt);
0422 switch(st)
0423 {
0424 default:
0425 case writer::state::arr1: goto do_arr1;
0426 case writer::state::arr2: goto do_arr2;
0427 case writer::state::arr3: goto do_arr3;
0428 case writer::state::arr4: goto do_arr4;
0429 break;
0430 }
0431 }
0432 do_arr1:
0433 if(BOOST_JSON_LIKELY(ss))
0434 ss.append('[');
0435 else
0436 return w.suspend(writer::state::arr1, cur, pt);
0437 for(;;)
0438 {
0439 do_arr2:
0440 {
0441 bool const stop = !mp11::mp_with_index<N>(
0442 cur,
0443 serialize_tuple_elem_helper<T, StackEmpty>{w, ss, pt});
0444 if(BOOST_JSON_UNLIKELY( stop ))
0445 return w.suspend(writer::state::arr2, cur, pt);
0446 }
0447 if(BOOST_JSON_UNLIKELY( ++cur == N ))
0448 break;
0449 do_arr3:
0450 if(BOOST_JSON_LIKELY(ss))
0451 ss.append(',');
0452 else
0453 return w.suspend(writer::state::arr3, cur, pt);
0454 }
0455 do_arr4:
0456 if(BOOST_JSON_LIKELY(ss))
0457 ss.append(']');
0458 else
0459 return w.suspend(writer::state::arr4, cur, pt);
0460 return true;
0461 }
0462
0463 template< class T, bool StackEmpty >
0464 struct serialize_struct_elem_helper
0465 {
0466 writer& w;
0467 local_stream& ss;
0468 T const* pt;
0469 writer::state st;
0470
0471 template< std::size_t I >
0472 writer::state
0473 operator()( std::integral_constant<std::size_t, I> ) const
0474 {
0475 using Ds = described_members<T>;
0476 using D = mp11::mp_at_c<Ds, I>;
0477 using M = described_member_t<T, D>;
0478
0479 switch(st)
0480 {
0481 case writer::state::obj2: goto do_obj2;
0482 case writer::state::obj3: goto do_obj3;
0483 case writer::state::obj4: goto do_obj4;
0484 default: break;
0485 }
0486
0487 {
0488 string_view const sv = D::name;
0489 w.cs0_ = { sv.data(), sv.size() };
0490 }
0491 if( true )
0492 {
0493 if(BOOST_JSON_UNLIKELY( !write_string(w, ss) ))
0494 return writer::state::obj2;
0495 }
0496 else
0497 {
0498 do_obj2:
0499 if(BOOST_JSON_UNLIKELY( !resume_string(w, ss) ))
0500 return writer::state::obj2;
0501 }
0502 do_obj3:
0503 if(BOOST_JSON_LIKELY(ss))
0504 ss.append(':');
0505 else
0506 return writer::state::obj3;
0507 do_obj4:
0508 w.p_ = std::addressof( pt->* D::pointer );
0509 if(BOOST_JSON_UNLIKELY((
0510 !write_impl<M, StackEmpty>(w, ss) )))
0511 return writer::state::obj4;
0512
0513 return writer::state{};
0514 }
0515 };
0516
0517 template<class T, bool StackEmpty>
0518 BOOST_FORCEINLINE
0519 bool
0520 write_impl(described_class_conversion_tag, writer& w, stream& ss0)
0521 {
0522 using Ds = described_members<T>;
0523
0524 T const* pt;
0525 local_stream ss(ss0);
0526 std::size_t cur;
0527 constexpr std::size_t N = mp11::mp_size<Ds>::value;
0528 writer::state st;
0529 #if defined(_MSC_VER)
0530 # pragma warning( push )
0531 # pragma warning( disable : 4127 )
0532 #endif
0533 if(StackEmpty || w.st_.empty())
0534 #if defined(_MSC_VER)
0535 # pragma warning( pop )
0536 #endif
0537 {
0538 BOOST_ASSERT( w.p_ );
0539 pt = reinterpret_cast<T const*>(w.p_);
0540 cur = 0;
0541 }
0542 else
0543 {
0544 w.st_.pop(st);
0545 w.st_.pop(cur);
0546 w.st_.pop(pt);
0547 switch(st)
0548 {
0549 default:
0550 case writer::state::obj1: goto do_obj1;
0551 case writer::state::obj2:
0552 case writer::state::obj3:
0553 case writer::state::obj4: goto do_obj2;
0554 case writer::state::obj5: goto do_obj5;
0555 case writer::state::obj6: goto do_obj6;
0556 break;
0557 }
0558 }
0559 do_obj1:
0560 if(BOOST_JSON_LIKELY( ss ))
0561 ss.append('{');
0562 else
0563 return w.suspend(writer::state::obj1, cur, pt);
0564 if(BOOST_JSON_UNLIKELY( cur == N ))
0565 goto do_obj6;
0566 for(;;)
0567 {
0568 st = {};
0569 do_obj2:
0570 st = mp11::mp_with_index<N>(
0571 cur,
0572 serialize_struct_elem_helper<T, StackEmpty>{w, ss, pt, st});
0573 if(BOOST_JSON_UNLIKELY( st != writer::state{} ))
0574 return w.suspend(st, cur, pt);
0575 ++cur;
0576 if(BOOST_JSON_UNLIKELY(cur == N))
0577 break;
0578 do_obj5:
0579 if(BOOST_JSON_LIKELY(ss))
0580 ss.append(',');
0581 else
0582 return w.suspend(writer::state::obj5, cur, pt);
0583 }
0584 do_obj6:
0585 if(BOOST_JSON_LIKELY( ss ))
0586 {
0587 ss.append('}');
0588 return true;
0589 }
0590 return w.suspend(writer::state::obj6, cur, pt);
0591 }
0592
0593 template<class T, bool StackEmpty>
0594 BOOST_FORCEINLINE
0595 bool
0596 write_impl(described_enum_conversion_tag, writer& w, stream& ss)
0597 {
0598 #ifdef BOOST_DESCRIBE_CXX14
0599 using Integer = typename std::underlying_type<T>::type;
0600
0601 #if defined(_MSC_VER)
0602 # pragma warning( push )
0603 # pragma warning( disable : 4127 )
0604 #endif
0605 if(StackEmpty || w.st_.empty())
0606 #if defined(_MSC_VER)
0607 # pragma warning( pop )
0608 #endif
0609 {
0610 BOOST_ASSERT( w.p_ );
0611 T const* pt = reinterpret_cast<T const*>(w.p_);
0612 char const* const name = describe::enum_to_string(*pt, nullptr);
0613 if( name )
0614 {
0615 string_view const sv = name;
0616 w.cs0_ = { sv.data(), sv.size() };
0617 return write_string(w, ss);
0618 }
0619 else
0620 {
0621 Integer n = static_cast<Integer>(*pt);
0622 w.p_ = &n;
0623 return write_impl<Integer, true>(w, ss);
0624 }
0625 }
0626 else
0627 {
0628 writer::state st;
0629 w.st_.peek(st);
0630 if( st == writer::state::lit )
0631 return write_impl<Integer, false>(w, ss);
0632 else
0633 return resume_string(w, ss);
0634 }
0635 #else
0636 (void)w;
0637 (void)ss;
0638 static_assert(
0639 !std::is_same<T, T>::value,
0640 "described enums require C++14 support");
0641 return false;
0642 #endif
0643 }
0644
0645 template< class T, bool StackEmpty >
0646 struct serialize_variant_elem_helper
0647 {
0648 writer& w;
0649 stream& ss;
0650
0651 template<class Elem>
0652 bool
0653 operator()(Elem const& x) const
0654 {
0655 w.p_ = std::addressof(x);
0656 return write_impl<Elem, true>(w, ss);
0657 }
0658 };
0659
0660 template< class T >
0661 struct serialize_variant_elem_helper<T, false>
0662 {
0663 writer& w;
0664 stream& ss;
0665
0666 template< std::size_t I >
0667 bool
0668 operator()( std::integral_constant<std::size_t, I> ) const
0669 {
0670 using std::get;
0671 using Elem = remove_cvref<decltype(get<I>(
0672 std::declval<T const&>() ))>;
0673 return write_impl<Elem, false>(w, ss);
0674 }
0675 };
0676
0677 template<class T, bool StackEmpty>
0678 BOOST_FORCEINLINE
0679 bool
0680 write_impl(variant_conversion_tag, writer& w, stream& ss)
0681 {
0682 T const* pt;
0683
0684 using Index = remove_cvref<decltype( pt->index() )>;
0685
0686 #if defined(_MSC_VER)
0687 # pragma warning( push )
0688 # pragma warning( disable : 4127 )
0689 #endif
0690 if(StackEmpty || w.st_.empty())
0691 #if defined(_MSC_VER)
0692 # pragma warning( pop )
0693 #endif
0694 {
0695 BOOST_ASSERT( w.p_ );
0696 pt = reinterpret_cast<T const*>(w.p_);
0697 if(BOOST_JSON_LIKELY((
0698 visit(serialize_variant_elem_helper<T, true>{w, ss}, *pt))))
0699 return true;
0700
0701 Index const ix = pt->index();
0702 w.st_.push(ix);
0703 return false;
0704 }
0705 else
0706 {
0707 Index ix;
0708 w.st_.pop(ix);
0709
0710 constexpr std::size_t N = mp11::mp_size<T>::value;
0711 if(BOOST_JSON_LIKELY(( mp11::mp_with_index<N>(
0712 ix,
0713 serialize_variant_elem_helper<T, false>{w, ss}))))
0714 return true;
0715
0716 w.st_.push(ix);
0717 return false;
0718 }
0719 }
0720
0721 template<class T, bool StackEmpty>
0722 BOOST_FORCEINLINE
0723 bool
0724 write_impl(optional_conversion_tag, writer& w, stream& ss)
0725 {
0726 using Elem = value_result_type<T>;
0727
0728 bool done;
0729 bool has_value;
0730
0731 #if defined(_MSC_VER)
0732 # pragma warning( push )
0733 # pragma warning( disable : 4127 )
0734 #endif
0735 if(StackEmpty || w.st_.empty())
0736 #if defined(_MSC_VER)
0737 # pragma warning( pop )
0738 #endif
0739 {
0740 BOOST_ASSERT( w.p_ );
0741 T const* pt = reinterpret_cast<T const*>(w.p_);
0742 has_value = static_cast<bool>(*pt);
0743 if( has_value )
0744 {
0745 w.p_ = std::addressof( *(*pt) );
0746 done = write_impl<Elem, true>(w, ss);
0747 }
0748 else
0749 {
0750 w.p_ = nullptr;
0751 done = write_impl<std::nullptr_t, true>(w, ss);;
0752 }
0753 }
0754 else
0755 {
0756 w.st_.pop(has_value);
0757
0758 if( has_value )
0759 done = write_impl<Elem, false>(w, ss);
0760 else
0761 done = write_impl<std::nullptr_t, false>(w, ss);
0762 }
0763
0764 if(BOOST_JSON_UNLIKELY( !done ))
0765 w.st_.push(has_value);
0766
0767 return done;
0768 }
0769
0770 template<class T, bool StackEmpty>
0771 BOOST_FORCEINLINE
0772 bool
0773 write_impl(path_conversion_tag, writer& w, stream& ss)
0774 {
0775 #if defined(_MSC_VER)
0776 # pragma warning( push )
0777 # pragma warning( disable : 4127 )
0778 #endif
0779 if(StackEmpty || w.st_.empty())
0780 #if defined(_MSC_VER)
0781 # pragma warning( pop )
0782 #endif
0783 {
0784 BOOST_ASSERT( w.p_ );
0785 T const* pt = reinterpret_cast<T const*>(w.p_);
0786
0787 std::string const s = pt->generic_string();
0788 w.cs0_ = { s.data(), s.size() };
0789 if(BOOST_JSON_LIKELY( write_string(w, ss) ))
0790 return true;
0791
0792 std::size_t const used = w.cs0_.used( s.data() );
0793 w.st_.push( used );
0794 w.st_.push( std::move(s) );
0795 return false;
0796 }
0797 else
0798 {
0799 std::string s;
0800 std::size_t used;
0801 w.st_.pop( s );
0802 w.st_.pop( used );
0803
0804 w.cs0_ = { s.data(), s.size() };
0805 w.cs0_.skip(used);
0806
0807 if(BOOST_JSON_LIKELY( resume_string(w, ss) ))
0808 return true;
0809
0810 used = w.cs0_.used( s.data() );
0811 w.st_.push( used );
0812 w.st_.push( std::move(s) );
0813 return false;
0814 }
0815 }
0816
0817 template<class T, bool StackEmpty>
0818 bool
0819 write_impl(writer& w, stream& ss)
0820 {
0821 using cat = detail::generic_conversion_category<T>;
0822 return write_impl<T, StackEmpty>( cat(), w, ss );
0823 }
0824
0825 }
0826
0827 template<class T>
0828 void
0829 serializer::reset(T const* p) noexcept
0830 {
0831 BOOST_STATIC_ASSERT( !std::is_pointer<T>::value );
0832 BOOST_STATIC_ASSERT( std::is_object<T>::value );
0833
0834 p_ = p;
0835 fn0_ = &detail::write_impl<T, true>;
0836 fn1_ = &detail::write_impl<T, false>;
0837 st_.clear();
0838 done_ = false;
0839 }
0840
0841 }
0842 }
0843
0844 #endif