| // Components for manipulating sequences of characters -*- C++ -*- | |
| // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. | |
| // | |
| // This file is part of the GNU ISO C++ Library. This library is free | |
| // software; you can redistribute it and/or modify it under the | |
| // terms of the GNU General Public License as published by the | |
| // Free Software Foundation; either version 2, or (at your option) | |
| // any later version. | |
| // This library is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // You should have received a copy of the GNU General Public License along | |
| // with this library; see the file COPYING. If not, write to the Free | |
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
| // USA. | |
| // As a special exception, you may use this file as part of a free software | |
| // library without restriction. Specifically, if other files instantiate | |
| // templates or use macros or inline functions from this file, or you compile | |
| // this file and link it with other files to produce an executable, this | |
| // file does not by itself cause the resulting executable to be covered by | |
| // the GNU General Public License. This exception does not however | |
| // invalidate any other reasons why the executable file might be covered by | |
| // the GNU General Public License. | |
| // | |
| // ISO C++ 14882: 21 Strings library | |
| // | |
| /** @file basic_string.h | |
| * This is an internal header file, included by other library headers. | |
| * You should not attempt to use it directly. | |
| */ | |
| #ifndef _CPP_BITS_STRING_H | |
| #define _CPP_BITS_STRING_H 1 | |
| #pragma GCC system_header | |
| #include <bits/atomicity.h> | |
| namespace std | |
| { | |
| // Documentation? What's that? | |
| // Nathan Myers <ncm@cantrip.org>. | |
| // | |
| // A string looks like this: | |
| // | |
| // [_Rep] | |
| // _M_length | |
| // [basic_string<char_type>] _M_capacity | |
| // _M_dataplus _M_state | |
| // _M_p ----------------> unnamed array of char_type | |
| // Where the _M_p points to the first character in the string, and | |
| // you cast it to a pointer-to-_Rep and subtract 1 to get a | |
| // pointer to the header. | |
| // This approach has the enormous advantage that a string object | |
| // requires only one allocation. All the ugliness is confined | |
| // within a single pair of inline functions, which each compile to | |
| // a single "add" instruction: _Rep::_M_data(), and | |
| // string::_M_rep(); and the allocation function which gets a | |
| // block of raw bytes and with room enough and constructs a _Rep | |
| // object at the front. | |
| // The reason you want _M_data pointing to the character array and | |
| // not the _Rep is so that the debugger can see the string | |
| // contents. (Probably we should add a non-inline member to get | |
| // the _Rep for the debugger to use, so users can check the actual | |
| // string length.) | |
| // Note that the _Rep object is a POD so that you can have a | |
| // static "empty string" _Rep object already "constructed" before | |
| // static constructors have run. The reference-count encoding is | |
| // chosen so that a 0 indicates one reference, so you never try to | |
| // destroy the empty-string _Rep object. | |
| // All but the last paragraph is considered pretty conventional | |
| // for a C++ string implementation. | |
| // 21.3 Template class basic_string | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| class basic_string | |
| { | |
| // Types: | |
| public: | |
| typedef _Traits traits_type; | |
| typedef typename _Traits::char_type value_type; | |
| typedef _Alloc allocator_type; | |
| typedef typename _Alloc::size_type size_type; | |
| typedef typename _Alloc::difference_type difference_type; | |
| typedef typename _Alloc::reference reference; | |
| typedef typename _Alloc::const_reference const_reference; | |
| typedef typename _Alloc::pointer pointer; | |
| typedef typename _Alloc::const_pointer const_pointer; | |
| typedef __normal_iterator<pointer, basic_string> iterator; | |
| typedef __normal_iterator<const_pointer, basic_string> const_iterator; | |
| typedef reverse_iterator<const_iterator> const_reverse_iterator; | |
| typedef reverse_iterator<iterator> reverse_iterator; | |
| private: | |
| // _Rep: string representation | |
| // Invariants: | |
| // 1. String really contains _M_length + 1 characters; last is set | |
| // to 0 only on call to c_str(). We avoid instantiating | |
| // _CharT() where the interface does not require it. | |
| // 2. _M_capacity >= _M_length | |
| // Allocated memory is always _M_capacity + (1 * sizeof(_CharT)). | |
| // 3. _M_references has three states: | |
| // -1: leaked, one reference, no ref-copies allowed, non-const. | |
| // 0: one reference, non-const. | |
| // n>0: n + 1 references, operations require a lock, const. | |
| // 4. All fields==0 is an empty string, given the extra storage | |
| // beyond-the-end for a null terminator; thus, the shared | |
| // empty string representation needs no constructor. | |
| struct _Rep | |
| { | |
| // Types: | |
| typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc; | |
| // (Public) Data members: | |
| // The maximum number of individual char_type elements of an | |
| // individual string is determined by _S_max_size. This is the | |
| // value that will be returned by max_size(). (Whereas npos | |
| // is the maximum number of bytes the allocator can allocate.) | |
| // If one was to divvy up the theoretical largest size string, | |
| // with a terminating character and m _CharT elements, it'd | |
| // look like this: | |
| // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT) | |
| // Solving for m: | |
| // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1 | |
| // In addition, this implementation quarters this ammount. | |
| static const size_type _S_max_size; | |
| static const _CharT _S_terminal; | |
| size_type _M_length; | |
| size_type _M_capacity; | |
| _Atomic_word _M_references; | |
| bool | |
| _M_is_leaked() const | |
| { return _M_references < 0; } | |
| bool | |
| _M_is_shared() const | |
| { return _M_references > 0; } | |
| void | |
| _M_set_leaked() | |
| { _M_references = -1; } | |
| void | |
| _M_set_sharable() | |
| { _M_references = 0; } | |
| _CharT* | |
| _M_refdata() throw() | |
| { return reinterpret_cast<_CharT*> (this + 1); } | |
| _CharT& | |
| operator[](size_t __s) throw() | |
| { return _M_refdata() [__s]; } | |
| _CharT* | |
| _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2) | |
| { return (!_M_is_leaked() && __alloc1 == __alloc2) ? | |
| _M_refcopy() : _M_clone(__alloc1); } | |
| // Create & Destroy | |
| static _Rep* | |
| _S_create(size_t, const _Alloc&); | |
| void | |
| _M_dispose(const _Alloc& __a) | |
| { | |
| if (__exchange_and_add(&_M_references, -1) <= 0) | |
| _M_destroy(__a); | |
| } // XXX MT | |
| void | |
| _M_destroy(const _Alloc&) throw(); | |
| _CharT* | |
| _M_refcopy() throw() | |
| { | |
| __atomic_add(&_M_references, 1); | |
| return _M_refdata(); | |
| } // XXX MT | |
| _CharT* | |
| _M_clone(const _Alloc&, size_type __res = 0); | |
| }; | |
| // Use empty-base optimization: http://www.cantrip.org/emptyopt.html | |
| struct _Alloc_hider : _Alloc | |
| { | |
| _Alloc_hider(_CharT* __dat, const _Alloc& __a) | |
| : _Alloc(__a), _M_p(__dat) { } | |
| _CharT* _M_p; // The actual data. | |
| }; | |
| public: | |
| // Data Members (public): | |
| // NB: This is an unsigned type, and thus represents the maximum | |
| // size that the allocator can hold. | |
| static const size_type npos = static_cast<size_type>(-1); | |
| private: | |
| // Data Members (private): | |
| mutable _Alloc_hider _M_dataplus; | |
| // The following storage is init'd to 0 by the linker, resulting | |
| // (carefully) in an empty string with one reference. | |
| static size_type _S_empty_rep_storage[(sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)]; | |
| _CharT* | |
| _M_data() const | |
| { return _M_dataplus._M_p; } | |
| _CharT* | |
| _M_data(_CharT* __p) | |
| { return (_M_dataplus._M_p = __p); } | |
| _Rep* | |
| _M_rep() const | |
| { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); } | |
| // For the internal use we have functions similar to `begin'/`end' | |
| // but they do not call _M_leak. | |
| iterator | |
| _M_ibegin() const { return iterator(_M_data()); } | |
| iterator | |
| _M_iend() const { return iterator(_M_data() + this->size()); } | |
| void | |
| _M_leak() // for use in begin() & non-const op[] | |
| { | |
| if (!_M_rep()->_M_is_leaked()) | |
| _M_leak_hard(); | |
| } | |
| iterator | |
| _M_check(size_type __pos) const | |
| { | |
| if (__pos > this->size()) | |
| __throw_out_of_range("basic_string::_M_check"); | |
| return _M_ibegin() + __pos; | |
| } | |
| // NB: _M_fold doesn't check for a bad __pos1 value. | |
| iterator | |
| _M_fold(size_type __pos, size_type __off) const | |
| { | |
| bool __testoff = __off < this->size() - __pos; | |
| size_type __newoff = __testoff ? __off : this->size() - __pos; | |
| return (_M_ibegin() + __pos + __newoff); | |
| } | |
| // _S_copy_chars is a separate template to permit specialization | |
| // to optimize for the common case of pointers as iterators. | |
| template<class _Iterator> | |
| static void | |
| _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) | |
| { | |
| for (; __k1 != __k2; ++__k1, ++__p) | |
| traits_type::assign(*__p, *__k1); // These types are off. | |
| } | |
| static void | |
| _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) | |
| { _S_copy_chars(__p, __k1.base(), __k2.base()); } | |
| static void | |
| _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2) | |
| { _S_copy_chars(__p, __k1.base(), __k2.base()); } | |
| static void | |
| _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) | |
| { traits_type::copy(__p, __k1, __k2 - __k1); } | |
| static void | |
| _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2) | |
| { traits_type::copy(__p, __k1, __k2 - __k1); } | |
| void | |
| _M_mutate(size_type __pos, size_type __len1, size_type __len2); | |
| void | |
| _M_leak_hard(); | |
| static _Rep& | |
| _S_empty_rep() | |
| { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); } | |
| public: | |
| // Construct/copy/destroy: | |
| // NB: We overload ctors in some cases instead of using default | |
| // arguments, per 17.4.4.4 para. 2 item 2. | |
| inline | |
| basic_string(); | |
| explicit | |
| basic_string(const _Alloc& __a); | |
| // NB: per LWG issue 42, semantics different from IS: | |
| basic_string(const basic_string& __str); | |
| basic_string(const basic_string& __str, size_type __pos, | |
| size_type __n = npos); | |
| basic_string(const basic_string& __str, size_type __pos, | |
| size_type __n, const _Alloc& __a); | |
| basic_string(const _CharT* __s, size_type __n, | |
| const _Alloc& __a = _Alloc()); | |
| basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()); | |
| basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()); | |
| template<class _InputIterator> | |
| basic_string(_InputIterator __beg, _InputIterator __end, | |
| const _Alloc& __a = _Alloc()); | |
| ~basic_string() | |
| { _M_rep()->_M_dispose(this->get_allocator()); } | |
| basic_string& | |
| operator=(const basic_string& __str) { return this->assign(__str); } | |
| basic_string& | |
| operator=(const _CharT* __s) { return this->assign(__s); } | |
| basic_string& | |
| operator=(_CharT __c) { return this->assign(1, __c); } | |
| // Iterators: | |
| iterator | |
| begin() | |
| { | |
| _M_leak(); | |
| return iterator(_M_data()); | |
| } | |
| const_iterator | |
| begin() const | |
| { return const_iterator(_M_data()); } | |
| iterator | |
| end() | |
| { | |
| _M_leak(); | |
| return iterator(_M_data() + this->size()); | |
| } | |
| const_iterator | |
| end() const | |
| { return const_iterator(_M_data() + this->size()); } | |
| reverse_iterator | |
| rbegin() | |
| { return reverse_iterator(this->end()); } | |
| const_reverse_iterator | |
| rbegin() const | |
| { return const_reverse_iterator(this->end()); } | |
| reverse_iterator | |
| rend() | |
| { return reverse_iterator(this->begin()); } | |
| const_reverse_iterator | |
| rend() const | |
| { return const_reverse_iterator(this->begin()); } | |
| public: | |
| // Capacity: | |
| size_type | |
| size() const { return _M_rep()->_M_length; } | |
| size_type | |
| length() const { return _M_rep()->_M_length; } | |
| size_type | |
| max_size() const { return _Rep::_S_max_size; } | |
| void | |
| resize(size_type __n, _CharT __c); | |
| void | |
| resize(size_type __n) { this->resize(__n, _CharT()); } | |
| size_type | |
| capacity() const { return _M_rep()->_M_capacity; } | |
| void | |
| reserve(size_type __res_arg = 0); | |
| void | |
| clear() { _M_mutate(0, this->size(), 0); } | |
| bool | |
| empty() const { return this->size() == 0; } | |
| // Element access: | |
| const_reference | |
| operator[] (size_type __pos) const | |
| { return _M_data()[__pos]; } | |
| reference | |
| operator[](size_type __pos) | |
| { | |
| _M_leak(); | |
| return _M_data()[__pos]; | |
| } | |
| const_reference | |
| at(size_type __n) const | |
| { | |
| if (__n >= this->size()) | |
| __throw_out_of_range("basic_string::at"); | |
| return _M_data()[__n]; | |
| } | |
| reference | |
| at(size_type __n) | |
| { | |
| if (__n >= size()) | |
| __throw_out_of_range("basic_string::at"); | |
| _M_leak(); | |
| return _M_data()[__n]; | |
| } | |
| // Modifiers: | |
| basic_string& | |
| operator+=(const basic_string& __str) { return this->append(__str); } | |
| basic_string& | |
| operator+=(const _CharT* __s) { return this->append(__s); } | |
| basic_string& | |
| operator+=(_CharT __c) { return this->append(size_type(1), __c); } | |
| basic_string& | |
| append(const basic_string& __str); | |
| basic_string& | |
| append(const basic_string& __str, size_type __pos, size_type __n); | |
| basic_string& | |
| append(const _CharT* __s, size_type __n); | |
| basic_string& | |
| append(const _CharT* __s) | |
| { return this->append(__s, traits_type::length(__s)); } | |
| basic_string& | |
| append(size_type __n, _CharT __c); | |
| template<class _InputIterator> | |
| basic_string& | |
| append(_InputIterator __first, _InputIterator __last) | |
| { return this->replace(_M_iend(), _M_iend(), __first, __last); } | |
| void | |
| push_back(_CharT __c) | |
| { this->replace(_M_iend(), _M_iend(), 1, __c); } | |
| basic_string& | |
| assign(const basic_string& __str); | |
| basic_string& | |
| assign(const basic_string& __str, size_type __pos, size_type __n) | |
| { | |
| const size_type __strsize = __str.size(); | |
| if (__pos > __strsize) | |
| __throw_out_of_range("basic_string::assign"); | |
| const bool __testn = __n < __strsize - __pos; | |
| const size_type __newsize = __testn ? __n : __strsize - __pos; | |
| return this->assign(__str._M_data() + __pos, __newsize); | |
| } | |
| basic_string& | |
| assign(const _CharT* __s, size_type __n) | |
| { | |
| if (__n > this->max_size()) | |
| __throw_length_error("basic_string::assign"); | |
| if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) | |
| || less<const _CharT*>()(_M_data() + this->size(), __s)) | |
| return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n); | |
| else | |
| { | |
| // Work in-place | |
| const size_type __pos = __s - _M_data(); | |
| if (__pos >= __n) | |
| traits_type::copy(_M_data(), __s, __n); | |
| else if (__pos) | |
| traits_type::move(_M_data(), __s, __n); | |
| _M_rep()->_M_length = __n; | |
| _M_data()[__n] = _Rep::_S_terminal; | |
| return *this; | |
| } | |
| } | |
| basic_string& | |
| assign(const _CharT* __s) | |
| { return this->assign(__s, traits_type::length(__s)); } | |
| basic_string& | |
| assign(size_type __n, _CharT __c) | |
| { return this->replace(_M_ibegin(), _M_iend(), __n, __c); } | |
| template<class _InputIterator> | |
| basic_string& | |
| assign(_InputIterator __first, _InputIterator __last) | |
| { return this->replace(_M_ibegin(), _M_iend(), __first, __last); } | |
| void | |
| insert(iterator __p, size_type __n, _CharT __c) | |
| { this->replace(__p, __p, __n, __c); } | |
| template<class _InputIterator> | |
| void insert(iterator __p, _InputIterator __beg, _InputIterator __end) | |
| { this->replace(__p, __p, __beg, __end); } | |
| basic_string& | |
| insert(size_type __pos1, const basic_string& __str) | |
| { | |
| iterator __p = _M_check(__pos1); | |
| this->replace(__p, __p, __str._M_ibegin(), __str._M_iend()); | |
| return *this; | |
| } | |
| basic_string& | |
| insert(size_type __pos1, const basic_string& __str, | |
| size_type __pos2, size_type __n) | |
| { | |
| iterator __p = _M_check(__pos1); | |
| this->replace(__p, __p, __str._M_check(__pos2), | |
| __str._M_fold(__pos2, __n)); | |
| return *this; | |
| } | |
| basic_string& | |
| insert(size_type __pos, const _CharT* __s, size_type __n) | |
| { | |
| iterator __p = _M_check(__pos); | |
| this->replace(__p, __p, __s, __s + __n); | |
| return *this; | |
| } | |
| basic_string& | |
| insert(size_type __pos, const _CharT* __s) | |
| { return this->insert(__pos, __s, traits_type::length(__s)); } | |
| basic_string& | |
| insert(size_type __pos, size_type __n, _CharT __c) | |
| { | |
| this->insert(_M_check(__pos), __n, __c); | |
| return *this; | |
| } | |
| iterator | |
| insert(iterator __p, _CharT __c = _CharT()) | |
| { | |
| size_type __pos = __p - _M_ibegin(); | |
| this->insert(_M_check(__pos), size_type(1), __c); | |
| _M_rep()->_M_set_leaked(); | |
| return this->_M_ibegin() + __pos; | |
| } | |
| basic_string& | |
| erase(size_type __pos = 0, size_type __n = npos) | |
| { | |
| return this->replace(_M_check(__pos), _M_fold(__pos, __n), | |
| _M_data(), _M_data()); | |
| } | |
| iterator | |
| erase(iterator __position) | |
| { | |
| size_type __i = __position - _M_ibegin(); | |
| this->replace(__position, __position + 1, _M_data(), _M_data()); | |
| _M_rep()->_M_set_leaked(); | |
| return _M_ibegin() + __i; | |
| } | |
| iterator | |
| erase(iterator __first, iterator __last) | |
| { | |
| size_type __i = __first - _M_ibegin(); | |
| this->replace(__first, __last, _M_data(), _M_data()); | |
| _M_rep()->_M_set_leaked(); | |
| return _M_ibegin() + __i; | |
| } | |
| basic_string& | |
| replace(size_type __pos, size_type __n, const basic_string& __str) | |
| { | |
| return this->replace(_M_check(__pos), _M_fold(__pos, __n), | |
| __str.begin(), __str.end()); | |
| } | |
| basic_string& | |
| replace(size_type __pos1, size_type __n1, const basic_string& __str, | |
| size_type __pos2, size_type __n2); | |
| basic_string& | |
| replace(size_type __pos, size_type __n1, const _CharT* __s, | |
| size_type __n2) | |
| { | |
| return this->replace(_M_check(__pos), _M_fold(__pos, __n1), | |
| __s, __s + __n2); | |
| } | |
| basic_string& | |
| replace(size_type __pos, size_type __n1, const _CharT* __s) | |
| { | |
| return this->replace(_M_check(__pos), _M_fold(__pos, __n1), | |
| __s, __s + traits_type::length(__s)); | |
| } | |
| basic_string& | |
| replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) | |
| { | |
| return this->replace(_M_check(__pos), _M_fold(__pos, __n1), __n2, __c); | |
| } | |
| basic_string& | |
| replace(iterator __i1, iterator __i2, const basic_string& __str) | |
| { return this->replace(__i1, __i2, __str.begin(), __str.end()); } | |
| basic_string& | |
| replace(iterator __i1, iterator __i2, | |
| const _CharT* __s, size_type __n) | |
| { return this->replace(__i1, __i2, __s, __s + __n); } | |
| basic_string& | |
| replace(iterator __i1, iterator __i2, const _CharT* __s) | |
| { return this->replace(__i1, __i2, __s, | |
| __s + traits_type::length(__s)); } | |
| basic_string& | |
| replace(iterator __i1, iterator __i2, size_type __n, _CharT __c); | |
| template<class _InputIterator> | |
| basic_string& | |
| replace(iterator __i1, iterator __i2, | |
| _InputIterator __k1, _InputIterator __k2) | |
| { return _M_replace(__i1, __i2, __k1, __k2, | |
| typename iterator_traits<_InputIterator>::iterator_category()); } | |
| private: | |
| template<class _InputIterator> | |
| basic_string& | |
| _M_replace(iterator __i1, iterator __i2, _InputIterator __k1, | |
| _InputIterator __k2, input_iterator_tag); | |
| template<class _ForwardIterator> | |
| basic_string& | |
| _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1, | |
| _ForwardIterator __k2); | |
| // _S_construct_aux is used to implement the 21.3.1 para 15 which | |
| // requires special behaviour if _InIter is an integral type | |
| template<class _InIter> | |
| static _CharT* | |
| _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a, | |
| __false_type) | |
| { | |
| typedef typename iterator_traits<_InIter>::iterator_category _Tag; | |
| return _S_construct(__beg, __end, __a, _Tag()); | |
| } | |
| template<class _InIter> | |
| static _CharT* | |
| _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a, | |
| __true_type) | |
| { | |
| return _S_construct(static_cast<size_type>(__beg), | |
| static_cast<value_type>(__end), __a); | |
| } | |
| template<class _InIter> | |
| static _CharT* | |
| _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a) | |
| { | |
| typedef typename _Is_integer<_InIter>::_Integral _Integral; | |
| return _S_construct_aux(__beg, __end, __a, _Integral()); | |
| } | |
| // For Input Iterators, used in istreambuf_iterators, etc. | |
| template<class _InIter> | |
| static _CharT* | |
| _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, | |
| input_iterator_tag); | |
| // For forward_iterators up to random_access_iterators, used for | |
| // string::iterator, _CharT*, etc. | |
| template<class _FwdIter> | |
| static _CharT* | |
| _S_construct(_FwdIter __end, _FwdIter __beg, const _Alloc& __a, | |
| forward_iterator_tag); | |
| static _CharT* | |
| _S_construct(size_type __req, _CharT __c, const _Alloc& __a); | |
| public: | |
| size_type | |
| copy(_CharT* __s, size_type __n, size_type __pos = 0) const; | |
| void | |
| swap(basic_string<_CharT, _Traits, _Alloc>& __s); | |
| // String operations: | |
| const _CharT* | |
| c_str() const | |
| { | |
| // MT: This assumes concurrent writes are OK. | |
| size_type __n = this->size(); | |
| traits_type::assign(_M_data()[__n], _Rep::_S_terminal); | |
| return _M_data(); | |
| } | |
| const _CharT* | |
| data() const { return _M_data(); } | |
| allocator_type | |
| get_allocator() const { return _M_dataplus; } | |
| size_type | |
| find(const _CharT* __s, size_type __pos, size_type __n) const; | |
| size_type | |
| find(const basic_string& __str, size_type __pos = 0) const | |
| { return this->find(__str.data(), __pos, __str.size()); } | |
| size_type | |
| find(const _CharT* __s, size_type __pos = 0) const | |
| { return this->find(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| find(_CharT __c, size_type __pos = 0) const; | |
| size_type | |
| rfind(const basic_string& __str, size_type __pos = npos) const | |
| { return this->rfind(__str.data(), __pos, __str.size()); } | |
| size_type | |
| rfind(const _CharT* __s, size_type __pos, size_type __n) const; | |
| size_type | |
| rfind(const _CharT* __s, size_type __pos = npos) const | |
| { return this->rfind(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| rfind(_CharT __c, size_type __pos = npos) const; | |
| size_type | |
| find_first_of(const basic_string& __str, size_type __pos = 0) const | |
| { return this->find_first_of(__str.data(), __pos, __str.size()); } | |
| size_type | |
| find_first_of(const _CharT* __s, size_type __pos, size_type __n) const; | |
| size_type | |
| find_first_of(const _CharT* __s, size_type __pos = 0) const | |
| { return this->find_first_of(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| find_first_of(_CharT __c, size_type __pos = 0) const | |
| { return this->find(__c, __pos); } | |
| size_type | |
| find_last_of(const basic_string& __str, size_type __pos = npos) const | |
| { return this->find_last_of(__str.data(), __pos, __str.size()); } | |
| size_type | |
| find_last_of(const _CharT* __s, size_type __pos, size_type __n) const; | |
| size_type | |
| find_last_of(const _CharT* __s, size_type __pos = npos) const | |
| { return this->find_last_of(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| find_last_of(_CharT __c, size_type __pos = npos) const | |
| { return this->rfind(__c, __pos); } | |
| size_type | |
| find_first_not_of(const basic_string& __str, size_type __pos = 0) const | |
| { return this->find_first_not_of(__str.data(), __pos, __str.size()); } | |
| size_type | |
| find_first_not_of(const _CharT* __s, size_type __pos, | |
| size_type __n) const; | |
| size_type | |
| find_first_not_of(const _CharT* __s, size_type __pos = 0) const | |
| { return this->find_first_not_of(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| find_first_not_of(_CharT __c, size_type __pos = 0) const; | |
| size_type | |
| find_last_not_of(const basic_string& __str, size_type __pos = npos) const | |
| { return this->find_last_not_of(__str.data(), __pos, __str.size()); } | |
| size_type | |
| find_last_not_of(const _CharT* __s, size_type __pos, | |
| size_type __n) const; | |
| size_type | |
| find_last_not_of(const _CharT* __s, size_type __pos = npos) const | |
| { return this->find_last_not_of(__s, __pos, traits_type::length(__s)); } | |
| size_type | |
| find_last_not_of(_CharT __c, size_type __pos = npos) const; | |
| basic_string | |
| substr(size_type __pos = 0, size_type __n = npos) const | |
| { | |
| if (__pos > this->size()) | |
| __throw_out_of_range("basic_string::substr"); | |
| return basic_string(*this, __pos, __n); | |
| } | |
| int | |
| compare(const basic_string& __str) const | |
| { | |
| size_type __size = this->size(); | |
| size_type __osize = __str.size(); | |
| size_type __len = min(__size, __osize); | |
| int __r = traits_type::compare(_M_data(), __str.data(), __len); | |
| if (!__r) | |
| __r = __size - __osize; | |
| return __r; | |
| } | |
| int | |
| compare(size_type __pos, size_type __n, const basic_string& __str) const; | |
| int | |
| compare(size_type __pos1, size_type __n1, const basic_string& __str, | |
| size_type __pos2, size_type __n2) const; | |
| int | |
| compare(const _CharT* __s) const; | |
| #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS | |
| // 5. String::compare specification questionable | |
| int | |
| compare(size_type __pos, size_type __n1, const _CharT* __s) const; | |
| int | |
| compare(size_type __pos, size_type __n1, const _CharT* __s, | |
| size_type __n2) const; | |
| #endif | |
| }; | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline basic_string<_CharT, _Traits, _Alloc>:: | |
| basic_string() | |
| : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { } | |
| // operator+ | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_string<_CharT, _Traits, _Alloc> | |
| operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { | |
| basic_string<_CharT, _Traits, _Alloc> __str(__lhs); | |
| __str.append(__rhs); | |
| return __str; | |
| } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_string<_CharT,_Traits,_Alloc> | |
| operator+(const _CharT* __lhs, | |
| const basic_string<_CharT,_Traits,_Alloc>& __rhs); | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_string<_CharT,_Traits,_Alloc> | |
| operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline basic_string<_CharT, _Traits, _Alloc> | |
| operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { | |
| basic_string<_CharT, _Traits, _Alloc> __str(__lhs); | |
| __str.append(__rhs); | |
| return __str; | |
| } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline basic_string<_CharT, _Traits, _Alloc> | |
| operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) | |
| { | |
| typedef basic_string<_CharT, _Traits, _Alloc> __string_type; | |
| typedef typename __string_type::size_type __size_type; | |
| __string_type __str(__lhs); | |
| __str.append(__size_type(1), __rhs); | |
| return __str; | |
| } | |
| // operator == | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __lhs.compare(__rhs) == 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator==(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) == 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) == 0; } | |
| // operator != | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) != 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator!=(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) != 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) != 0; } | |
| // operator < | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __lhs.compare(__rhs) < 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) < 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) > 0; } | |
| // operator > | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __lhs.compare(__rhs) > 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) > 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) < 0; } | |
| // operator <= | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __lhs.compare(__rhs) <= 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) <= 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator<=(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) >= 0; } | |
| // operator >= | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __lhs.compare(__rhs) >= 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| const _CharT* __rhs) | |
| { return __lhs.compare(__rhs) >= 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline bool | |
| operator>=(const _CharT* __lhs, | |
| const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { return __rhs.compare(__lhs) <= 0; } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline void | |
| swap(basic_string<_CharT, _Traits, _Alloc>& __lhs, | |
| basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
| { __lhs.swap(__rhs); } | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_istream<_CharT, _Traits>& | |
| operator>>(basic_istream<_CharT, _Traits>& __is, | |
| basic_string<_CharT, _Traits, _Alloc>& __str); | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_ostream<_CharT, _Traits>& | |
| operator<<(basic_ostream<_CharT, _Traits>& __os, | |
| const basic_string<_CharT, _Traits, _Alloc>& __str); | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| basic_istream<_CharT,_Traits>& | |
| getline(basic_istream<_CharT, _Traits>& __is, | |
| basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim); | |
| template<typename _CharT, typename _Traits, typename _Alloc> | |
| inline basic_istream<_CharT,_Traits>& | |
| getline(basic_istream<_CharT, _Traits>& __is, | |
| basic_string<_CharT, _Traits, _Alloc>& __str); | |
| } // namespace std | |
| #endif /* _CPP_BITS_STRING_H */ |