📄 string
字号:
/* * Copyright (c) 1997-1999 * Silicon Graphics Computer Systems, Inc. * * 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. Silicon Graphics makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ #ifndef __SGI_STL_STRING#define __SGI_STL_STRING#include <stl_config.h>#include <stl_string_fwd.h>#include <ctype.h> #include <functional>#include <stl_ctraits_fns.h>#include <stdexcept> #include <stl_iterator_base.h>#include <memory>#include <algorithm>#ifdef __STL_USE_NEW_IOSTREAMS#include <iosfwd>#else /* __STL_USE_NEW_IOSTREAMS */#include <char_traits.h>#endif /* __STL_USE_NEW_IOSTREAMS */// Standard C++ string class. This class has performance// characteristics very much like vector<>, meaning, for example, that// it does not perform reference-count or copy-on-write, and that// concatenation of two strings is an O(N) operation. // There are three reasons why basic_string is not identical to// vector. First, basic_string always stores a null character at the// end; this makes it possible for c_str to be a fast operation.// Second, the C++ standard requires basic_string to copy elements// using char_traits<>::assign, char_traits<>::copy, and// char_traits<>::move. This means that all of vector<>'s low-level// operations must be rewritten. Third, basic_string<> has a lot of// extra functions in its interface that are convenient but, strictly// speaking, redundant.// Additionally, the C++ standard imposes a major restriction: according// to the standard, the character type _CharT must be a POD type. This// implementation weakens that restriction, and allows _CharT to be a// a user-defined non-POD type. However, _CharT must still have a// default constructor.__STL_BEGIN_NAMESPACE#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma set woff 1174#pragma set woff 1375#endif// A helper class to use a char_traits as a function object.template <class _Traits>struct _Not_within_traits : public unary_function<typename _Traits::char_type, bool>{ typedef const typename _Traits::char_type* _Pointer; const _Pointer _M_first; const _Pointer _M_last; _Not_within_traits(_Pointer __f, _Pointer __l) : _M_first(__f), _M_last(__l) {} bool operator()(const typename _Traits::char_type& __x) const { return find_if(_M_first, _M_last, bind1st(_Eq_traits<_Traits>(), __x)) == _M_last; }};// ------------------------------------------------------------// Class _String_base. // _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 _M_start either is null, or else// points to a block of memory that was allocated using _String_base's // allocator and whose size is _M_end_of_storage - _M_start.// Additionally, _String_base encapsulates the difference between// old SGI-style allocators and standard-conforming allocators.#ifdef __STL_USE_STD_ALLOCATORS// General base class.template <class _Tp, class _Alloc, bool _S_instanceless>class _String_alloc_base {public: typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; allocator_type get_allocator() const { return _M_data_allocator; } _String_alloc_base(const allocator_type& __a) : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) {}protected: _Tp* _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); } void _M_deallocate(_Tp* __p, size_t __n) { if (__p) _M_data_allocator.deallocate(__p, __n); }protected: allocator_type _M_data_allocator; _Tp* _M_start; _Tp* _M_finish; _Tp* _M_end_of_storage;};// Specialization for instanceless allocators.template <class _Tp, class _Alloc>class _String_alloc_base<_Tp,_Alloc,true> {public: typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; allocator_type get_allocator() const { return allocator_type(); } _String_alloc_base(const allocator_type&) : _M_start(0), _M_finish(0), _M_end_of_storage(0) {}protected: typedef typename _Alloc_traits<_Tp, _Alloc>::_Alloc_type _Alloc_type; _Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); } void _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n); }protected: _Tp* _M_start; _Tp* _M_finish; _Tp* _M_end_of_storage;};template <class _Tp, class _Alloc>class _String_base : public _String_alloc_base<_Tp, _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless>{protected: typedef _String_alloc_base<_Tp, _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless> _Base; typedef typename _Base::allocator_type allocator_type; void _M_allocate_block(size_t __n) { if (__n <= max_size()) { _M_start = _M_allocate(__n); _M_finish = _M_start; _M_end_of_storage = _M_start + __n; } else _M_throw_length_error(); } void _M_deallocate_block() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } size_t max_size() const { return (size_t(-1) / sizeof(_Tp)) - 1; } _String_base(const allocator_type& __a) : _Base(__a) { } _String_base(const allocator_type& __a, size_t __n) : _Base(__a) { _M_allocate_block(__n); } ~_String_base() { _M_deallocate_block(); } void _M_throw_length_error() const; void _M_throw_out_of_range() const;};#else /* __STL_USE_STD_ALLOCATORS */template <class _Tp, class _Alloc> class _String_base {public: typedef _Alloc allocator_type; allocator_type get_allocator() const { return allocator_type(); }protected: typedef simple_alloc<_Tp, _Alloc> _Alloc_type; _Tp* _M_start; _Tp* _M_finish; _Tp* _M_end_of_storage; // Precondition: 0 < __n <= max_size(). _Tp* _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); } void _M_deallocate(_Tp* __p, size_t __n) { if (__p) _Alloc_type::deallocate(__p, __n); } void _M_allocate_block(size_t __n) { if (__n <= max_size()) { _M_start = _M_allocate(__n); _M_finish = _M_start; _M_end_of_storage = _M_start + __n; } else _M_throw_length_error(); } void _M_deallocate_block() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } size_t max_size() const { return (size_t(-1) / sizeof(_Tp)) - 1; } _String_base(const allocator_type&) : _M_start(0), _M_finish(0), _M_end_of_storage(0) { } _String_base(const allocator_type&, size_t __n) : _M_start(0), _M_finish(0), _M_end_of_storage(0) { _M_allocate_block(__n); } ~_String_base() { _M_deallocate_block(); } void _M_throw_length_error() const; void _M_throw_out_of_range() const;};#endif /* __STL_USE_STD_ALLOCATORS */// Helper functions for exception handling.template <class _Tp, class _Alloc> void _String_base<_Tp,_Alloc>::_M_throw_length_error() const { __STL_THROW(length_error("basic_string"));}template <class _Tp, class _Alloc> void _String_base<_Tp, _Alloc>::_M_throw_out_of_range() const { __STL_THROW(out_of_range("basic_string"));}// ------------------------------------------------------------// Class basic_string. // Class invariants:// (1) [start, finish) is a valid range.// (2) Each iterator in [start, finish) points to a valid object// of type value_type.// (3) *finish is a valid object of type value_type; in particular,// it is value_type().// (4) [finish + 1, end_of_storage) is a valid range.// (5) Each iterator in [finish + 1, end_of_storage) points to // unininitialized memory.// Note one important consequence: a string of length n must manage// a block of memory whose size is at least n + 1. template <class _CharT, class _Traits, class _Alloc> class basic_string : private _String_base<_CharT,_Alloc> {public: typedef _CharT value_type; typedef _Traits traits_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef const value_type* const_iterator; typedef value_type* iterator;#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION typedef reverse_iterator<const_iterator> const_reverse_iterator; typedef reverse_iterator<iterator> reverse_iterator;#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */ typedef reverse_iterator<const_iterator, value_type, const_reference, difference_type> const_reverse_iterator; typedef reverse_iterator<iterator, value_type, reference, difference_type> reverse_iterator; #endif /* __STL_PARTIAL_SPECIALIZATION */ static const size_type npos; typedef _String_base<_CharT,_Alloc> _Base;public: // Constructor, destructor, assignment. typedef typename _Base::allocator_type allocator_type; allocator_type get_allocator() const { return _Base::get_allocator(); } explicit basic_string(const allocator_type& __a = allocator_type()) : _Base(__a, 8) { _M_terminate_string(); } struct _Reserve_t {}; basic_string(_Reserve_t, size_t __n, const allocator_type& __a = allocator_type()) : _Base(__a, __n + 1) { _M_terminate_string(); } basic_string(const basic_string& __s) : _Base(__s.get_allocator()) { _M_range_initialize(__s.begin(), __s.end()); } basic_string(const basic_string& __s, size_type __pos, size_type __n = npos, const allocator_type& __a = allocator_type()) : _Base(__a) { if (__pos > __s.size()) _M_throw_out_of_range(); else _M_range_initialize(__s.begin() + __pos, __s.begin() + __pos + min(__n, __s.size() - __pos)); } basic_string(const _CharT* __s, size_type __n, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_range_initialize(__s, __s + __n); } basic_string(const _CharT* __s, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_range_initialize(__s, __s + _Traits::length(__s)); } basic_string(size_type __n, _CharT __c, const allocator_type& __a = allocator_type()) : _Base(__a, __n + 1) { _M_finish = uninitialized_fill_n(_M_start, __n, __c); _M_terminate_string(); } // Check to see if _InputIterator is an integer type. If so, then // it can't be an iterator.#ifdef __STL_MEMBER_TEMPLATES template <class _InputIterator> basic_string(_InputIterator __f, _InputIterator __l, const allocator_type& __a = allocator_type()) : _Base(__a) { typedef typename _Is_integer<_InputIterator>::_Integral _Integral; _M_initialize_dispatch(__f, __l, _Integral()); }#else /* __STL_MEMBER_TEMPLATES */ basic_string(const _CharT* __f, const _CharT* __l, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_range_initialize(__f, __l); }#endif ~basic_string() { destroy(_M_start, _M_finish + 1); } basic_string& operator=(const basic_string& __s) { if (&__s != this) assign(__s.begin(), __s.end()); return *this; } basic_string& operator=(const _CharT* __s) { return assign(__s, __s + _Traits::length(__s)); } basic_string& operator=(_CharT __c) { return assign(static_cast<size_type>(1), __c); }protected: // Protected members inherited from base.#ifdef __STL_HAS_NAMESPACES using _Base::_M_allocate; using _Base::_M_deallocate; using _Base::_M_allocate_block; using _Base::_M_deallocate_block; using _Base::_M_throw_length_error; using _Base::_M_throw_out_of_range; using _Base::_M_start; using _Base::_M_finish; using _Base::_M_end_of_storage;#endif /* __STL_HAS_NAMESPACES */private: // Helper functions used by constructors // and elsewhere. void _M_construct_null(_CharT* __p) { construct(__p);# ifdef __STL_DEFAULT_CONSTRUCTOR_BUG __STL_TRY { *__p = (_CharT) 0; } __STL_UNWIND(destroy(__p));# endif } static _CharT _M_null() {# ifndef __STL_DEFAULT_CONSTRUCTOR_BUG return _CharT();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -