File indexing completed on 2025-09-15 08:38:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_JSON_DETAIL_IMPL_STACK_HPP
0011 #define BOOST_JSON_DETAIL_IMPL_STACK_HPP
0012
0013 #include <boost/align/align.hpp>
0014 #include <boost/static_assert.hpp>
0015
0016 namespace boost {
0017 namespace json {
0018 namespace detail {
0019
0020 template<>
0021 struct stack::non_trivial<void>
0022 {
0023 using relocate_t = non_trivial* (*) (non_trivial*, void*);
0024
0025 relocate_t rel;
0026 non_trivial* next;
0027 std::size_t offset;
0028
0029 BOOST_JSON_DECL
0030 non_trivial<>*
0031 destroy() noexcept;
0032
0033 BOOST_JSON_DECL
0034 non_trivial*
0035 relocate(void* dst) noexcept;
0036
0037 protected:
0038 ~non_trivial() = default;
0039 };
0040
0041 template< class T >
0042 struct stack::non_trivial
0043 : stack::non_trivial<void>
0044 {
0045 T obj;
0046
0047 explicit
0048 non_trivial(T t, non_trivial<>* next, std::size_t offset)
0049 : non_trivial<void>{relocate, next, offset}, obj( std::move(t) )
0050 {}
0051
0052 static
0053 non_trivial<>*
0054 relocate(non_trivial<>* src, void* dest) noexcept
0055 {
0056 non_trivial* self = static_cast<non_trivial*>(src);
0057 non_trivial<>* result = nullptr;
0058 if( dest )
0059 result = ::new(dest) non_trivial( std::move(*self) );
0060 self->~non_trivial();
0061 return result;
0062 }
0063 };
0064
0065 template<class T>
0066 void
0067 stack::
0068 push_unchecked(T const& t)
0069 {
0070 constexpr std::size_t n = sizeof(T);
0071 BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
0072 BOOST_ASSERT( n <= cap_ - size_ );
0073 std::memcpy( base_ + size_, &t, n );
0074 size_ += n;
0075 }
0076
0077 template<class T>
0078 void
0079 stack::
0080 peek(T& t)
0081 {
0082 constexpr std::size_t n = sizeof(T);
0083 BOOST_STATIC_ASSERT( is_trivially_copy_assignable<T>::value );
0084 BOOST_ASSERT( size_ >= n );
0085 std::memcpy( &t, base_ + size_ - n, n );
0086 }
0087
0088
0089
0090
0091 template<class T>
0092 void
0093 stack::
0094 push(T const& t, std::true_type)
0095 {
0096 if( sizeof(T) > cap_ - size_ )
0097 reserve_impl( sizeof(T) + size_ );
0098 push_unchecked(t);
0099 }
0100
0101
0102 template<class T>
0103 void
0104 stack::
0105 push(T&& t, std::false_type)
0106 {
0107 BOOST_STATIC_ASSERT( ! is_trivially_copy_assignable<T>::value );
0108
0109 using Holder = non_trivial< remove_cvref<T> >;
0110 constexpr std::size_t size = sizeof(Holder);
0111 constexpr std::size_t alignment = alignof(Holder);
0112
0113 void* ptr;
0114 std::size_t offset;
0115 do
0116 {
0117 std::size_t space = cap_ - size_;
0118 unsigned char* buf = base_ + size_;
0119 ptr = buf;
0120 if( alignment::align(alignment, size, ptr, space) )
0121 {
0122 offset = (reinterpret_cast<unsigned char*>(ptr) - buf) + size;
0123 break;
0124 }
0125
0126 reserve_impl(size_ + size + alignment - 1);
0127 }
0128 while(true);
0129 BOOST_ASSERT(
0130 (reinterpret_cast<unsigned char*>(ptr) + size - offset) ==
0131 (base_ + size_) );
0132
0133 head_ = ::new(ptr) Holder( static_cast<T&&>(t), head_, offset );
0134 size_ += offset;
0135 }
0136
0137
0138 template<class T>
0139 void
0140 stack::
0141 pop(T& t, std::true_type)
0142 {
0143 BOOST_ASSERT( size_ >= sizeof(T) );
0144 peek(t);
0145 size_ -= sizeof(T);
0146 }
0147
0148
0149 template<class T>
0150 void
0151 stack::
0152 pop(T& t, std::false_type)
0153 {
0154 auto next = head_->next;
0155 auto offset = head_->offset;
0156
0157 using U = remove_cvref<T>;
0158 using Holder = non_trivial<U>;
0159 auto const head = static_cast<Holder*>(head_);
0160
0161 t = std::move( head->obj );
0162 head->~Holder();
0163
0164 head_ = next;
0165 size_ -= offset;
0166 }
0167
0168 }
0169 }
0170 }
0171
0172 #endif