string.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,794 行 · 第 1/5 页
HPP
1,794 行
////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost// Software License, Version 1.0. (See accompanying file// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//// See http://www.boost.org/libs/interprocess for documentation.//////////////////////////////////////////////////////////////////////////////////// This file comes from SGI's string file. Modified by Ion Gaztanaga 2004-2008// Renaming, isolating and porting to generic algorithms. Pointer typedef // set to allocator::pointer to allow placing it in shared memory./////////////////////////////////////////////////////////////////////////////////// Copyright (c) 1994// Hewlett-Packard Company// // Permission to use, copy, modify, distribute and sell this software// and its documentation for any purpose is hereby granted without fee,// provided that the above copyright notice appear in all copies and// that both that copyright notice and this permission notice appear// in supporting documentation. Hewlett-Packard Company makes no// representations about the suitability of this software for any// purpose. It is provided "as is" without express or implied warranty.#ifndef BOOST_INTERPROCESS_STRING_HPP#define BOOST_INTERPROCESS_STRING_HPP#include <boost/interprocess/detail/config_begin.hpp>#include <boost/interprocess/detail/workaround.hpp>#include <boost/interprocess/detail/workaround.hpp>#include <boost/interprocess/interprocess_fwd.hpp>#include <boost/interprocess/detail/utilities.hpp>#include <boost/interprocess/detail/algorithms.hpp>#include <boost/interprocess/detail/min_max.hpp>#include <boost/interprocess/detail/iterators.hpp>#include <boost/interprocess/detail/version_type.hpp>#include <boost/interprocess/allocators/allocation_type.hpp>#include <boost/interprocess/detail/mpl.hpp>#include <boost/interprocess/detail/move.hpp>#include <boost/static_assert.hpp>#include <functional>#include <string>#include <stdexcept> #include <utility> #include <iterator>#include <memory>#include <algorithm>#include <iosfwd>#include <istream>#include <ostream>#include <ios>#include <locale>#include <cstddef>#include <climits>#include <boost/interprocess/detail/type_traits.hpp>#include <boost/detail/no_exceptions_support.hpp>#include <boost/type_traits/has_trivial_destructor.hpp>namespace boost {namespace interprocess {namespace detail {/// @cond// ------------------------------------------------------------// Class basic_string_base. // basic_string_base is a helper class that makes it it easier to write// an exception-safe version of basic_string. The constructor allocates,// but does not initialize, a block of memory. The destructor// deallocates, but does not destroy elements within, a block of// memory. The destructor assumes that the memory either is the internal buffer, // or else points to a block of memory that was allocated using _String_base's // allocator and whose size is this->m_storage.template <class A>class basic_string_base{ basic_string_base(); public: typedef A allocator_type; //! The stored allocator type typedef allocator_type stored_allocator_type; typedef typename A::pointer pointer; typedef typename A::value_type value_type; typedef typename A::size_type size_type; basic_string_base(const allocator_type& a) : members_(a) { init(); } basic_string_base(const allocator_type& a, std::size_t n) : members_(a) { this->init(); this->allocate_initial_block(n); } #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE basic_string_base(const detail::moved_object<basic_string_base<A> >& b) : members_(b.get().members_) { init(); this->swap(b.get()); } #else basic_string_base(basic_string_base<A> && b) : members_(b.members_) { init(); this->swap(b); } #endif ~basic_string_base() { this->deallocate_block(); if(!this->is_short()){ static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))->~long_t(); } } private: //This is the structure controlling a long string struct long_t { size_type is_short : 1; size_type length : (sizeof(size_type)*CHAR_BIT - 1); size_type storage; pointer start; long_t() {} long_t(const long_t &other) { this->is_short = other.is_short; length = other.length; storage = other.storage; start = other.start; } long_t &operator =(const long_t &other) { this->is_short = other.is_short; length = other.length; storage = other.storage; start = other.start; return *this; } }; //This basic type should have the same alignment as long_t//iG typedef typename type_with_alignment<detail::alignment_of<long_t>::value>::type// long_alignment_type; typedef void *long_alignment_type; BOOST_STATIC_ASSERT((detail::alignment_of<long_alignment_type>::value % detail::alignment_of<long_t>::value) == 0); //This type is the first part of the structure controlling a short string //The "data" member stores struct short_header { unsigned char is_short : 1; unsigned char length : (CHAR_BIT - 1); }; //This type has the same alignment and size as long_t but it's POD //so, unlike long_t, it can be placed in a union struct long_raw_t { long_alignment_type a; unsigned char b[sizeof(long_t) - sizeof(long_alignment_type)]; }; protected: static const size_type MinInternalBufferChars = 8; static const size_type AlignmentOfValueType = alignment_of<value_type>::value; static const size_type ShortDataOffset = detail::ct_rounded_size<sizeof(short_header), AlignmentOfValueType>::value; static const size_type ZeroCostInternalBufferChars = (sizeof(long_t) - ShortDataOffset)/sizeof(value_type); static const size_type UnalignedFinalInternalBufferChars = (ZeroCostInternalBufferChars > MinInternalBufferChars) ? ZeroCostInternalBufferChars : MinInternalBufferChars; struct short_t { short_header h; value_type data[UnalignedFinalInternalBufferChars]; }; union repr_t { long_raw_t r; short_t s; short_t &short_repr() const { return *const_cast<short_t *>(&s); } long_t &long_repr() const { return *static_cast<long_t*>(const_cast<void*>(static_cast<const void*>(&r))); } }; struct members_holder : public A { members_holder(const A &a) : A(a) {} repr_t m_repr; } members_; const A &alloc() const { return members_; } A &alloc() { return members_; } static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type); private: static const size_type MinAllocation = InternalBufferChars*2; protected: bool is_short() const { return static_cast<bool>(this->members_.m_repr.s.h.is_short != 0); } void is_short(bool yes) { if(yes && !this->is_short()){ static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))->~long_t(); } else{ new(static_cast<void*>(&this->members_.m_repr.r))long_t(); } this->members_.m_repr.s.h.is_short = yes; } private: void init() { this->members_.m_repr.s.h.is_short = 1; this->members_.m_repr.s.h.length = 0; } protected: typedef detail::integral_constant<unsigned, 1> allocator_v1; typedef detail::integral_constant<unsigned, 2> allocator_v2; typedef detail::integral_constant<unsigned, boost::interprocess::detail::version<A>::value> alloc_version; std::pair<pointer, bool> allocation_command(allocation_type command, size_type limit_size, size_type preferred_size, size_type &received_size, pointer reuse = 0) { if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){ reuse = pointer(0); command &= ~(expand_fwd | expand_bwd); } return this->allocation_command (command, limit_size, preferred_size, received_size, reuse, alloc_version()); } std::pair<pointer, bool> allocation_command(allocation_type command, size_type limit_size, size_type preferred_size, size_type &received_size, const pointer &reuse, allocator_v1) { (void)limit_size; (void)reuse; if(!(command & allocate_new)) return std::pair<pointer, bool>(pointer(0), 0); received_size = preferred_size; return std::make_pair(this->alloc().allocate(received_size), false); } std::pair<pointer, bool> allocation_command(allocation_type command, size_type limit_size, size_type preferred_size, size_type &received_size, pointer reuse, allocator_v2) { return this->alloc().allocation_command(command, limit_size, preferred_size, received_size, reuse); } size_type next_capacity(size_type additional_objects) const { return get_next_capacity(this->alloc().max_size(), this->priv_storage(), additional_objects); } void deallocate(pointer p, std::size_t n) { if (p && (n > InternalBufferChars)) this->alloc().deallocate(p, n); } void construct(pointer p, const value_type &value = value_type()) { new((void*)detail::get_pointer(p)) value_type(value); } void destroy(pointer p, size_type n) { for(; n--; ++p) detail::get_pointer(p)->~value_type(); } void destroy(pointer p) { detail::get_pointer(p)->~value_type(); } void allocate_initial_block(std::size_t n) { if (n <= this->max_size()) { if(n > InternalBufferChars){ size_type new_cap = this->next_capacity(n); pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first; this->is_short(false); this->priv_addr(p); this->priv_size(0); this->priv_storage(new_cap); } } else throw_length_error(); } void deallocate_block() { this->deallocate(this->priv_addr(), this->priv_storage()); } std::size_t max_size() const { return this->alloc().max_size() - 1; } // Helper functions for exception handling. void throw_length_error() const { throw(std::length_error("basic_string")); } void throw_out_of_range() const { throw(std::out_of_range("basic_string")); } protected: size_type priv_capacity() const { return this->priv_storage() - 1; } pointer priv_addr() const { return this->is_short() ? pointer(&this->members_.m_repr.short_repr().data[0]) : this->members_.m_repr.long_repr().start; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?