]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/container/string.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / container / string.hpp
index 8829fdaadb5d432dff798fd2a91c251767961a54..516b701aa4ed71e353c0a2867d601c5e786f924d 100644 (file)
@@ -87,9 +87,9 @@ class basic_string_base
    basic_string_base & operator=(const basic_string_base &);
    basic_string_base(const basic_string_base &);
 
-   typedef allocator_traits<Allocator> allocator_traits_type;
+   typedef Allocator allocator_type;
  public:
-   typedef Allocator                                   allocator_type;
+   typedef allocator_traits<allocator_type> allocator_traits_type;
    typedef allocator_type                              stored_allocator_type;
    typedef typename allocator_traits_type::pointer     pointer;
    typedef typename allocator_traits_type::value_type  value_type;
@@ -98,27 +98,25 @@ class basic_string_base
 
    basic_string_base()
       : members_()
-   {  init(); }
+   {}
 
    explicit basic_string_base(const allocator_type& a)
       : members_(a)
-   {  init(); }
+   {}
 
    explicit basic_string_base(BOOST_RV_REF(allocator_type) a)
       :  members_(boost::move(a))
-   {  this->init();  }
+   {}
 
    basic_string_base(const allocator_type& a, size_type n)
       : members_(a)
    {
-      this->init();
       this->allocate_initial_block(n);
    }
 
    explicit basic_string_base(size_type n)
       : members_()
    {
-      this->init();
       this->allocate_initial_block(n);
    }
 
@@ -140,6 +138,11 @@ class basic_string_base
       pointer        start;
 
       long_t()
+         : is_short(0)
+      {}
+
+      long_t(size_type len, size_type stor, pointer ptr)
+         : is_short(0), length(len), storage(stor), start(ptr)
       {}
 
       long_t(const long_t &other)
@@ -190,43 +193,57 @@ class basic_string_base
       value_type     data[UnalignedFinalInternalBufferChars];
    };
 
-   union repr_t
+   union repr_t_size_t
    {
       long_raw_t  r;
       short_t     s;
+   };
 
-      const short_t &short_repr() const
-      {  return s;  }
-
-      const long_t &long_repr() const
-      {  return *static_cast<const long_t*>(static_cast<const void*>(r.data));  }
-
-      short_t &short_repr()
-      {  return s;  }
-
-      long_t &long_repr()
-      {  return *static_cast<long_t*>(static_cast<void*>(&r));  }
+   union repr_t
+   {
+      long_raw_t  r_aligner;
+      short_t     s_aligner;
+      unsigned char data[sizeof(repr_t_size_t)];
    };
 
    struct members_holder
-      :  public Allocator
+      :  public allocator_type
    {
+      void init()
+      {
+         short_t &s = *::new(this->m_repr.data) short_t;
+         s.h.is_short = 1;
+         s.h.length = 0;
+      }
+
       members_holder()
-         : Allocator()
-      {}
+         : allocator_type()
+      { this->init(); }
 
       template<class AllocatorConvertible>
       explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
-         :  Allocator(boost::forward<AllocatorConvertible>(a))
-      {}
+         :  allocator_type(boost::forward<AllocatorConvertible>(a))
+      { this->init(); }
+
+      const short_t *pshort_repr() const
+      {  return reinterpret_cast<const short_t*>(m_repr.data);  }
+
+      const long_t *plong_repr() const
+      {  return reinterpret_cast<const long_t*>(m_repr.data);  }
+
+      short_t *pshort_repr()
+      {  return reinterpret_cast<short_t*>(m_repr.data);  }
+
+      long_t *plong_repr()
+      {  return reinterpret_cast<long_t*>(m_repr.data);  }
 
       repr_t m_repr;
    } members_;
 
-   const Allocator &alloc() const
+   const allocator_type &alloc() const
    {  return members_;  }
 
-   Allocator &alloc()
+   allocator_type &alloc()
    {  return members_;  }
 
    static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
@@ -246,36 +263,55 @@ class basic_string_base
       return hdr.is_short != 0;
    }
 
-   void is_short(bool yes)
+   short_t *construct_short()
    {
-      const bool was_short = this->is_short();
-      if(yes && !was_short){
-         allocator_traits_type::destroy
-            ( this->alloc()
-            , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
-            );
-         this->members_.m_repr.s.h.is_short = true;
-      }
-      else if(!yes && was_short){
-         allocator_traits_type::construct
-            ( this->alloc()
-            , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
-            );
-         this->members_.m_repr.s.h.is_short = false;
+      short_t *ps = ::new(this->members_.m_repr.data) short_t;
+      ps->h.is_short = 1;
+      return ps;
+   }
+
+   void destroy_short()
+   {
+      BOOST_ASSERT(this->is_short());
+      this->members_.pshort_repr()->~short_t();
+   }
+
+   short_t *assure_short()
+   {
+      if (!this->is_short()){
+         this->destroy_long();
+         return construct_short();
       }
+      return this->members_.pshort_repr();
    }
 
-   private:
-   void init()
+   long_t *construct_long()
+   {
+      long_t *pl = ::new(this->members_.m_repr.data) long_t;
+      //is_short flag is written in the constructor
+      return pl;
+   }
+
+   void destroy_long()
+   {
+      BOOST_ASSERT(!this->is_short());
+      this->members_.plong_repr()->~long_t();
+   }
+
+   long_t *assure_long()
    {
-      this->members_.m_repr.s.h.is_short = 1;
-      this->members_.m_repr.s.h.length   = 0;
+      if (this->is_short()){
+         this->destroy_short();
+         return this->construct_long();
+      }
+      return this->members_.plong_repr();
    }
 
+  
    protected:
 
    typedef dtl::integral_constant<unsigned,
-      boost::container::dtl::version<Allocator>::value> alloc_version;
+      boost::container::dtl::version<allocator_type>::value> alloc_version;
 
    pointer allocation_command(allocation_type command,
                          size_type limit_size,
@@ -286,7 +322,7 @@ class basic_string_base
          reuse = 0;
          command &= ~(expand_fwd | expand_bwd);
       }
-      return dtl::allocator_version_traits<Allocator>::allocation_command
+      return dtl::allocator_version_traits<allocator_type>::allocation_command
          (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
    }
 
@@ -334,7 +370,8 @@ class basic_string_base
             size_type new_cap = this->next_capacity(n);
             pointer reuse = 0;
             pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
-            this->is_short(false);
+            BOOST_ASSERT(this->is_short());
+            this->construct_long();
             this->priv_long_addr(p);
             this->priv_long_size(0);
             this->priv_storage(new_cap);
@@ -356,10 +393,16 @@ class basic_string_base
    { return this->priv_storage() - 1; }
 
    pointer priv_short_addr() const
-   {  return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.m_repr.short_repr().data[0]));  }
+   {  return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.pshort_repr()->data[0]));  }
+
+   //GCC seems a bit confused about uninitialized accesses
+   #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
+   #pragma GCC diagnostic push
+   #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+   #endif
 
    pointer priv_long_addr() const
-   {  return this->members_.m_repr.long_repr().start;  }
+   {  return this->members_.plong_repr()->start;  }
 
    pointer priv_addr() const
    {
@@ -378,7 +421,7 @@ class basic_string_base
    }
 
    void priv_long_addr(pointer addr)
-   {  this->members_.m_repr.long_repr().start = addr;  }
+   {  this->members_.plong_repr()->start = addr;  }
 
    size_type priv_storage() const
    {  return this->is_short() ? priv_short_storage() : priv_long_storage();  }
@@ -387,7 +430,7 @@ class basic_string_base
    {  return InternalBufferChars;  }
 
    size_type priv_long_storage() const
-   {  return this->members_.m_repr.long_repr().storage;  }
+   {  return this->members_.plong_repr()->storage;  }
 
    void priv_storage(size_type storage)
    {
@@ -397,17 +440,17 @@ class basic_string_base
 
    void priv_long_storage(size_type storage)
    {
-      this->members_.m_repr.long_repr().storage = storage;
+      this->members_.plong_repr()->storage = storage;
    }
 
    size_type priv_size() const
    {  return this->is_short() ? this->priv_short_size() : this->priv_long_size();  }
 
    size_type priv_short_size() const
-   {  return this->members_.m_repr.short_repr().h.length;  }
+   {  return this->members_.pshort_repr()->h.length;  }
 
    size_type priv_long_size() const
-   {  return this->members_.m_repr.long_repr().length;  }
+   {  return this->members_.plong_repr()->length;  }
 
    void priv_size(size_type sz)
    {
@@ -418,14 +461,14 @@ class basic_string_base
    }
 
    void priv_short_size(size_type sz)
-   {
-      this->members_.m_repr.s.h.length = (unsigned char)sz;
-   }
+   {  this->members_.pshort_repr()->h.length = (unsigned char)sz; }
 
    void priv_long_size(size_type sz)
-   {
-      this->members_.m_repr.long_repr().length = sz;
-   }
+   {  this->members_.plong_repr()->length = sz;  }
+
+   #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
+   #pragma GCC diagnostic pop
+   #endif
 
    void swap_data(basic_string_base& other)
    {
@@ -436,23 +479,23 @@ class basic_string_base
             other.members_.m_repr = tmp;
          }
          else{
-            short_t short_backup(this->members_.m_repr.short_repr());
-            this->members_.m_repr.short_repr().~short_t();
-            ::new(&this->members_.m_repr.long_repr()) long_t(other.members_.m_repr.long_repr());
-            other.members_.m_repr.long_repr().~long_t();
-            ::new(&other.members_.m_repr.short_repr()) short_t(short_backup);
+            short_t short_backup(*this->members_.pshort_repr());
+            this->members_.pshort_repr()->~short_t();
+            ::new(this->members_.plong_repr()) long_t(*other.members_.plong_repr());
+            other.members_.plong_repr()->~long_t();
+            ::new(other.members_.pshort_repr()) short_t(short_backup);
          }
       }
       else{
          if(other.is_short()){
-            short_t short_backup(other.members_.m_repr.short_repr());
-            other.members_.m_repr.short_repr().~short_t();
-            ::new(&other.members_.m_repr.long_repr()) long_t(this->members_.m_repr.long_repr());
-            this->members_.m_repr.long_repr().~long_t();
-            ::new(&this->members_.m_repr.short_repr()) short_t(short_backup);
+            short_t short_backup(*other.members_.pshort_repr());
+            other.members_.pshort_repr()->~short_t();
+            ::new(other.members_.plong_repr()) long_t(*this->members_.plong_repr());
+            this->members_.plong_repr()->~long_t();
+            ::new(this->members_.pshort_repr()) short_t(short_backup);
          }
          else{
-            boost::adl_move_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
+            boost::adl_move_swap(*this->members_.plong_repr(), *other.members_.plong_repr());
          }
       }
    }
@@ -495,18 +538,18 @@ class basic_string_base
 //! \tparam Traits The Character Traits type, which encapsulates basic character operations
 //! \tparam Allocator The allocator, used for internal memory management.
 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = new_allocator<CharT> >
+template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = void >
 #else
 template <class CharT, class Traits, class Allocator>
 #endif
 class basic_string
-   :  private dtl::basic_string_base<Allocator>
+   :  private dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type>
 {
    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
    private:
-   typedef allocator_traits<Allocator> allocator_traits_type;
    BOOST_COPYABLE_AND_MOVABLE(basic_string)
-   typedef dtl::basic_string_base<Allocator> base_t;
+   typedef dtl::basic_string_base<typename real_allocator<CharT, Allocator>::type> base_t;
+   typedef typename base_t::allocator_traits_type allocator_traits_type;
    static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
 
    protected:
@@ -553,13 +596,13 @@ class basic_string
    //////////////////////////////////////////////
    typedef Traits                                                                      traits_type;
    typedef CharT                                                                       value_type;
-   typedef typename ::boost::container::allocator_traits<Allocator>::pointer           pointer;
-   typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer     const_pointer;
-   typedef typename ::boost::container::allocator_traits<Allocator>::reference         reference;
-   typedef typename ::boost::container::allocator_traits<Allocator>::const_reference   const_reference;
-   typedef typename ::boost::container::allocator_traits<Allocator>::size_type         size_type;
-   typedef typename ::boost::container::allocator_traits<Allocator>::difference_type   difference_type;
-   typedef Allocator                                                                   allocator_type;
+   typedef typename real_allocator<CharT, Allocator>::type                             allocator_type;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::pointer           pointer;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::const_pointer     const_pointer;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::reference         reference;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::const_reference   const_reference;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::size_type         size_type;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::difference_type   difference_type;
    typedef BOOST_CONTAINER_IMPDEF(allocator_type)                                      stored_allocator_type;
    typedef BOOST_CONTAINER_IMPDEF(pointer)                                             iterator;
    typedef BOOST_CONTAINER_IMPDEF(const_pointer)                                       const_iterator;
@@ -596,7 +639,7 @@ class basic_string
    //! <b>Effects</b>: Default constructs a basic_string.
    //!
    //! <b>Throws</b>: If allocator_type's default constructor throws.
-   basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+   basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
       : base_t()
    { this->priv_terminate_string(); }
 
@@ -624,7 +667,7 @@ class basic_string
    //!
    //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
    template<template <class, class> class BasicStringView>
-   explicit basic_string(BasicStringView<CharT, Traits> sv, const Allocator& a = Allocator())
+   explicit basic_string(BasicStringView<CharT, Traits> sv, const allocator_type& a = allocator_type())
       :  base_t(allocator_traits_type::select_on_container_copy_construction(a))
    {
       this->priv_terminate_string();
@@ -669,7 +712,7 @@ class basic_string
       : base_t(a)
    {
       this->priv_terminate_string();
-      if(a == this->alloc()){
+      if(s.alloc() == this->alloc()){
          this->swap_data(s);
       }
       else{
@@ -822,7 +865,7 @@ class basic_string
    //! <b>Complexity</b>: Linear to the elements x contains.
    basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
    {
-      if (&x != this){
+      if (BOOST_LIKELY(this != &x)) {
          allocator_type &this_alloc     = this->alloc();
          const allocator_type &x_alloc  = x.alloc();
          dtl::bool_<allocator_traits_type::
@@ -830,7 +873,7 @@ class basic_string
          if(flag && this_alloc != x_alloc){
             if(!this->is_short()){
                this->deallocate_block();
-               this->is_short(true);
+               this->assure_short();
                Traits::assign(*this->priv_addr(), CharT(0));
                this->priv_short_size(0);
             }
@@ -853,27 +896,27 @@ class basic_string
       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
                                   || allocator_traits_type::is_always_equal::value)
    {
-      //for move constructor, no aliasing (&x != this) is assummed.
-      BOOST_ASSERT(this != &x);
-      allocator_type &this_alloc = this->alloc();
-      allocator_type &x_alloc    = x.alloc();
-      const bool propagate_alloc = allocator_traits_type::
-            propagate_on_container_move_assignment::value;
-      dtl::bool_<propagate_alloc> flag;
-      const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
-      //Resources can be transferred if both allocators are
-      //going to be equal after this function (either propagated or already equal)
-      if(propagate_alloc || allocators_equal){
-         //Destroy objects but retain memory in case x reuses it in the future
-         this->clear();
-         //Move allocator if needed
-         dtl::move_alloc(this_alloc, x_alloc, flag);
-         //Nothrow swap
-         this->swap_data(x);
-      }
-      //Else do a one by one move
-      else{
-         this->assign( x.begin(), x.end());
+      if (BOOST_LIKELY(this != &x)) {
+         allocator_type &this_alloc = this->alloc();
+         allocator_type &x_alloc    = x.alloc();
+         const bool propagate_alloc = allocator_traits_type::
+               propagate_on_container_move_assignment::value;
+         dtl::bool_<propagate_alloc> flag;
+         const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+         //Resources can be transferred if both allocators are
+         //going to be equal after this function (either propagated or already equal)
+         if(propagate_alloc || allocators_equal){
+            //Destroy objects but retain memory in case x reuses it in the future
+            this->clear();
+            //Move allocator if needed
+            dtl::move_alloc(this_alloc, x_alloc, flag);
+            //Nothrow swap
+            this->swap_data(x);
+         }
+         //Else do a one by one move
+         else{
+            this->assign( x.begin(), x.end());
+         }
       }
       return *this;
    }
@@ -1159,7 +1202,9 @@ class basic_string
             Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
                         , boost::movelib::to_raw_pointer(long_addr)
                         , long_size+1);
-            this->is_short(true);
+            BOOST_ASSERT(!this->is_short());
+            this->destroy_long();
+            this->construct_short();
             this->alloc().deallocate(long_addr, long_storage);
          }
          else{
@@ -1763,7 +1808,7 @@ class basic_string
                this->priv_construct_null(new_start + new_length);
 
                this->deallocate_block();
-               this->is_short(false);
+               this->assure_long();
                this->priv_long_addr(new_start);
                this->priv_long_size(new_length);
                this->priv_long_storage(new_cap);
@@ -1782,7 +1827,7 @@ class basic_string
                //Now initialize the new data
                priv_uninitialized_copy(first, last, new_start + before);
                this->priv_construct_null(new_start + (old_size + n));
-               this->is_short(false);
+               this->assure_long();
                this->priv_long_addr(new_start);
                this->priv_long_size(old_size + n);
                this->priv_long_storage(new_cap);
@@ -2261,7 +2306,7 @@ class basic_string
    //!
    //! <b>Throws</b>: Nothing
    //!
-   //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(s,n),pos).
+   //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(s,n),pos).
    size_type find(const CharT* s, size_type pos, size_type n) const
    {
       if (pos + n > this->size())
@@ -2287,7 +2332,7 @@ class basic_string
 
    //! <b>Throws</b>: Nothing
    //!
-   //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(1,c), pos).
+   //! <b>Returns</b>: find(basic_string<CharT,traits,allocator_type>(1,c), pos).
    size_type find(CharT c, size_type pos = 0) const
    {
       const size_type sz = this->size();
@@ -2359,7 +2404,7 @@ class basic_string
 
    //! <b>Throws</b>: Nothing
    //!
-   //! <b>Returns</b>: rfind(basic_string<CharT,traits,Allocator>(1,c),pos).
+   //! <b>Returns</b>: rfind(basic_string<CharT,traits,allocator_type>(1,c),pos).
    size_type rfind(CharT c, size_type pos = npos) const
    {
       const size_type len = this->size();
@@ -2427,7 +2472,7 @@ class basic_string
    //!
    //! <b>Throws</b>: Nothing
    //!
-   //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos).
+   //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,allocator_type>(1,c), pos).
    size_type find_first_of(CharT c, size_type pos = 0) const
     { return this->find(c, pos); }
 
@@ -2477,7 +2522,7 @@ class basic_string
    //!
    //! <b>Throws</b>: Nothing
    //!
-   //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,Allocator>(1,c),pos).
+   //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,allocator_type>(1,c),pos).
    size_type find_last_of(const CharT* s, size_type pos = npos) const
       { return find_last_of(s, pos, Traits::length(s)); }
 
@@ -2627,7 +2672,7 @@ class basic_string
    //!
    //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
    //!
-   //! <b>Returns</b>: basic_string<CharT,traits,Allocator>(data()+pos,rlen).
+   //! <b>Returns</b>: basic_string<CharT,traits,allocator_type>(data()+pos,rlen).
    basic_string substr(size_type pos = 0, size_type n = npos) const
    {
       if (pos > this->size())
@@ -2790,7 +2835,7 @@ class basic_string
             this->priv_construct_null(new_start + new_length);
          }
          this->deallocate_block();
-         this->is_short(false);
+         this->assure_long();
          this->priv_long_addr(new_start);
          this->priv_long_size(new_length);
          this->priv_storage(new_cap);
@@ -2933,6 +2978,18 @@ class basic_string
    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
 };
 
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+
+template <typename InputIterator>
+basic_string(InputIterator, InputIterator) ->
+   basic_string<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+basic_string(InputIterator, InputIterator, Allocator const&) ->
+   basic_string<typename iterator_traits<InputIterator>::value_type, Allocator>;
+
+#endif
+
 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
 
 //!Typedef for a basic_string of
@@ -3433,8 +3490,9 @@ namespace boost {
 template <class C, class T, class Allocator>
 struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
 {
-   typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
-   static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+   typedef typename boost::container::basic_string<C, T, Allocator>::allocator_type allocator_type;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+   static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
                              ::boost::has_trivial_destructor_after_move<pointer>::value;
 };