impl/serializer.hpp

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