/src/boost/boost/json/detail/impl/stack.hpp
Line | Count | Source |
1 | | // |
2 | | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) |
3 | | // |
4 | | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
5 | | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | | // |
7 | | // Official repository: https://github.com/boostorg/json |
8 | | // |
9 | | |
10 | | #ifndef BOOST_JSON_DETAIL_IMPL_STACK_HPP |
11 | | #define BOOST_JSON_DETAIL_IMPL_STACK_HPP |
12 | | |
13 | | #include <boost/core/detail/static_assert.hpp> |
14 | | #include <memory> |
15 | | |
16 | | namespace boost { |
17 | | namespace json { |
18 | | namespace detail { |
19 | | |
20 | | template<> |
21 | | struct stack::non_trivial<void> |
22 | | { |
23 | | using relocate_t = non_trivial* (*) (non_trivial*, void*); |
24 | | |
25 | | relocate_t rel; |
26 | | non_trivial* next; |
27 | | std::size_t offset; |
28 | | |
29 | | BOOST_JSON_DECL |
30 | | non_trivial<>* |
31 | | destroy() noexcept; |
32 | | |
33 | | BOOST_JSON_DECL |
34 | | non_trivial* |
35 | | relocate(void* dst) noexcept; |
36 | | |
37 | | protected: |
38 | | ~non_trivial() = default; |
39 | | }; |
40 | | |
41 | | template< class T > |
42 | | struct stack::non_trivial |
43 | | : stack::non_trivial<void> |
44 | | { |
45 | | T obj; |
46 | | |
47 | | explicit |
48 | | non_trivial(T t, non_trivial<>* next, std::size_t offset) |
49 | | : non_trivial<void>{relocate, next, offset}, obj( std::move(t) ) |
50 | | {} |
51 | | |
52 | | static |
53 | | non_trivial<>* |
54 | | relocate(non_trivial<>* src, void* dest) noexcept |
55 | | { |
56 | | non_trivial* self = static_cast<non_trivial*>(src); |
57 | | non_trivial<>* result = nullptr; |
58 | | if( dest ) |
59 | | result = ::new(dest) non_trivial( std::move(*self) ); |
60 | | self->~non_trivial(); |
61 | | return result; |
62 | | } |
63 | | }; |
64 | | |
65 | | template<class T> |
66 | | void |
67 | | stack:: |
68 | | push_unchecked(T const& t) |
69 | 43.1k | { |
70 | 43.1k | constexpr std::size_t n = sizeof(T); |
71 | 43.1k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); |
72 | 43.1k | BOOST_ASSERT( n <= cap_ - size_ ); |
73 | 43.1k | std::memcpy( base_ + size_, &t, n ); |
74 | 43.1k | size_ += n; |
75 | 43.1k | } void boost::json::detail::stack::push_unchecked<boost::json::detail::writer::state>(boost::json::detail::writer::state const&) Line | Count | Source | 69 | 9.78k | { | 70 | 9.78k | constexpr std::size_t n = sizeof(T); | 71 | 9.78k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 9.78k | std::memcpy( base_ + size_, &t, n ); | 74 | 9.78k | size_ += n; | 75 | 9.78k | } |
void boost::json::detail::stack::push_unchecked<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state const&) Line | Count | Source | 69 | 13.6k | { | 70 | 13.6k | constexpr std::size_t n = sizeof(T); | 71 | 13.6k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 13.6k | std::memcpy( base_ + size_, &t, n ); | 74 | 13.6k | size_ += n; | 75 | 13.6k | } |
void boost::json::detail::stack::push_unchecked<unsigned long>(unsigned long const&) Line | Count | Source | 69 | 4.47k | { | 70 | 4.47k | constexpr std::size_t n = sizeof(T); | 71 | 4.47k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 4.47k | std::memcpy( base_ + size_, &t, n ); | 74 | 4.47k | size_ += n; | 75 | 4.47k | } |
void boost::json::detail::stack::push_unchecked<boost::json::array const*>(boost::json::array const* const&) Line | Count | Source | 69 | 5.76k | { | 70 | 5.76k | constexpr std::size_t n = sizeof(T); | 71 | 5.76k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 5.76k | std::memcpy( base_ + size_, &t, n ); | 74 | 5.76k | size_ += n; | 75 | 5.76k | } |
void boost::json::detail::stack::push_unchecked<boost::json::value const*>(boost::json::value const* const&) Line | Count | Source | 69 | 5.76k | { | 70 | 5.76k | constexpr std::size_t n = sizeof(T); | 71 | 5.76k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 5.76k | std::memcpy( base_ + size_, &t, n ); | 74 | 5.76k | size_ += n; | 75 | 5.76k | } |
void boost::json::detail::stack::push_unchecked<boost::json::object const*>(boost::json::object const* const&) Line | Count | Source | 69 | 1.89k | { | 70 | 1.89k | constexpr std::size_t n = sizeof(T); | 71 | 1.89k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 1.89k | std::memcpy( base_ + size_, &t, n ); | 74 | 1.89k | size_ += n; | 75 | 1.89k | } |
void boost::json::detail::stack::push_unchecked<boost::json::key_value_pair const*>(boost::json::key_value_pair const* const&) Line | Count | Source | 69 | 1.89k | { | 70 | 1.89k | constexpr std::size_t n = sizeof(T); | 71 | 1.89k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 72 | | BOOST_ASSERT( n <= cap_ - size_ ); | 73 | 1.89k | std::memcpy( base_ + size_, &t, n ); | 74 | 1.89k | size_ += n; | 75 | 1.89k | } |
|
76 | | |
77 | | template<class T> |
78 | | void |
79 | | stack:: |
80 | | peek(T& t) |
81 | 84.7k | { |
82 | 84.7k | constexpr std::size_t n = sizeof(T); |
83 | 84.7k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); |
84 | 84.7k | BOOST_ASSERT( size_ >= n ); |
85 | 84.7k | std::memcpy( &t, base_ + size_ - n, n ); |
86 | 84.7k | } void boost::json::detail::stack::peek<unsigned long>(unsigned long&) Line | Count | Source | 81 | 4.47k | { | 82 | 4.47k | constexpr std::size_t n = sizeof(T); | 83 | 4.47k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 4.47k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 4.47k | } |
void boost::json::detail::stack::peek<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state&) Line | Count | Source | 81 | 45.7k | { | 82 | 45.7k | constexpr std::size_t n = sizeof(T); | 83 | 45.7k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 45.7k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 45.7k | } |
void boost::json::detail::stack::peek<boost::json::detail::writer::state>(boost::json::detail::writer::state&) Line | Count | Source | 81 | 19.1k | { | 82 | 19.1k | constexpr std::size_t n = sizeof(T); | 83 | 19.1k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 19.1k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 19.1k | } |
void boost::json::detail::stack::peek<boost::json::value const*>(boost::json::value const*&) Line | Count | Source | 81 | 5.76k | { | 82 | 5.76k | constexpr std::size_t n = sizeof(T); | 83 | 5.76k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 5.76k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 5.76k | } |
void boost::json::detail::stack::peek<boost::json::array const*>(boost::json::array const*&) Line | Count | Source | 81 | 5.76k | { | 82 | 5.76k | constexpr std::size_t n = sizeof(T); | 83 | 5.76k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 5.76k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 5.76k | } |
void boost::json::detail::stack::peek<boost::json::key_value_pair const*>(boost::json::key_value_pair const*&) Line | Count | Source | 81 | 1.89k | { | 82 | 1.89k | constexpr std::size_t n = sizeof(T); | 83 | 1.89k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 1.89k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 1.89k | } |
void boost::json::detail::stack::peek<boost::json::object const*>(boost::json::object const*&) Line | Count | Source | 81 | 1.89k | { | 82 | 1.89k | constexpr std::size_t n = sizeof(T); | 83 | 1.89k | BOOST_CORE_STATIC_ASSERT( is_trivially_copy_assignable<T>::value ); | 84 | | BOOST_ASSERT( size_ >= n ); | 85 | 1.89k | std::memcpy( &t, base_ + size_ - n, n ); | 86 | 1.89k | } |
|
87 | | |
88 | | //-------------------------------------- |
89 | | |
90 | | // trivial |
91 | | template<class T> |
92 | | void |
93 | | stack:: |
94 | | push(T const& t, std::true_type) |
95 | 25.1k | { |
96 | 25.1k | if( sizeof(T) > cap_ - size_ ) |
97 | 1.69k | reserve_impl( sizeof(T) + size_ ); |
98 | 25.1k | push_unchecked(t); |
99 | 25.1k | } void boost::json::detail::stack::push<boost::json::detail::writer::state>(boost::json::detail::writer::state const&, std::__1::integral_constant<bool, true>) Line | Count | Source | 95 | 9.78k | { | 96 | 9.78k | if( sizeof(T) > cap_ - size_ ) | 97 | 566 | reserve_impl( sizeof(T) + size_ ); | 98 | 9.78k | push_unchecked(t); | 99 | 9.78k | } |
Unexecuted instantiation: void boost::json::detail::stack::push<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state const&, std::__1::integral_constant<bool, true>) void boost::json::detail::stack::push<boost::json::array const*>(boost::json::array const* const&, std::__1::integral_constant<bool, true>) Line | Count | Source | 95 | 5.76k | { | 96 | 5.76k | if( sizeof(T) > cap_ - size_ ) | 97 | 418 | reserve_impl( sizeof(T) + size_ ); | 98 | 5.76k | push_unchecked(t); | 99 | 5.76k | } |
void boost::json::detail::stack::push<boost::json::value const*>(boost::json::value const* const&, std::__1::integral_constant<bool, true>) Line | Count | Source | 95 | 5.76k | { | 96 | 5.76k | if( sizeof(T) > cap_ - size_ ) | 97 | 418 | reserve_impl( sizeof(T) + size_ ); | 98 | 5.76k | push_unchecked(t); | 99 | 5.76k | } |
void boost::json::detail::stack::push<boost::json::object const*>(boost::json::object const* const&, std::__1::integral_constant<bool, true>) Line | Count | Source | 95 | 1.89k | { | 96 | 1.89k | if( sizeof(T) > cap_ - size_ ) | 97 | 147 | reserve_impl( sizeof(T) + size_ ); | 98 | 1.89k | push_unchecked(t); | 99 | 1.89k | } |
void boost::json::detail::stack::push<boost::json::key_value_pair const*>(boost::json::key_value_pair const* const&, std::__1::integral_constant<bool, true>) Line | Count | Source | 95 | 1.89k | { | 96 | 1.89k | if( sizeof(T) > cap_ - size_ ) | 97 | 147 | reserve_impl( sizeof(T) + size_ ); | 98 | 1.89k | push_unchecked(t); | 99 | 1.89k | } |
|
100 | | |
101 | | // non-trivial |
102 | | template<class T> |
103 | | void |
104 | | stack:: |
105 | | push(T&& t, std::false_type) |
106 | | { |
107 | | BOOST_CORE_STATIC_ASSERT( ! is_trivially_copy_assignable<T>::value ); |
108 | | |
109 | | using Holder = non_trivial< remove_cvref<T> >; |
110 | | constexpr std::size_t size = sizeof(Holder); |
111 | | constexpr std::size_t alignment = alignof(Holder); |
112 | | |
113 | | void* ptr; |
114 | | std::size_t offset; |
115 | | do |
116 | | { |
117 | | std::size_t space = cap_ - size_; |
118 | | unsigned char* buf = base_ + size_; |
119 | | ptr = buf; |
120 | | if( std::align(alignment, size, ptr, space) ) |
121 | | { |
122 | | offset = (reinterpret_cast<unsigned char*>(ptr) - buf) + size; |
123 | | break; |
124 | | } |
125 | | |
126 | | reserve_impl(size_ + size + alignment - 1); |
127 | | } |
128 | | while(true); |
129 | | BOOST_ASSERT( |
130 | | (reinterpret_cast<unsigned char*>(ptr) + size - offset) == |
131 | | (base_ + size_) ); |
132 | | |
133 | | head_ = ::new(ptr) Holder( static_cast<T&&>(t), head_, offset ); |
134 | | size_ += offset; |
135 | | } |
136 | | |
137 | | // trivial |
138 | | template<class T> |
139 | | void |
140 | | stack:: |
141 | | pop(T& t, std::true_type) |
142 | 43.1k | { |
143 | | BOOST_ASSERT( size_ >= sizeof(T) ); |
144 | 43.1k | peek(t); |
145 | 43.1k | size_ -= sizeof(T); |
146 | 43.1k | } void boost::json::detail::stack::pop<boost::json::basic_parser<boost::json::detail::handler>::state>(boost::json::basic_parser<boost::json::detail::handler>::state&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 13.5k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 13.5k | peek(t); | 145 | 13.5k | size_ -= sizeof(T); | 146 | 13.5k | } |
void boost::json::detail::stack::pop<unsigned long>(unsigned long&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 4.47k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 4.47k | peek(t); | 145 | 4.47k | size_ -= sizeof(T); | 146 | 4.47k | } |
void boost::json::detail::stack::pop<boost::json::detail::writer::state>(boost::json::detail::writer::state&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 9.78k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 9.78k | peek(t); | 145 | 9.78k | size_ -= sizeof(T); | 146 | 9.78k | } |
void boost::json::detail::stack::pop<boost::json::value const*>(boost::json::value const*&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 5.76k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 5.76k | peek(t); | 145 | 5.76k | size_ -= sizeof(T); | 146 | 5.76k | } |
void boost::json::detail::stack::pop<boost::json::array const*>(boost::json::array const*&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 5.76k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 5.76k | peek(t); | 145 | 5.76k | size_ -= sizeof(T); | 146 | 5.76k | } |
void boost::json::detail::stack::pop<boost::json::key_value_pair const*>(boost::json::key_value_pair const*&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 1.89k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 1.89k | peek(t); | 145 | 1.89k | size_ -= sizeof(T); | 146 | 1.89k | } |
void boost::json::detail::stack::pop<boost::json::object const*>(boost::json::object const*&, std::__1::integral_constant<bool, true>) Line | Count | Source | 142 | 1.89k | { | 143 | | BOOST_ASSERT( size_ >= sizeof(T) ); | 144 | 1.89k | peek(t); | 145 | 1.89k | size_ -= sizeof(T); | 146 | 1.89k | } |
|
147 | | |
148 | | // non-trivial |
149 | | template<class T> |
150 | | void |
151 | | stack:: |
152 | | pop(T& t, std::false_type) |
153 | | { |
154 | | auto next = head_->next; |
155 | | auto offset = head_->offset; |
156 | | |
157 | | using U = remove_cvref<T>; |
158 | | using Holder = non_trivial<U>; |
159 | | auto const head = static_cast<Holder*>(head_); |
160 | | |
161 | | t = std::move( head->obj ); |
162 | | head->~Holder(); |
163 | | |
164 | | head_ = next; |
165 | | size_ -= offset; |
166 | | } |
167 | | |
168 | | } // detail |
169 | | } // json |
170 | | } // boost |
171 | | |
172 | | #endif |