Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:16:04

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_IMPL_ARRAY_HPP
0011 #define BOOST_JSON_IMPL_ARRAY_HPP
0012 
0013 #include <boost/json/value.hpp>
0014 #include <boost/json/detail/except.hpp>
0015 #include <algorithm>
0016 #include <stdexcept>
0017 #include <type_traits>
0018 
0019 namespace boost {
0020 namespace json {
0021 
0022 //----------------------------------------------------------
0023 
0024 struct alignas(value)
0025     array::table
0026 {
0027     std::uint32_t size = 0;
0028     std::uint32_t capacity = 0;
0029 
0030     constexpr table();
0031 
0032     value&
0033     operator[](std::size_t pos) noexcept
0034     {
0035         return (reinterpret_cast<
0036             value*>(this + 1))[pos];
0037     }
0038 
0039     BOOST_JSON_DECL
0040     static
0041     table*
0042     allocate(
0043         std::size_t capacity,
0044         storage_ptr const& sp);
0045 
0046     BOOST_JSON_DECL
0047     static
0048     void
0049     deallocate(
0050         table* p,
0051         storage_ptr const& sp);
0052 };
0053 
0054 //----------------------------------------------------------
0055 
0056 class array::revert_construct
0057 {
0058     array* arr_;
0059 
0060 public:
0061     explicit
0062     revert_construct(
0063         array& arr) noexcept
0064         : arr_(&arr)
0065     {
0066     }
0067 
0068     ~revert_construct()
0069     {
0070         if(! arr_)
0071             return;
0072         arr_->destroy();
0073     }
0074 
0075     void
0076     commit() noexcept
0077     {
0078         arr_ = nullptr;
0079     }
0080 };
0081 
0082 //----------------------------------------------------------
0083 
0084 class array::revert_insert
0085 {
0086     array* arr_;
0087     std::size_t const i_;
0088     std::size_t const n_;
0089 
0090 public:
0091     value* p;
0092 
0093     BOOST_JSON_DECL
0094     revert_insert(
0095         const_iterator pos,
0096         std::size_t n,
0097         array& arr);
0098 
0099     BOOST_JSON_DECL
0100     ~revert_insert();
0101 
0102     value*
0103     commit() noexcept
0104     {
0105         auto it =
0106             arr_->data() + i_;
0107         arr_ = nullptr;
0108         return it;
0109     }
0110 };
0111 
0112 //----------------------------------------------------------
0113 
0114 void
0115 array::
0116 relocate(
0117     value* dest,
0118     value* src,
0119     std::size_t n) noexcept
0120 {
0121     if(n == 0)
0122         return;
0123     std::memmove(
0124         static_cast<void*>(dest),
0125         static_cast<void const*>(src),
0126         n * sizeof(value));
0127 }
0128 
0129 //----------------------------------------------------------
0130 //
0131 // Construction
0132 //
0133 //----------------------------------------------------------
0134 
0135 template<class InputIt, class>
0136 array::
0137 array(
0138     InputIt first, InputIt last,
0139     storage_ptr sp)
0140     : array(
0141         first, last,
0142         std::move(sp),
0143         iter_cat<InputIt>{})
0144 {
0145     BOOST_STATIC_ASSERT(
0146         std::is_constructible<value,
0147             decltype(*first)>::value);
0148 }
0149 
0150 //----------------------------------------------------------
0151 //
0152 // Modifiers
0153 //
0154 //----------------------------------------------------------
0155 
0156 template<class InputIt, class>
0157 auto
0158 array::
0159 insert(
0160     const_iterator pos,
0161     InputIt first, InputIt last) ->
0162         iterator
0163 {
0164     BOOST_STATIC_ASSERT(
0165         std::is_constructible<value,
0166             decltype(*first)>::value);
0167     return insert(pos, first, last,
0168         iter_cat<InputIt>{});
0169 }
0170 
0171 template<class Arg>
0172 auto
0173 array::
0174 emplace(
0175     const_iterator pos,
0176     Arg&& arg) ->
0177         iterator
0178 {
0179     BOOST_ASSERT(
0180         pos >= begin() &&
0181         pos <= end());
0182     value jv(
0183         std::forward<Arg>(arg),
0184         storage());
0185     return insert(pos, pilfer(jv));
0186 }
0187 
0188 template<class Arg>
0189 value&
0190 array::
0191 emplace_back(Arg&& arg)
0192 {
0193     value jv(
0194         std::forward<Arg>(arg),
0195         storage());
0196     return push_back(pilfer(jv));
0197 }
0198 
0199 //----------------------------------------------------------
0200 //
0201 // Element access
0202 //
0203 //----------------------------------------------------------
0204 
0205 value&
0206 array::
0207 at(std::size_t pos, source_location const& loc) &
0208 {
0209     auto const& self = *this;
0210     return const_cast< value& >( self.at(pos, loc) );
0211 }
0212 
0213 value&&
0214 array::
0215 at(std::size_t pos, source_location const& loc) &&
0216 {
0217     return std::move( at(pos, loc) );
0218 }
0219 
0220 value&
0221 array::
0222 operator[](std::size_t pos) & noexcept
0223 {
0224     BOOST_ASSERT(pos < t_->size);
0225     return (*t_)[pos];
0226 }
0227 
0228 value&&
0229 array::
0230 operator[](std::size_t pos) && noexcept
0231 {
0232     return std::move( (*this)[pos] );
0233 }
0234 
0235 value const&
0236 array::
0237 operator[](std::size_t pos) const& noexcept
0238 {
0239     BOOST_ASSERT(pos < t_->size);
0240     return (*t_)[pos];
0241 }
0242 
0243 value&
0244 array::
0245 front() & noexcept
0246 {
0247     BOOST_ASSERT(t_->size > 0);
0248     return (*t_)[0];
0249 }
0250 
0251 value&&
0252 array::
0253 front() && noexcept
0254 {
0255     return std::move( front() );
0256 }
0257 
0258 value const&
0259 array::
0260 front() const& noexcept
0261 {
0262     BOOST_ASSERT(t_->size > 0);
0263     return (*t_)[0];
0264 }
0265 
0266 value&
0267 array::
0268 back() & noexcept
0269 {
0270     BOOST_ASSERT(
0271         t_->size > 0);
0272     return (*t_)[t_->size - 1];
0273 }
0274 
0275 value&&
0276 array::
0277 back() && noexcept
0278 {
0279     return std::move( back() );
0280 }
0281 
0282 value const&
0283 array::
0284 back() const& noexcept
0285 {
0286     BOOST_ASSERT(
0287         t_->size > 0);
0288     return (*t_)[t_->size - 1];
0289 }
0290 
0291 value*
0292 array::
0293 data() noexcept
0294 {
0295     return &(*t_)[0];
0296 }
0297 
0298 value const*
0299 array::
0300 data() const noexcept
0301 {
0302     return &(*t_)[0];
0303 }
0304 
0305 value const*
0306 array::
0307 if_contains(
0308     std::size_t pos) const noexcept
0309 {
0310     if( pos < t_->size )
0311         return &(*t_)[pos];
0312     return nullptr;
0313 }
0314 
0315 value*
0316 array::
0317 if_contains(
0318     std::size_t pos) noexcept
0319 {
0320     if( pos < t_->size )
0321         return &(*t_)[pos];
0322     return nullptr;
0323 }
0324 
0325 //----------------------------------------------------------
0326 //
0327 // Iterators
0328 //
0329 //----------------------------------------------------------
0330 
0331 auto
0332 array::
0333 begin() noexcept ->
0334     iterator
0335 {
0336     return &(*t_)[0];
0337 }
0338 
0339 auto
0340 array::
0341 begin() const noexcept ->
0342     const_iterator
0343 {
0344     return &(*t_)[0];
0345 }
0346 
0347 auto
0348 array::
0349 cbegin() const noexcept ->
0350     const_iterator
0351 {
0352     return &(*t_)[0];
0353 }
0354 
0355 auto
0356 array::
0357 end() noexcept ->
0358     iterator
0359 {
0360     return &(*t_)[t_->size];
0361 }
0362 
0363 auto
0364 array::
0365 end() const noexcept ->
0366     const_iterator
0367 {
0368     return &(*t_)[t_->size];
0369 }
0370 
0371 auto
0372 array::
0373 cend() const noexcept ->
0374     const_iterator
0375 {
0376     return &(*t_)[t_->size];
0377 }
0378 
0379 auto
0380 array::
0381 rbegin() noexcept ->
0382     reverse_iterator
0383 {
0384     return reverse_iterator(end());
0385 }
0386 
0387 auto
0388 array::
0389 rbegin() const noexcept ->
0390     const_reverse_iterator
0391 {
0392     return const_reverse_iterator(end());
0393 }
0394 
0395 auto
0396 array::
0397 crbegin() const noexcept ->
0398     const_reverse_iterator
0399 {
0400     return const_reverse_iterator(end());
0401 }
0402 
0403 auto
0404 array::
0405 rend() noexcept ->
0406     reverse_iterator
0407 {
0408     return reverse_iterator(begin());
0409 }
0410 
0411 auto
0412 array::
0413 rend() const noexcept ->
0414     const_reverse_iterator
0415 {
0416     return const_reverse_iterator(begin());
0417 }
0418 
0419 auto
0420 array::
0421 crend() const noexcept ->
0422     const_reverse_iterator
0423 {
0424     return const_reverse_iterator(begin());
0425 }
0426 
0427 //----------------------------------------------------------
0428 //
0429 // Capacity
0430 //
0431 //----------------------------------------------------------
0432 
0433 std::size_t
0434 array::
0435 size() const noexcept
0436 {
0437     return t_->size;
0438 }
0439 
0440 constexpr
0441 std::size_t
0442 array::
0443 max_size() noexcept
0444 {
0445     // max_size depends on the address model
0446     using min = std::integral_constant<std::size_t,
0447         (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
0448     return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
0449         min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
0450 }
0451 
0452 std::size_t
0453 array::
0454 capacity() const noexcept
0455 {
0456     return t_->capacity;
0457 }
0458 
0459 bool
0460 array::
0461 empty() const noexcept
0462 {
0463     return t_->size == 0;
0464 }
0465 
0466 void
0467 array::
0468 reserve(
0469     std::size_t new_capacity)
0470 {
0471     // never shrink
0472     if(new_capacity <= t_->capacity)
0473         return;
0474     reserve_impl(new_capacity);
0475 }
0476 
0477 //----------------------------------------------------------
0478 //
0479 // private
0480 //
0481 //----------------------------------------------------------
0482 
0483 template<class InputIt>
0484 array::
0485 array(
0486     InputIt first, InputIt last,
0487     storage_ptr sp,
0488     std::input_iterator_tag)
0489     : sp_(std::move(sp))
0490     , t_(&empty_)
0491 {
0492     revert_construct r(*this);
0493     while(first != last)
0494     {
0495         reserve(size() + 1);
0496         ::new(end()) value(
0497             *first++, sp_);
0498         ++t_->size;
0499     }
0500     r.commit();
0501 }
0502 
0503 template<class InputIt>
0504 array::
0505 array(
0506     InputIt first, InputIt last,
0507     storage_ptr sp,
0508     std::forward_iterator_tag)
0509     : sp_(std::move(sp))
0510 {
0511     std::size_t n =
0512         std::distance(first, last);
0513     if( n == 0 )
0514     {
0515         t_ = &empty_;
0516         return;
0517     }
0518 
0519     t_ = table::allocate(n, sp_);
0520     t_->size = 0;
0521     revert_construct r(*this);
0522     while(n--)
0523     {
0524         ::new(end()) value(
0525             *first++, sp_);
0526         ++t_->size;
0527     }
0528     r.commit();
0529 }
0530 
0531 template<class InputIt>
0532 auto
0533 array::
0534 insert(
0535     const_iterator pos,
0536     InputIt first, InputIt last,
0537     std::input_iterator_tag) ->
0538         iterator
0539 {
0540     BOOST_ASSERT(
0541         pos >= begin() && pos <= end());
0542     if(first == last)
0543         return data() + (pos - data());
0544     array temp(first, last, sp_);
0545     revert_insert r(
0546         pos, temp.size(), *this);
0547     relocate(
0548         r.p,
0549         temp.data(),
0550         temp.size());
0551     temp.t_->size = 0;
0552     return r.commit();
0553 }
0554 
0555 template<class InputIt>
0556 auto
0557 array::
0558 insert(
0559     const_iterator pos,
0560     InputIt first, InputIt last,
0561     std::forward_iterator_tag) ->
0562         iterator
0563 {
0564     std::size_t n =
0565         std::distance(first, last);
0566     revert_insert r(pos, n, *this);
0567     while(n--)
0568     {
0569         ::new(r.p) value(*first++);
0570         ++r.p;
0571     }
0572     return r.commit();
0573 }
0574 
0575 } // namespace json
0576 } // namespace boost
0577 
0578 #endif