Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:00

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) &
0208 {
0209     auto const& self = *this;
0210     return const_cast< value& >( self.at(pos) );
0211 }
0212 
0213 value&&
0214 array::
0215 at(std::size_t pos) &&
0216 {
0217     return std::move( at(pos) );
0218 }
0219 
0220 value const&
0221 array::
0222 at(std::size_t pos) const&
0223 {
0224     if(pos >= t_->size)
0225     {
0226         BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
0227         detail::throw_system_error( error::out_of_range, &loc );
0228     }
0229     return (*t_)[pos];
0230 }
0231 
0232 value&
0233 array::
0234 operator[](std::size_t pos) & noexcept
0235 {
0236     BOOST_ASSERT(pos < t_->size);
0237     return (*t_)[pos];
0238 }
0239 
0240 value&&
0241 array::
0242 operator[](std::size_t pos) && noexcept
0243 {
0244     return std::move( (*this)[pos] );
0245 }
0246 
0247 value const&
0248 array::
0249 operator[](std::size_t pos) const& noexcept
0250 {
0251     BOOST_ASSERT(pos < t_->size);
0252     return (*t_)[pos];
0253 }
0254 
0255 value&
0256 array::
0257 front() & noexcept
0258 {
0259     BOOST_ASSERT(t_->size > 0);
0260     return (*t_)[0];
0261 }
0262 
0263 value&&
0264 array::
0265 front() && noexcept
0266 {
0267     return std::move( front() );
0268 }
0269 
0270 value const&
0271 array::
0272 front() const& noexcept
0273 {
0274     BOOST_ASSERT(t_->size > 0);
0275     return (*t_)[0];
0276 }
0277 
0278 value&
0279 array::
0280 back() & noexcept
0281 {
0282     BOOST_ASSERT(
0283         t_->size > 0);
0284     return (*t_)[t_->size - 1];
0285 }
0286 
0287 value&&
0288 array::
0289 back() && noexcept
0290 {
0291     return std::move( back() );
0292 }
0293 
0294 value const&
0295 array::
0296 back() const& noexcept
0297 {
0298     BOOST_ASSERT(
0299         t_->size > 0);
0300     return (*t_)[t_->size - 1];
0301 }
0302 
0303 value*
0304 array::
0305 data() noexcept
0306 {
0307     return &(*t_)[0];
0308 }
0309 
0310 value const*
0311 array::
0312 data() const noexcept
0313 {
0314     return &(*t_)[0];
0315 }
0316 
0317 value const*
0318 array::
0319 if_contains(
0320     std::size_t pos) const noexcept
0321 {
0322     if( pos < t_->size )
0323         return &(*t_)[pos];
0324     return nullptr;
0325 }
0326 
0327 value*
0328 array::
0329 if_contains(
0330     std::size_t pos) noexcept
0331 {
0332     if( pos < t_->size )
0333         return &(*t_)[pos];
0334     return nullptr;
0335 }
0336 
0337 //----------------------------------------------------------
0338 //
0339 // Iterators
0340 //
0341 //----------------------------------------------------------
0342 
0343 auto
0344 array::
0345 begin() noexcept ->
0346     iterator
0347 {
0348     return &(*t_)[0];
0349 }
0350 
0351 auto
0352 array::
0353 begin() const noexcept ->
0354     const_iterator
0355 {
0356     return &(*t_)[0];
0357 }
0358 
0359 auto
0360 array::
0361 cbegin() const noexcept ->
0362     const_iterator
0363 {
0364     return &(*t_)[0];
0365 }
0366 
0367 auto
0368 array::
0369 end() noexcept ->
0370     iterator
0371 {
0372     return &(*t_)[t_->size];
0373 }
0374 
0375 auto
0376 array::
0377 end() const noexcept ->
0378     const_iterator
0379 {
0380     return &(*t_)[t_->size];
0381 }
0382 
0383 auto
0384 array::
0385 cend() const noexcept ->
0386     const_iterator
0387 {
0388     return &(*t_)[t_->size];
0389 }
0390 
0391 auto
0392 array::
0393 rbegin() noexcept ->
0394     reverse_iterator
0395 {
0396     return reverse_iterator(end());
0397 }
0398 
0399 auto
0400 array::
0401 rbegin() const noexcept ->
0402     const_reverse_iterator
0403 {
0404     return const_reverse_iterator(end());
0405 }
0406 
0407 auto
0408 array::
0409 crbegin() const noexcept ->
0410     const_reverse_iterator
0411 {
0412     return const_reverse_iterator(end());
0413 }
0414 
0415 auto
0416 array::
0417 rend() noexcept ->
0418     reverse_iterator
0419 {
0420     return reverse_iterator(begin());
0421 }
0422 
0423 auto
0424 array::
0425 rend() const noexcept ->
0426     const_reverse_iterator
0427 {
0428     return const_reverse_iterator(begin());
0429 }
0430 
0431 auto
0432 array::
0433 crend() const noexcept ->
0434     const_reverse_iterator
0435 {
0436     return const_reverse_iterator(begin());
0437 }
0438 
0439 //----------------------------------------------------------
0440 //
0441 // Capacity
0442 //
0443 //----------------------------------------------------------
0444 
0445 std::size_t
0446 array::
0447 size() const noexcept
0448 {
0449     return t_->size;
0450 }
0451 
0452 constexpr
0453 std::size_t
0454 array::
0455 max_size() noexcept
0456 {
0457     // max_size depends on the address model
0458     using min = std::integral_constant<std::size_t,
0459         (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
0460     return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
0461         min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
0462 }
0463 
0464 std::size_t
0465 array::
0466 capacity() const noexcept
0467 {
0468     return t_->capacity;
0469 }
0470 
0471 bool
0472 array::
0473 empty() const noexcept
0474 {
0475     return t_->size == 0;
0476 }
0477 
0478 void
0479 array::
0480 reserve(
0481     std::size_t new_capacity)
0482 {
0483     // never shrink
0484     if(new_capacity <= t_->capacity)
0485         return;
0486     reserve_impl(new_capacity);
0487 }
0488 
0489 //----------------------------------------------------------
0490 //
0491 // private
0492 //
0493 //----------------------------------------------------------
0494 
0495 template<class InputIt>
0496 array::
0497 array(
0498     InputIt first, InputIt last,
0499     storage_ptr sp,
0500     std::input_iterator_tag)
0501     : sp_(std::move(sp))
0502     , t_(&empty_)
0503 {
0504     revert_construct r(*this);
0505     while(first != last)
0506     {
0507         reserve(size() + 1);
0508         ::new(end()) value(
0509             *first++, sp_);
0510         ++t_->size;
0511     }
0512     r.commit();
0513 }
0514 
0515 template<class InputIt>
0516 array::
0517 array(
0518     InputIt first, InputIt last,
0519     storage_ptr sp,
0520     std::forward_iterator_tag)
0521     : sp_(std::move(sp))
0522 {
0523     std::size_t n =
0524         std::distance(first, last);
0525     if( n == 0 )
0526     {
0527         t_ = &empty_;
0528         return;
0529     }
0530 
0531     t_ = table::allocate(n, sp_);
0532     t_->size = 0;
0533     revert_construct r(*this);
0534     while(n--)
0535     {
0536         ::new(end()) value(
0537             *first++, sp_);
0538         ++t_->size;
0539     }
0540     r.commit();
0541 }
0542 
0543 template<class InputIt>
0544 auto
0545 array::
0546 insert(
0547     const_iterator pos,
0548     InputIt first, InputIt last,
0549     std::input_iterator_tag) ->
0550         iterator
0551 {
0552     BOOST_ASSERT(
0553         pos >= begin() && pos <= end());
0554     if(first == last)
0555         return data() + (pos - data());
0556     array temp(first, last, sp_);
0557     revert_insert r(
0558         pos, temp.size(), *this);
0559     relocate(
0560         r.p,
0561         temp.data(),
0562         temp.size());
0563     temp.t_->size = 0;
0564     return r.commit();
0565 }
0566 
0567 template<class InputIt>
0568 auto
0569 array::
0570 insert(
0571     const_iterator pos,
0572     InputIt first, InputIt last,
0573     std::forward_iterator_tag) ->
0574         iterator
0575 {
0576     std::size_t n =
0577         std::distance(first, last);
0578     revert_insert r(pos, n, *this);
0579     while(n--)
0580     {
0581         ::new(r.p) value(*first++);
0582         ++r.p;
0583     }
0584     return r.commit();
0585 }
0586 
0587 } // namespace json
0588 } // namespace boost
0589 
0590 #endif