Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:59

0001 //
0002 // Copyright (c) 2023 Dmitry Arkhipov (grisumbras@yandex.ru)
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 
0011 #ifndef BOOST_JSON_DETAIL_SBO_BUFFER_HPP
0012 #define BOOST_JSON_DETAIL_SBO_BUFFER_HPP
0013 
0014 #include <boost/json/detail/config.hpp>
0015 #include <boost/json/detail/except.hpp>
0016 #include <string>
0017 #include <array>
0018 
0019 namespace boost {
0020 namespace json {
0021 namespace detail {
0022 
0023 template< std::size_t N >
0024 class sbo_buffer
0025 {
0026     struct size_ptr_pair
0027     {
0028         std::size_t size;
0029         char* ptr;
0030     };
0031     BOOST_STATIC_ASSERT( N >= sizeof(size_ptr_pair) );
0032 
0033     union {
0034         std::array<char, N> buffer_;
0035         std::size_t capacity_;
0036     };
0037     char* data_ = buffer_.data();
0038     std::size_t size_ = 0;
0039 
0040     bool
0041     is_small() const noexcept
0042     {
0043         return data_ == buffer_.data();
0044     }
0045 
0046     void
0047     dispose()
0048     {
0049         if( is_small() )
0050             return;
0051 
0052         delete[] data_;
0053 #if defined(__GNUC__)
0054 # pragma GCC diagnostic push
0055 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
0056 #endif
0057         buffer_ = {};
0058 #if defined(__GNUC__)
0059 # pragma GCC diagnostic pop
0060 #endif
0061         data_ = buffer_.data();
0062     }
0063 
0064     static constexpr
0065     std::size_t
0066     max_size() noexcept
0067     {
0068         return BOOST_JSON_MAX_STRING_SIZE;
0069     }
0070 
0071 public:
0072     sbo_buffer()
0073         : buffer_()
0074     {}
0075 
0076     sbo_buffer( sbo_buffer&& other ) noexcept
0077         : size_(other.size_)
0078     {
0079         if( other.is_small() )
0080         {
0081             buffer_ = other.buffer_;
0082             data_ = buffer_.data();
0083         }
0084         else
0085         {
0086             data_ = other.data_;
0087             other.data_ = other.buffer_.data();
0088         }
0089         BOOST_ASSERT( other.is_small() );
0090     }
0091 
0092     sbo_buffer&
0093     operator=( sbo_buffer&& other ) noexcept
0094     {
0095         if( &other == this )
0096             return this;
0097 
0098         if( other.is_small() )
0099         {
0100             buffer_ = other.buffer_;
0101             data_ = buffer_.data();
0102         }
0103         else
0104         {
0105             data_ = other.data_;
0106             other.data_ = other.buffer_.data();
0107         }
0108 
0109         size_ = other.size_;
0110         other.size_ = 0;
0111 
0112         return *this;
0113     }
0114 
0115     ~sbo_buffer()
0116     {
0117         if( !is_small() )
0118             delete[] data_;
0119     }
0120 
0121     std::size_t
0122     capacity() const noexcept
0123     {
0124         return is_small() ? buffer_.size() : capacity_;
0125     }
0126 
0127     void
0128     reset() noexcept
0129     {
0130         dispose();
0131         clear();
0132     }
0133 
0134     void
0135     clear()
0136     {
0137         size_ = 0;
0138     }
0139 
0140     void
0141     grow( std::size_t size )
0142     {
0143         if( !size )
0144             return;
0145 
0146         if( max_size() - size_ < size )
0147         {
0148             BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
0149             detail::throw_system_error( error::number_too_large, &loc );
0150         }
0151 
0152         std::size_t const old_capacity = this->capacity();
0153         std::size_t new_capacity = size_ + size;
0154 
0155         // growth factor 2
0156         if( old_capacity <= max_size() - old_capacity ) // check for overflow
0157             new_capacity = (std::max)(old_capacity * 2, new_capacity);
0158 
0159         char* new_data = new char[new_capacity];
0160         std::memcpy(new_data, data_, size_);
0161 
0162         dispose();
0163         data_ = new_data;
0164         capacity_ = new_capacity;
0165     }
0166 
0167     char*
0168     append( char const* ptr, std::size_t size )
0169     {
0170         grow(size);
0171 
0172         if(BOOST_JSON_LIKELY( size ))
0173             std::memcpy( data_ + size_, ptr, size );
0174         size_ += size;
0175         return data_;
0176     }
0177 
0178     std::size_t
0179     size() noexcept
0180     {
0181         return size_;
0182     }
0183 };
0184 
0185 } // namespace detail
0186 } // namespace json
0187 } // namespace boost
0188 
0189 #endif // BOOST_JSON_DETAIL_SBO_BUFFER_HPP