Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:38:55

0001 //
0002 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/json
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 // trivial
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 // non-trivial
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 // trivial
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 // non-trivial
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 } // detail
0169 } // json
0170 } // boost
0171 
0172 #endif