diff options
Diffstat (limited to 'libstdc++-v3/include/bits')
35 files changed, 4301 insertions, 3146 deletions
diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index f91719582f1..13ad0f82e99 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -64,24 +64,18 @@ namespace std // Data members: protected: basic_ostream<_CharT, _Traits>* _M_tie; - char_type _M_fill; - iostate _M_exception; - + mutable char_type _M_fill; + mutable bool _M_fill_init; basic_streambuf<_CharT, _Traits>* _M_streambuf; - iostate _M_streambuf_state; // Cached use_facet<ctype>, which is based on the current locale info. - const __ctype_type* _M_ios_fctype; + const __ctype_type* _M_fctype; // From ostream. const __numput_type* _M_fnumput; // From istream. const __numget_type* _M_fnumget; public: - const __ctype_type* - _M_get_fctype_ios(void) - { return _M_ios_fctype; } - operator void*() const { return this->fail() ? 0 : const_cast<basic_ios*>(this); } @@ -160,7 +154,14 @@ namespace std char_type fill() const - { return _M_fill; } + { + if (!_M_fill_init) + { + _M_fill = this->widen(' '); + _M_fill_init = true; + } + return _M_fill; + } char_type fill(char_type __ch) diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index 4db4a82d5ac..7ee8015e29f 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -64,31 +64,31 @@ namespace std // associated with imbue() // Alloc any new word array first, so if it fails we have "rollback". - _Words* __words = (__rhs._M_word_limit <= _S_local_words) ? - _M_word_array : new _Words[__rhs._M_word_limit]; - - // XXX This is the only reason _Callback_list was defined - // inline. The suspicion is that this increased compilation - // times dramatically for functions that use this member - // function (inserters_extractors, ios_manip_fmtflags). FIX ME, - // clean this stuff up. Callbacks are broken right now, anyway. + _Words* __words = (__rhs._M_word_size <= _S_local_word_size) ? + _M_local_word : new _Words[__rhs._M_word_size]; // Bump refs before doing callbacks, for safety. _Callback_list* __cb = __rhs._M_callbacks; if (__cb) __cb->_M_add_reference(); _M_call_callbacks(erase_event); - if (_M_words != _M_word_array) - delete [] _M_words; + if (_M_word != _M_local_word) + { + delete [] _M_word; + _M_word = 0; + } _M_dispose_callbacks(); _M_callbacks = __cb; // NB: Don't want any added during above. - for (int __i = 0; __i < __rhs._M_word_limit; ++__i) - __words[__i] = __rhs._M_words[__i]; - if (_M_words != _M_word_array) - delete [] _M_words; - _M_words = __words; - _M_word_limit = __rhs._M_word_limit; + for (int __i = 0; __i < __rhs._M_word_size; ++__i) + __words[__i] = __rhs._M_word[__i]; + if (_M_word != _M_local_word) + { + delete [] _M_word; + _M_word = 0; + } + _M_word = __words; + _M_word_size = __rhs._M_word_size; this->flags(__rhs.flags()); this->width(__rhs.width()); @@ -107,8 +107,8 @@ namespace std basic_ios<_CharT, _Traits>::narrow(char_type __c, char __dfault) const { char __ret = __dfault; - if (_M_check_facet(_M_ios_fctype)) - __ret = _M_ios_fctype->narrow(__c, __dfault); + if (_M_check_facet(_M_fctype)) + __ret = _M_fctype->narrow(__c, __dfault); return __ret; } @@ -117,8 +117,8 @@ namespace std basic_ios<_CharT, _Traits>::widen(char __c) const { char_type __ret = char_type(); - if (_M_check_facet(_M_ios_fctype)) - __ret = _M_ios_fctype->widen(__c); + if (_M_check_facet(_M_fctype)) + __ret = _M_fctype->widen(__c); return __ret; } @@ -144,17 +144,20 @@ namespace std _M_cache_facets(_M_ios_locale); _M_tie = 0; - // NB: The 27.4.4.1 Postconditions Table only specifies - // requirements after basic_ios::init() has been called. As part - // of this, fill() must return widen(' '), which needs an imbued - // ctype facet of char_type to return without throwing an - // exception. This is not a required facet, so streams with - // char_type != [char, wchar_t] will not have it by - // default. However, because fill()'s signature is const, this - // data member cannot be lazily initialized. Thus, thoughts of - // using a non-const helper function in ostream inserters is - // really besides the point. - _M_fill = this->widen(' '); + // NB: The 27.4.4.1 Postconditions Table specifies requirements + // after basic_ios::init() has been called. As part of this, + // fill() must return widen(' ') any time after init() has been + // called, which needs an imbued ctype facet of char_type to + // return without throwing an exception. Unfortunately, + // ctype<char_type> is not necessarily a required facet, so + // streams with char_type != [char, wchar_t] will not have it by + // default. Because of this, the correct value for _M_fill is + // constructed on the first call of fill(). That way, + // unformatted input and output with non-required basic_ios + // instantiations is possible even without imbuing the expected + // ctype<char_type> facet. + _M_fill = _CharT(); + _M_fill_init = false; _M_exception = goodbit; _M_streambuf = __sb; @@ -166,9 +169,9 @@ namespace std basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc) { if (has_facet<__ctype_type>(__loc)) - _M_ios_fctype = &use_facet<__ctype_type>(__loc); + _M_fctype = &use_facet<__ctype_type>(__loc); else - _M_ios_fctype = 0; + _M_fctype = 0; // Should be filled in by ostream and istream, respectively. if (has_facet<__numput_type>(__loc)) _M_fnumput = &use_facet<__numput_type>(__loc); @@ -184,7 +187,10 @@ namespace std // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. extern template class basic_ios<char>; + +#ifdef _GLIBCPP_USE_WCHAR_T extern template class basic_ios<wchar_t>; +#endif } // namespace std #endif diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 913484cbb7f..a9c02ce3708 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -99,8 +99,9 @@ namespace std 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 __gnu_cxx::__normal_iterator<pointer, basic_string> iterator; + typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string> + const_iterator; typedef reverse_iterator<const_iterator> const_reverse_iterator; typedef reverse_iterator<iterator> reverse_iterator; @@ -162,7 +163,7 @@ namespace std _CharT* _M_refdata() throw() - { return reinterpret_cast<_CharT*> (this + 1); } + { return reinterpret_cast<_CharT*>(this + 1); } _CharT& operator[](size_t __s) throw() @@ -170,8 +171,10 @@ namespace std _CharT* _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2) - { return (!_M_is_leaked() && __alloc1 == __alloc2) ? - _M_refcopy() : _M_clone(__alloc1); } + { + return (!_M_is_leaked() && __alloc1 == __alloc2) + ? _M_refcopy() : _M_clone(__alloc1); + } // Create & Destroy static _Rep* @@ -639,16 +642,19 @@ namespace std const size_type __size = this->size(); if (__pos > __size) __throw_out_of_range("basic_string::replace"); - if (__size - __n1 > this->max_size() - __n2) - __throw_length_error("basic_string::replace"); const bool __testn1 = __n1 < __size - __pos; const size_type __foldn1 = __testn1 ? __n1 : __size - __pos; + if (__size - __foldn1 > this->max_size() - __n2) + __throw_length_error("basic_string::replace"); if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) || less<const _CharT*>()(_M_data() + __size, __s)) return _M_replace_safe(_M_ibegin() + __pos, _M_ibegin() + __pos + __foldn1, __s, __s + __n2); - else return this->replace(_M_check(__pos), _M_fold(__pos, __n1), - __s, __s + __n2); + // Todo: optimized in-place replace. + else return + _M_replace(_M_ibegin() + __pos, _M_ibegin() + __pos + __foldn1, + __s, __s + __n2, + typename iterator_traits<const _CharT*>::iterator_category()); } basic_string& @@ -682,6 +688,30 @@ namespace std { return _M_replace(__i1, __i2, __k1, __k2, typename iterator_traits<_InputIterator>::iterator_category()); } + // Specializations for the common case of pointer and iterator: + // useful to avoid the overhead of temporary buffering in _M_replace. + basic_string& + replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2) + { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, + __k1, __k2 - __k1); } + + basic_string& + replace(iterator __i1, iterator __i2, const _CharT* __k1, const _CharT* __k2) + { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, + __k1, __k2 - __k1); } + + basic_string& + replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2) + { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, + __k1.base(), __k2 - __k1); + } + + basic_string& + replace(iterator __i1, iterator __i2, const_iterator __k1, const_iterator __k2) + { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, + __k1.base(), __k2 - __k1); + } + private: template<class _InputIterator> basic_string& @@ -731,7 +761,7 @@ namespace std // string::iterator, _CharT*, etc. template<class _FwdIter> static _CharT* - _S_construct(_FwdIter __end, _FwdIter __beg, const _Alloc& __a, + _S_construct(_FwdIter __beg, _FwdIter __end, const _Alloc& __a, forward_iterator_tag); static _CharT* @@ -879,15 +909,14 @@ namespace std int compare(const _CharT* __s) const; -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS -// 5. String::compare specification questionable + // _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 }; diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index dce9b38fcb4..4a22d896792 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -142,6 +142,10 @@ namespace std if (__beg == __end && __a == _Alloc()) return _S_empty_rep()._M_refcopy(); + // NB: Not required, but considered best practice. + if (__builtin_expect(__beg == _InIter(), 0)) + __throw_logic_error("attempt to create string with null pointer"); + // Check for out_of_range and length_error exceptions. _Rep* __r = _Rep::_S_create(__dnew, __a); try @@ -219,7 +223,8 @@ namespace std template<typename _CharT, typename _Traits, typename _Alloc> basic_string<_CharT, _Traits, _Alloc>:: basic_string(const _CharT* __s, const _Alloc& __a) - : _M_dataplus(_S_construct(__s, __s + traits_type::length(__s), __a), __a) + : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : + __s + npos, __a), __a) { } template<typename _CharT, typename _Traits, typename _Alloc> @@ -438,7 +443,7 @@ namespace std void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); _Rep *__p = new (__place) _Rep; __p->_M_capacity = __capacity; - __p->_M_set_sharable(); // one reference + __p->_M_set_sharable(); // One reference. __p->_M_length = 0; return __p; } @@ -492,14 +497,10 @@ namespace std this->erase(__n); // else nothing (in particular, avoid calling _M_mutate() unnecessarily.) } - - // This is the general replace helper, which gets instantiated both - // for input-iterators and forward-iterators. It buffers internally and - // then calls _M_replace_safe. For input-iterators this is almost the - // best we can do, but for forward-iterators many optimizations could be - // conceived: f.i., when source and destination ranges do not overlap - // buffering is not really needed. In order to easily implement them, it - // could become useful to add an _M_replace(forward_iterator_tag) + + // This is the general replace helper, which currently gets instantiated both + // for input iterators and reverse iterators. It buffers internally and then + // calls _M_replace_safe. template<typename _CharT, typename _Traits, typename _Alloc> template<typename _InputIter> basic_string<_CharT, _Traits, _Alloc>& @@ -513,10 +514,8 @@ namespace std } // This is a special replace helper, which does not buffer internally - // and can be used in the "safe" situations involving forward-iterators, + // and can be used in "safe" situations involving forward iterators, // i.e., when source and destination ranges are known to not overlap. - // Presently, is called by _M_replace, by the various append and by - // the assigns. template<typename _CharT, typename _Traits, typename _Alloc> template<typename _ForwardIter> basic_string<_CharT, _Traits, _Alloc>& @@ -885,9 +884,11 @@ namespace std compare(const _CharT* __s) const { size_type __size = this->size(); - int __r = traits_type::compare(_M_data(), __s, __size); + size_type __osize = traits_type::length(__s); + size_type __len = min(__size, __osize); + int __r = traits_type::compare(_M_data(), __s, __len); if (!__r) - __r = __size - traits_type::length(__s); + __r = __size - __osize; return __r; } @@ -945,7 +946,7 @@ namespace std // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. extern template class basic_string<char>; - extern template + extern template basic_istream<char>& operator>>(basic_istream<char>&, string&); extern template @@ -958,6 +959,7 @@ namespace std basic_istream<char>& getline(basic_istream<char>&, string&); +#ifdef _GLIBCPP_USE_WCHAR_T extern template class basic_string<wchar_t>; extern template basic_istream<wchar_t>& @@ -971,6 +973,7 @@ namespace std extern template basic_istream<wchar_t>& getline(basic_istream<wchar_t>&, wstring&); +#endif } // namespace std #endif diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 4e88d9f2e3f..cda776c22da 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -34,7 +34,7 @@ #include <bits/os_defines.h> // The current version of the C++ library in compressed ISO date format. -#define __GLIBCPP__ 20020225 +#define __GLIBCPP__ 20030205 // This is necessary until GCC supports separate template // compilation. @@ -55,6 +55,9 @@ // Use corrected code from the committee library group's issues list. #define _GLIBCPP_RESOLVE_LIB_DEFECTS 1 +// Hopefully temporary workaround to autoconf/m4 issue with quoting '@'. +#define _GLIBCPP_AT_AT "@@" + // In those parts of the standard C++ library that use a mutex instead // of a spin-lock, we now unconditionally use GCC's gthr.h mutex // abstraction layer. All support to directly map to various @@ -69,7 +72,10 @@ // that threads are properly configured on your platform before // assigning blame to the STL container-memory allocator. After doing // so, please report any possible issues to libstdc++@gcc.gnu.org . -// Do not blindly #define __USE_MALLOC here or on the command line. +// Do not define __USE_MALLOC on the command line. Enforce it here: +#ifdef __USE_MALLOC +#error __USE_MALLOC should never be defined. Read the release notes. +#endif // The remainder of the prewritten config is mostly automatic; all the // user hooks are listed above. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 7d14838ab26..41f943d9a59 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -1,6 +1,7 @@ // Character Traits for use by standard string and iostream -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// 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 @@ -53,82 +54,53 @@ namespace std struct char_traits { typedef _CharT char_type; - // Unsigned as wint_t in unsigned. + // Unsigned as wint_t is unsigned. typedef unsigned long int_type; typedef streampos pos_type; typedef streamoff off_type; typedef mbstate_t state_type; static void - assign(char_type& __c1, const char_type& __c2) - { __c1 = __c2; } + assign(char_type& __c1, const char_type& __c2); static bool - eq(const char_type& __c1, const char_type& __c2) - { return __c1 == __c2; } + eq(const char_type& __c1, const char_type& __c2); static bool - lt(const char_type& __c1, const char_type& __c2) - { return __c1 < __c2; } + lt(const char_type& __c1, const char_type& __c2); static int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - for (size_t __i = 0; __i < __n; ++__i) - if (!eq(__s1[__i], __s2[__i])) - return lt(__s1[__i], __s2[__i]) ? -1 : 1; - return 0; - } + compare(const char_type* __s1, const char_type* __s2, size_t __n); static size_t - length(const char_type* __s) - { - const char_type* __p = __s; - while (*__p) ++__p; - return (__p - __s); - } + length(const char_type* __s); static const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) - if (*__p == __a) return __p; - return 0; - } + find(const char_type* __s, size_t __n, const char_type& __a); static char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { return (char_type*) memmove(__s1, __s2, __n * sizeof(char_type)); } + move(char_type* __s1, const char_type* __s2, size_t __n); static char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { return (char_type*) memcpy(__s1, __s2, __n * sizeof(char_type)); } + copy(char_type* __s1, const char_type* __s2, size_t __n); static char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - for (char_type* __p = __s; __p < __s + __n; ++__p) - assign(*__p, __a); - return __s; - } + assign(char_type* __s, size_t __n, char_type __a); static char_type - to_char_type(const int_type& __c) - { return char_type(__c); } + to_char_type(const int_type& __c); static int_type - to_int_type(const char_type& __c) { return int_type(__c); } + to_int_type(const char_type& __c); static bool - eq_int_type(const int_type& __c1, const int_type& __c2) - { return __c1 == __c2; } + eq_int_type(const int_type& __c1, const int_type& __c2); static int_type - eof() { return static_cast<int_type>(-1); } + eof(); static int_type - not_eof(const int_type& __c) - { return eq_int_type(__c, eof()) ? int_type(0) : __c; } + not_eof(const int_type& __c); }; diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h index 506752f3432..3666e987d6d 100644 --- a/libstdc++-v3/include/bits/codecvt.h +++ b/libstdc++-v3/include/bits/codecvt.h @@ -1,6 +1,6 @@ // Locale support (codecvt) -*- C++ -*- -// Copyright (C) 2000, 2001 Free Software Foundation, Inc. +// Copyright (C) 2000, 2001, 2002 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 @@ -66,10 +66,10 @@ { public: // Types: - typedef codecvt_base::result result; - typedef _InternT intern_type; - typedef _ExternT extern_type; - typedef _StateT state_type; + typedef codecvt_base::result result; + typedef _InternT intern_type; + typedef _ExternT extern_type; + typedef _StateT state_type; // 22.2.1.5.1 codecvt members result @@ -159,17 +159,17 @@ { public: // Types: - typedef codecvt_base::result result; - typedef _InternT intern_type; - typedef _ExternT extern_type; - typedef _StateT state_type; + typedef codecvt_base::result result; + typedef _InternT intern_type; + typedef _ExternT extern_type; + typedef _StateT state_type; - // Data Members: - static locale::id id; + public: + static locale::id id; explicit codecvt(size_t __refs = 0) - : __codecvt_abstract_base<_InternT,_ExternT,_StateT> (__refs) { } + : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs) { } protected: virtual @@ -215,11 +215,11 @@ { public: // Types: - typedef char intern_type; - typedef char extern_type; - typedef mbstate_t state_type; + typedef char intern_type; + typedef char extern_type; + typedef mbstate_t state_type; - // Data Members: + public: static locale::id id; explicit @@ -267,12 +267,12 @@ { public: // Types: - typedef wchar_t intern_type; - typedef char extern_type; - typedef mbstate_t state_type; + typedef wchar_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; - // Data Members: - static locale::id id; + public: + static locale::id id; explicit codecvt(size_t __refs = 0); @@ -322,6 +322,7 @@ explicit codecvt_byname(const char*, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__refs) { } + protected: virtual ~codecvt_byname() { } diff --git a/libstdc++-v3/include/bits/fpos.h b/libstdc++-v3/include/bits/fpos.h index 3cb3e4b51a2..279e0ab16ba 100644 --- a/libstdc++-v3/include/bits/fpos.h +++ b/libstdc++-v3/include/bits/fpos.h @@ -105,7 +105,7 @@ namespace std bool operator!=(const fpos& __pos) const { return _M_off != __pos._M_off; } - + streamoff _M_position() const { return _M_off; } diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index 0d0882619e8..0b3bec1c263 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -1,6 +1,6 @@ // File based streams -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -42,24 +42,6 @@ namespace std template<typename _CharT, typename _Traits> void basic_filebuf<_CharT, _Traits>:: - _M_allocate_file() - { - if (!_M_file) - { - _M_buf_unified = true; // Tie input to output for basic_filebuf. - try - { _M_file = new __file_type(&_M_lock); } - catch(...) - { - delete _M_file; - __throw_exception_again; - } - } - } - - template<typename _CharT, typename _Traits> - void - basic_filebuf<_CharT, _Traits>:: _M_allocate_internal_buffer() { if (!_M_buf && _M_buf_size_opt) @@ -67,12 +49,7 @@ namespace std _M_buf_size = _M_buf_size_opt; // Allocate internal buffer. - try { _M_buf = new char_type[_M_buf_size]; } - catch(...) - { - delete [] _M_buf; - __throw_exception_again; - } + _M_buf = new char_type[_M_buf_size]; _M_buf_allocated = true; } } @@ -93,59 +70,12 @@ namespace std } } - template<typename _CharT, typename _Traits> - void - basic_filebuf<_CharT, _Traits>:: - _M_allocate_pback_buffer() - { - if (!_M_pback && _M_pback_size) - { - // Allocate pback buffer. - try - { _M_pback = new char_type[_M_pback_size]; } - catch(...) - { - delete [] _M_pback; - __throw_exception_again; - } - } - } - template<typename _CharT, typename _Traits> basic_filebuf<_CharT, _Traits>:: - basic_filebuf() - : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), - _M_state_beg(__state_type()), _M_buf_allocated(false), - _M_last_overflowed(false) - { } - - template<typename _CharT, typename _Traits> - basic_filebuf<_CharT, _Traits>:: - basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, int_type __s) - : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), - _M_state_beg(__state_type()), _M_buf_allocated(false), - _M_last_overflowed(false) - { - _M_allocate_file(); - _M_file->sys_open(__f, __mode); - if (this->is_open()) - { - _M_mode = __mode; - if (__s) - { - _M_buf_size_opt = __s; - _M_allocate_internal_buffer(); - _M_set_indeterminate(); - } - _M_allocate_pback_buffer(); - } - } - - template<typename _CharT, typename _Traits> - int - basic_filebuf<_CharT, _Traits>:: - fd() - { return _M_file->fd(); } + basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), + _M_state_cur(__state_type()), _M_state_beg(__state_type()), + _M_buf_allocated(false), _M_last_overflowed(false) + { _M_buf_unified = true; } template<typename _CharT, typename _Traits> typename basic_filebuf<_CharT, _Traits>::__filebuf_type* @@ -155,17 +85,14 @@ namespace std __filebuf_type *__ret = NULL; if (!this->is_open()) { - _M_allocate_file(); - _M_file->open(__s, __mode); + _M_file.open(__s, __mode); if (this->is_open()) { _M_allocate_internal_buffer(); - _M_allocate_pback_buffer(); _M_mode = __mode; - - // For time being, set both (in/out) sets of pointers. _M_set_indeterminate(); - if (__mode & ios_base::ate + + if ((__mode & ios_base::ate) && this->seekoff(0, ios_base::end, __mode) < 0) this->close(); __ret = this; @@ -184,19 +111,14 @@ namespace std { const int_type __eof = traits_type::eof(); bool __testput = _M_out_cur && _M_out_beg < _M_out_end; - if (__testput && _M_really_overflow(__eof) == __eof) + if (__testput + && traits_type::eq_int_type(_M_really_overflow(__eof), __eof)) return __ret; // NB: Do this here so that re-opened filebufs will be cool... _M_mode = ios_base::openmode(0); _M_destroy_internal_buffer(); - _M_pback_destroy(); - if (_M_pback) - { - delete [] _M_pback; - _M_pback = NULL; - } #if 0 // XXX not done @@ -206,16 +128,11 @@ namespace std _M_really_overflow(__eof); } #endif - __ret = this; - } - // Can actually allocate this file as part of an open and never - // have it be opened..... - if (_M_file) - { - delete _M_file; - _M_file = NULL; + if (_M_file.close()) + __ret = this; } + _M_last_overflowed = false; return __ret; } @@ -229,106 +146,7 @@ namespace std bool __testin = _M_mode & ios_base::in; if (__testin && this->is_open()) - { - if (_M_in_cur < _M_in_end) - __ret = _M_in_end - _M_in_cur; - else - __ret = 0; - } - _M_last_overflowed = false; - return __ret; - } - - template<typename _CharT, typename _Traits> - typename basic_filebuf<_CharT, _Traits>::int_type - basic_filebuf<_CharT, _Traits>:: - underflow() - { - int_type __ret = traits_type::eof(); - bool __testin = _M_mode & ios_base::in; - bool __testout = _M_mode & ios_base::out; - - if (__testin) - { - // Check for pback madness, and if so swich back to the - // normal buffers and jet outta here before expensive - // fileops happen... - if (_M_pback_init) - { - _M_pback_destroy(); - if (_M_in_cur < _M_in_end) - return traits_type::to_int_type(*_M_in_cur); - } - - // Sync internal and external buffers. - // NB: __testget -> __testput as _M_buf_unified here. - bool __testget = _M_in_cur && _M_in_beg < _M_in_cur; - bool __testinit = _M_is_indeterminate(); - if (__testget) - { - if (__testout) - _M_really_overflow(); -#if _GLIBCPP_AVOID_FSEEK - else if ((_M_in_cur - _M_in_beg) == 1) - _M_file->sys_getc(); -#endif - else - _M_file->seekoff(_M_in_cur - _M_in_beg, - ios_base::cur, ios_base::in); - } - - if (__testinit || __testget) - { - const locale __loc = this->getloc(); - const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); - - streamsize __elen = 0; - streamsize __ilen = 0; - if (__cvt.always_noconv()) - { - __elen = _M_file->xsgetn(reinterpret_cast<char*>(_M_in_beg), - _M_buf_size); - __ilen = __elen; - } - else - { - char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size)); - __elen = _M_file->xsgetn(__buf, _M_buf_size); - - const char* __eend; - char_type* __iend; - __res_type __r = __cvt.in(_M_state_cur, __buf, - __buf + __elen, __eend, _M_in_beg, - _M_in_beg + _M_buf_size, __iend); - if (__r == codecvt_base::ok) - __ilen = __iend - _M_in_beg; - else - { - // Unwind. - __ilen = 0; - _M_file->seekoff(-__elen, ios_base::cur, ios_base::in); - } - } - - if (0 < __ilen) - { - _M_set_determinate(__ilen); - if (__testout) - _M_out_cur = _M_in_cur; - __ret = traits_type::to_int_type(*_M_in_cur); -#if _GLIBCPP_AVOID_FSEEK - if (__elen == 1) - _M_file->sys_ungetc(*_M_in_cur); - else - { -#endif - _M_file->seekoff(-__elen, ios_base::cur, ios_base::in); -#if _GLIBCPP_AVOID_FSEEK - } -#endif - } - } - } + __ret = _M_in_end - _M_in_cur; _M_last_overflowed = false; return __ret; } @@ -437,7 +255,7 @@ namespace std if (__cvt.always_noconv() && __ilen) { - __elen += _M_file->xsputn(reinterpret_cast<char*>(__ibuf), __ilen); + __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen); __plen += __ilen; } else @@ -461,7 +279,7 @@ namespace std if (__blen) { - __elen += _M_file->xsputn(__buf, __blen); + __elen += _M_file.xsputn(__buf, __blen); __plen += __blen; } @@ -478,7 +296,7 @@ namespace std __rlen = 0; if (__rlen) { - __elen += _M_file->xsputn(__buf, __rlen); + __elen += _M_file.xsputn(__buf, __rlen); __plen += __rlen; } } @@ -492,7 +310,7 @@ namespace std { int_type __ret = traits_type::eof(); bool __testput = _M_out_cur && _M_out_beg < _M_out_end; - bool __testunbuffered = _M_file && !_M_buf_size; + bool __testunbuffered = _M_file.is_open() && !_M_buf_size_opt; if (__testput || __testunbuffered) { @@ -500,6 +318,15 @@ namespace std streamsize __elen = 0; streamsize __plen = 0; + // Need to restore current position. The position of the external + // byte sequence (_M_file) corresponds to _M_filepos, and we need + // to move it to _M_out_beg for the write. + if (_M_filepos && _M_filepos != _M_out_beg) + { + off_type __off = _M_out_beg - _M_filepos; + _M_file.seekoff(__off, ios_base::cur); + } + // Convert internal buffer to external representation, output. // NB: In the unbuffered case, no internal buffer exists. if (!__testunbuffered) @@ -507,16 +334,20 @@ namespace std __elen, __plen); // Convert pending sequence to external representation, output. + // If eof, then just attempt sync. if (!traits_type::eq_int_type(__c, traits_type::eof())) { char_type __pending = traits_type::to_char_type(__c); _M_convert_to_external(&__pending, 1, __elen, __plen); - } - // Last, sync internal and external buffers. - // NB: Need this so that external byte sequence reflects - // internal buffer plus pending sequence. - if (__elen == __plen && !_M_file->sync()) + // User code must flush when switching modes (thus don't sync). + if (__elen == __plen) + { + _M_set_indeterminate(); + __ret = traits_type::not_eof(__c); + } + } + else if (!_M_file.sync()) { _M_set_indeterminate(); __ret = traits_type::not_eof(__c); @@ -546,9 +377,6 @@ namespace std _M_buf = __s; _M_buf_size_opt = _M_buf_size = __n; _M_set_indeterminate(); - - // Step 3: Make sure a pback buffer is allocated. - _M_allocate_pback_buffer(); } _M_last_overflowed = false; return this; @@ -560,17 +388,16 @@ namespace std seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) { pos_type __ret = pos_type(off_type(-1)); - bool __testopen = this->is_open(); - bool __testin = __mode & ios_base::in && _M_mode & ios_base::in; - bool __testout = __mode & ios_base::out && _M_mode & ios_base::out; + bool __testin = (ios_base::in & _M_mode & __mode) != 0; + bool __testout = (ios_base::out & _M_mode & __mode) != 0; // Should probably do has_facet checks here. int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding(); if (__width < 0) __width = 0; - bool __testfail = __off != 0 && __width <= 0; + bool __testfail = __off != 0 && __width <= 0; - if (__testopen && !__testfail && (__testin || __testout)) + if (this->is_open() && !__testfail && (__testin || __testout)) { // Ditch any pback buffers to avoid confusion. _M_pback_destroy(); @@ -591,19 +418,18 @@ namespace std _M_output_unshift(); } //in - // NB: underflow() rewinds the external buffer. else if (__testget && __way == ios_base::cur) - __computed_off += _M_in_cur - _M_in_beg; + __computed_off += _M_in_cur - _M_filepos; - __ret = _M_file->seekoff(__computed_off, __way, __mode); + __ret = _M_file.seekoff(__computed_off, __way, __mode); _M_set_indeterminate(); } // NB: Need to do this in case _M_file in indeterminate - // state, ie _M_file->_offset == -1 + // state, ie _M_file._offset == -1 else { - __ret = _M_file->seekoff(__off, ios_base::cur, __mode); - __ret += max(_M_out_cur, _M_in_cur) - _M_buf; + __ret = _M_file.seekoff(__off, ios_base::cur, __mode); + __ret += max(_M_out_cur, _M_in_cur) - _M_filepos; } } _M_last_overflowed = false; @@ -615,13 +441,10 @@ namespace std basic_filebuf<_CharT, _Traits>:: seekpos(pos_type __pos, ios_base::openmode __mode) { - pos_type __ret; - off_type __off = __pos; - - __ret = this->seekoff(__off, ios_base::beg, __mode); - - _M_last_overflowed = false; - return __ret; +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +// 171. Strange seekpos() semantics due to joint position + return this->seekoff(off_type(__pos), ios_base::beg, __mode); +#endif } template<typename _CharT, typename _Traits> @@ -638,10 +461,7 @@ namespace std bool __testbeg = gptr() == eback() && pptr() == pbase(); if (__testbeg && _M_buf_locale != __loc) - { - _M_buf_locale = __loc; - _M_buf_locale_init = true; - } + _M_buf_locale = __loc; // NB this may require the reconversion of previously // converted chars. This in turn may cause the reconstruction @@ -654,13 +474,16 @@ namespace std // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. extern template class basic_filebuf<char>; - extern template class basic_filebuf<wchar_t>; extern template class basic_ifstream<char>; - extern template class basic_ifstream<wchar_t>; extern template class basic_ofstream<char>; - extern template class basic_ofstream<wchar_t>; extern template class basic_fstream<char>; + +#ifdef _GLIBCPP_USE_WCHAR_T + extern template class basic_filebuf<wchar_t>; + extern template class basic_ifstream<wchar_t>; + extern template class basic_ofstream<wchar_t>; extern template class basic_fstream<wchar_t>; +#endif } // namespace std #endif diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index 7525e7d6f4c..a56475ccef6 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -158,6 +158,8 @@ namespace std explicit failure(const string& __str) throw(); + // This declaration is not useless: + // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~failure() throw(); @@ -218,6 +220,9 @@ namespace std typedef int io_state; typedef int open_mode; typedef int seek_dir; + + typedef std::streampos streampos; + typedef std::streamoff streamoff; #endif // Callbacks; @@ -238,6 +243,8 @@ namespace std streamsize _M_precision; streamsize _M_width; fmtflags _M_flags; + iostate _M_exception; + iostate _M_streambuf_state; // 27.4.2.6 Members for callbacks // 27.4.2.6 ios_base callbacks @@ -256,9 +263,9 @@ namespace std void _M_add_reference() { __atomic_add(&_M_refcount, 1); } + // 0 => OK to delete. int _M_remove_reference() { return __exchange_and_add(&_M_refcount, -1); } - // 0 => OK to delete }; _Callback_list* _M_callbacks; @@ -274,13 +281,19 @@ namespace std { void* _M_pword; long _M_iword; + _Words() : _M_pword(0), _M_iword(0) { } }; - static const int _S_local_words = 8; - _Words _M_word_array[_S_local_words]; // Guaranteed storage - _Words _M_dummy; // Only for failed iword/pword calls. - _Words* _M_words; - int _M_word_limit; + // Only for failed iword/pword calls. + _Words _M_word_zero; + + // Guaranteed storage. + static const int _S_local_word_size = 8; + _Words _M_local_word[_S_local_word_size]; + + // Allocated storage. + int _M_word_size; + _Words* _M_word; _Words& _M_grow_words(int __index); @@ -386,16 +399,16 @@ namespace std inline long& iword(int __ix) { - _Words& __word = (__ix < _M_word_limit) - ? _M_words[__ix] : _M_grow_words(__ix); + _Words& __word = (__ix < _M_word_size) + ? _M_word[__ix] : _M_grow_words(__ix); return __word._M_iword; } inline void*& pword(int __ix) { - _Words& __word = (__ix < _M_word_limit) - ? _M_words[__ix] : _M_grow_words(__ix); + _Words& __word = (__ix < _M_word_size) + ? _M_word[__ix] : _M_grow_words(__ix); return __word._M_pword; } diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index 4a32c659be4..a6e49a923bd 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -50,16 +50,18 @@ namespace std if (!__noskipws && (__in.flags() & ios_base::skipws)) { const __int_type __eof = traits_type::eof(); - const __ctype_type* __ctype = __in._M_get_fctype_ios(); __streambuf_type* __sb = __in.rdbuf(); __int_type __c = __sb->sgetc(); - - while (__c != __eof && __ctype->is(ctype_base::space, __c)) - __c = __sb->snextc(); + + if (__in._M_check_facet(__in._M_fctype)) + while (!traits_type::eq_int_type(__c, __eof) + && __in._M_fctype->is(ctype_base::space, + traits_type::to_char_type(__c))) + __c = __sb->snextc(); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS //195. Should basic_istream::sentry's constructor ever set eofbit? - if (__c == __eof) + if (traits_type::eq_int_type(__c, __eof)) __in.setstate(ios_base::eofbit); #endif } @@ -520,7 +522,7 @@ namespace std { __c = this->rdbuf()->sbumpc(); // 27.6.1.1 paragraph 3 - if (__c != __eof) + if (!traits_type::eq_int_type(__c, __eof)) _M_gcount = 1; else this->setstate(ios_base::eofbit | ios_base::failbit); @@ -551,7 +553,7 @@ namespace std const int_type __eof = traits_type::eof(); int_type __bufval = this->rdbuf()->sbumpc(); // 27.6.1.1 paragraph 3 - if (__bufval != __eof) + if (!traits_type::eq_int_type(__bufval, __eof)) { _M_gcount = 1; __c = traits_type::to_char_type(__bufval); @@ -578,28 +580,24 @@ namespace std { _M_gcount = 0; sentry __cerb(*this, true); - if (__cerb && __n > 1) + if (__cerb) { try { const int_type __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); - int_type __c = __sb->sbumpc(); - bool __testdelim = __c == __idelim; - bool __testeof = __c == __eof; + int_type __c = __sb->sgetc(); - while (_M_gcount < __n - 1 && !__testeof && !__testdelim) + while (_M_gcount + 1 < __n + && !traits_type::eq_int_type(__c, __eof) + && !traits_type::eq_int_type(__c, __idelim)) { *__s++ = traits_type::to_char_type(__c); + __c = __sb->snextc(); ++_M_gcount; - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testdelim = __c == __idelim; } - if (__testdelim || _M_gcount == __n - 1) - __sb->sputbackc(__c); - if (__testeof) + if (traits_type::eq_int_type(__c, __eof)) this->setstate(ios_base::eofbit); } catch(exception& __fail) @@ -626,35 +624,32 @@ namespace std sentry __cerb(*this, true); if (__cerb) { - int_type __c; - __streambuf_type* __this_sb = this->rdbuf(); try { const int_type __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); - __c = __this_sb->sbumpc(); - bool __testdelim = __c == __idelim; - bool __testeof = __c == __eof; - bool __testput = true; + __streambuf_type* __this_sb = this->rdbuf(); + int_type __c = __this_sb->sgetc(); + char_type __c2 = traits_type::to_char_type(__c); - while (!__testeof && !__testdelim - && (__testput = __sb.sputc(traits_type::to_char_type(__c)) - != __eof)) + while (!traits_type::eq_int_type(__c, __eof) + && !traits_type::eq_int_type(__c, __idelim) + && !traits_type::eq_int_type(__sb.sputc(__c2), __eof)) { ++_M_gcount; - __c = __this_sb->sbumpc(); - __testeof = __c == __eof; - __testdelim = __c == __idelim; + __c = __this_sb->snextc(); + __c2 = traits_type::to_char_type(__c); } - if (__testdelim || !__testput) - __this_sb->sputbackc(traits_type::to_char_type(__c)); - if (__testeof) + if (traits_type::eq_int_type(__c, __eof)) this->setstate(ios_base::eofbit); } catch(exception& __fail) { - // Exception may result from sputc->overflow. - __this_sb->sputbackc(traits_type::to_char_type(__c)); + // 27.6.1.3 paragraph 1 + // Turn this on without causing an ios::failure to be thrown. + this->setstate(ios_base::badbit); + if ((this->exceptions() & ios_base::badbit) != 0) + __throw_exception_again; } } if (!_M_gcount) @@ -673,33 +668,30 @@ namespace std { try { - __streambuf_type* __sb = this->rdbuf(); - int_type __c = __sb->sbumpc(); - ++_M_gcount; const int_type __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); - bool __testdelim = __c == __idelim; - bool __testeof = __c == __eof; + __streambuf_type* __sb = this->rdbuf(); + int_type __c = __sb->sgetc(); - while (_M_gcount < __n && !__testeof && !__testdelim) + while (_M_gcount + 1 < __n + && !traits_type::eq_int_type(__c, __eof) + && !traits_type::eq_int_type(__c, __idelim)) { *__s++ = traits_type::to_char_type(__c); - __c = __sb->sbumpc(); + __c = __sb->snextc(); ++_M_gcount; - __testeof = __c == __eof; - __testdelim = __c == __idelim; } - - if (__testeof) - { - --_M_gcount; - this->setstate(ios_base::eofbit); - } - else if (!__testdelim) + if (traits_type::eq_int_type(__c, __eof)) + this->setstate(ios_base::eofbit); + else { - --_M_gcount; - __sb->sputbackc(traits_type::to_char_type(__c)); - this->setstate(ios_base::failbit); + if (traits_type::eq_int_type(__c, __idelim)) + { + __sb->sbumpc(); + ++_M_gcount; + } + else + this->setstate(ios_base::failbit); } } catch(exception& __fail) @@ -728,24 +720,19 @@ namespace std { try { - const int_type __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); - int_type __c = __sb->sbumpc(); - bool __testdelim = __c == __idelim; - bool __testeof = __c == __eof; + int_type __c; __n = min(__n, numeric_limits<streamsize>::max()); - while (_M_gcount < __n - 1 && !__testeof && !__testdelim) + while (_M_gcount < __n + && !traits_type::eq_int_type(__c = __sb->sbumpc(), __eof)) { ++_M_gcount; - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testdelim = __c == __idelim; + if (traits_type::eq_int_type(__c, __delim)) + break; } - if ((_M_gcount == __n - 1 && !__testeof) || __testdelim) - ++_M_gcount; - if (__testeof) + if (traits_type::eq_int_type(__c, __eof)) this->setstate(ios_base::eofbit); } catch(exception& __fail) @@ -793,39 +780,19 @@ namespace std sentry __cerb(*this, true); if (__cerb) { - if (__n > 0) + try { - try - { - const int_type __eof = traits_type::eof(); - __streambuf_type* __sb = this->rdbuf(); - int_type __c = __sb->sbumpc(); - bool __testeof = __c == __eof; - - while (_M_gcount < __n - 1 && !__testeof) - { - *__s++ = traits_type::to_char_type(__c); - ++_M_gcount; - __c = __sb->sbumpc(); - __testeof = __c == __eof; - } - if (__testeof) - this->setstate(ios_base::eofbit | ios_base::failbit); - else - { - // _M_gcount == __n - 1 - *__s++ = traits_type::to_char_type(__c); - ++_M_gcount; - } - } - catch(exception& __fail) - { - // 27.6.1.3 paragraph 1 - // Turn this on without causing an ios::failure to be thrown. - this->setstate(ios_base::badbit); - if ((this->exceptions() & ios_base::badbit) != 0) - __throw_exception_again; - } + _M_gcount = this->rdbuf()->sgetn(__s, __n); + if (_M_gcount != __n) + this->setstate(ios_base::eofbit | ios_base::failbit); + } + catch(exception& __fail) + { + // 27.6.1.3 paragraph 1 + // Turn this on without causing an ios::failure to be thrown. + this->setstate(ios_base::badbit); + if ((this->exceptions() & ios_base::badbit) != 0) + __throw_exception_again; } } else @@ -838,32 +805,30 @@ namespace std basic_istream<_CharT, _Traits>:: readsome(char_type* __s, streamsize __n) { - const int_type __eof = traits_type::eof(); _M_gcount = 0; sentry __cerb(*this, true); if (__cerb) { - if (__n > 0) + try { - try + // Cannot compare int_type with streamsize generically. + streamsize __num = this->rdbuf()->in_avail(); + if (__num >= 0) { - streamsize __num = this->rdbuf()->in_avail(); - if (__num != static_cast<streamsize>(__eof)) - { - __num = min(__num, __n); - _M_gcount = this->rdbuf()->sgetn(__s, __num); - } - else - this->setstate(ios_base::eofbit); - } - catch(exception& __fail) - { - // 27.6.1.3 paragraph 1 - // Turn this on without causing an ios::failure to be thrown. - this->setstate(ios_base::badbit); - if ((this->exceptions() & ios_base::badbit) != 0) - __throw_exception_again; + __num = min(__num, __n); + if (__num) + _M_gcount = this->rdbuf()->sgetn(__s, __num); } + else + this->setstate(ios_base::eofbit); + } + catch(exception& __fail) + { + // 27.6.1.3 paragraph 1 + // Turn this on without causing an ios::failure to be thrown. + this->setstate(ios_base::badbit); + if ((this->exceptions() & ios_base::badbit) != 0) + __throw_exception_again; } } else @@ -883,7 +848,8 @@ namespace std { const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); - if (!__sb || __sb->sputbackc(__c) == __eof) + if (!__sb + || traits_type::eq_int_type(__sb->sputbackc(__c), __eof)) this->setstate(ios_base::badbit); } catch(exception& __fail) @@ -913,7 +879,8 @@ namespace std { const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); - if (!__sb || __eof == __sb->sungetc()) + if (!__sb + || traits_type::eq_int_type(__sb->sungetc(), __eof)) this->setstate(ios_base::badbit); } catch(exception& __fail) @@ -935,7 +902,7 @@ namespace std basic_istream<_CharT, _Traits>:: sync(void) { - int __ret = traits_type::eof(); + int __ret = -1; _M_gcount = 0; sentry __cerb(*this, true); if (__cerb) @@ -943,10 +910,13 @@ namespace std try { __streambuf_type* __sb = this->rdbuf(); - if (!__sb || __ret == __sb->pubsync()) - this->setstate(ios_base::badbit); - else - __ret = 0; + if (__sb) + { + if (__sb->pubsync() == -1) + this->setstate(ios_base::badbit); + else + __ret = 0; + } } catch(exception& __fail) { @@ -966,23 +936,8 @@ namespace std tellg(void) { pos_type __ret = pos_type(-1); - _M_gcount = 0; - sentry __cerb(*this, true); - if (__cerb) - { - try - { - __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); - } - catch(exception& __fail) - { - // 27.6.1.3 paragraph 1 - // Turn this on without causing an ios::failure to be thrown. - this->setstate(ios_base::badbit); - if ((this->exceptions() & ios_base::badbit) != 0) - __throw_exception_again; - } - } + if (!this->fail()) + __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); return __ret; } @@ -993,28 +948,16 @@ namespace std seekg(pos_type __pos) { _M_gcount = 0; - sentry __cerb(*this, true); - if (__cerb) + if (!this->fail()) { - try - { #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 136. seekp, seekg setting wrong streams? - pos_type __err = this->rdbuf()->pubseekpos(__pos, ios_base::in); + pos_type __err = this->rdbuf()->pubseekpos(__pos, ios_base::in); // 129. Need error indication from seekp() and seekg() - if (__err == pos_type(off_type(-1))) - this->setstate(ios_base::failbit); + if (__err == pos_type(off_type(-1))) + this->setstate(ios_base::failbit); #endif - } - catch(exception& __fail) - { - // 27.6.1.3 paragraph 1 - // Turn this on without causing an ios::failure to be thrown. - this->setstate(ios_base::badbit); - if ((this->exceptions() & ios_base::badbit) != 0) - __throw_exception_again; - } } return *this; } @@ -1025,29 +968,17 @@ namespace std seekg(off_type __off, ios_base::seekdir __dir) { _M_gcount = 0; - sentry __cerb(*this, true); - if (__cerb) + if (!this->fail()) { - try - { #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 136. seekp, seekg setting wrong streams? - pos_type __err = this->rdbuf()->pubseekoff(__off, __dir, - ios_base::in); + pos_type __err = this->rdbuf()->pubseekoff(__off, __dir, + ios_base::in); // 129. Need error indication from seekp() and seekg() - if (__err == pos_type(off_type(-1))) - this->setstate(ios_base::failbit); + if (__err == pos_type(off_type(-1))) + this->setstate(ios_base::failbit); #endif - } - catch(exception& __fail) - { - // 27.6.1.3 paragraph 1 - // Turn this on without causing an ios::failure to be thrown. - this->setstate(ios_base::badbit); - if ((this->exceptions() & ios_base::badbit) != 0) - __throw_exception_again; - } } return *this; } @@ -1098,25 +1029,20 @@ namespace std if (__num == 0) __num = numeric_limits<streamsize>::max(); - __streambuf_type* __sb = __in.rdbuf(); - const __ctype_type* __ctype = __in._M_get_fctype_ios(); - int_type __c = __sb->sbumpc(); + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); const int_type __eof = _Traits::eof(); - bool __testsp = __ctype->is(ctype_base::space, __c); - bool __testeof = __c == __eof; + __streambuf_type* __sb = __in.rdbuf(); + int_type __c = __sb->sgetc(); - while (__extracted < __num - 1 && !__testeof && !__testsp) + while (__extracted < __num - 1 + && !_Traits::eq_int_type(__c, __eof) + && !__ctype.is(ctype_base::space, __c)) { *__s++ = __c; ++__extracted; - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testsp = __ctype->is(ctype_base::space, __c); + __c = __sb->snextc(); } - - if (!__testeof) - __sb->sputbackc(__c); - else + if (_Traits::eq_int_type(__c, __eof)) __in.setstate(ios_base::eofbit); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS @@ -1148,26 +1074,17 @@ namespace std typedef typename __istream_type::__streambuf_type __streambuf_type; typedef typename __istream_type::__ctype_type __ctype_type; typedef typename __istream_type::int_type __int_type; - typedef typename __istream_type::char_type __char_type; - __streambuf_type* __sb = __in.rdbuf(); - const __ctype_type* __ctype = __in._M_get_fctype_ios(); + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); const __int_type __eof = _Traits::eof(); - __int_type __c; - bool __testeof; - bool __testsp; + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); - do - { - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testsp = __ctype->is(ctype_base::space, __c); - } - while (!__testeof && __testsp); + while (!_Traits::eq_int_type(__c, __eof) + && __ctype.is(ctype_base::space, __c)) + __c = __sb->snextc(); - if (!__testeof && !__testsp) - __sb->sputbackc(__c); - else + if (_Traits::eq_int_type(__c, __eof)) __in.setstate(ios_base::eofbit); return __in; @@ -1195,24 +1112,20 @@ namespace std __size_type __n; __n = __w > 0 ? static_cast<__size_type>(__w) : __str.max_size(); - __streambuf_type* __sb = __in.rdbuf(); - const __ctype_type* __ctype = __in._M_get_fctype_ios(); - __int_type __c = __sb->sbumpc(); + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); const __int_type __eof = _Traits::eof(); - bool __testsp = __ctype->is(ctype_base::space, __c); - bool __testeof = __c == __eof; - - while (__extracted < __n && !__testeof && !__testsp) + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); + + while (__extracted < __n + && !_Traits::eq_int_type(__c, __eof) + && !__ctype.is(ctype_base::space, __c)) { __str += _Traits::to_char_type(__c); ++__extracted; - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testsp = __ctype->is(ctype_base::space, __c); + __c = __sb->snextc(); } - if (!__testeof) - __sb->sputbackc(__c); - else + if (_Traits::eq_int_type(__c, __eof)) __in.setstate(ios_base::eofbit); __in.width(0); } @@ -1248,18 +1161,18 @@ namespace std __streambuf_type* __sb = __in.rdbuf(); __int_type __c = __sb->sbumpc(); const __int_type __eof = _Traits::eof(); - __testdelim = __c == __idelim; - bool __testeof = __c == __eof; + __testdelim = _Traits::eq_int_type(__c, __idelim); - while (__extracted <= __n && !__testeof && !__testdelim) + while (__extracted <= __n + && !_Traits::eq_int_type(__c, __eof) + && !__testdelim) { __str += _Traits::to_char_type(__c); ++__extracted; __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testdelim = __c == __idelim; + __testdelim = _Traits::eq_int_type(__c, __idelim); } - if (__testeof) + if (_Traits::eq_int_type(__c, __eof)) __in.setstate(ios_base::eofbit); } if (!__extracted && !__testdelim) @@ -1285,8 +1198,10 @@ namespace std extern template istream& operator>>(istream&, unsigned char*); extern template istream& operator>>(istream&, signed char*); +#ifdef _GLIBCPP_USE_WCHAR_T extern template class basic_istream<wchar_t>; extern template wistream& ws(wistream&); extern template wistream& operator>>(wistream&, wchar_t&); extern template wistream& operator>>(wistream&, wchar_t*); +#endif } // namespace std diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index c00e17cd5aa..6e42b3bb5ea 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -43,13 +43,21 @@ #pragma GCC system_header #include <ctime> // For struct tm -#ifdef _GLIBCPP_USE_WCHAR_T -# include <cwctype> // For wctype_t -#endif +#include <cwctype> // For wctype_t #include <ios> // For ios_base namespace std { + // NB: Don't instantiate required wchar_t facets if no wchar_t support. +#ifdef _GLIBCPP_USE_WCHAR_T +# define _GLIBCPP_NUM_FACETS 28 +#else +# define _GLIBCPP_NUM_FACETS 14 +#endif + + template<typename _CharT, typename _Traits> + struct __pad; + // 22.2.1.1 Template class ctype // Include host and configuration specific ctype enums for ctype_base. #include <bits/ctype_base.h> @@ -169,11 +177,11 @@ namespace std typedef _CharT char_type; typedef typename ctype::mask mask; + static locale::id id; + explicit ctype(size_t __refs = 0) : __ctype_abstract_base<_CharT>(__refs) { } - static locale::id id; - protected: virtual ~ctype(); @@ -421,12 +429,6 @@ namespace std class __num_base { protected: - // Used to establish gating factor for base 16 input. - static const double _S_scale_hex; - - // Used to establish gating factor for base 8 input. - static const double _S_scale_oct; - // String literal of acceptable (narrow) input, for num_get. // "0123456789eEabcdfABCDF" static const char _S_atoms[]; @@ -464,9 +466,9 @@ namespace std private: char_type _M_decimal_point; char_type _M_thousands_sep; - string _M_grouping; - string_type _M_truename; - string_type _M_falsename; + const char* _M_grouping; + const char_type* _M_truename; + const char_type* _M_falsename; public: explicit @@ -499,7 +501,7 @@ namespace std protected: virtual - ~numpunct() { } + ~numpunct(); virtual char_type do_decimal_point() const @@ -530,11 +532,17 @@ namespace std locale::id numpunct<_CharT>::id; template<> + numpunct<char>::~numpunct(); + + template<> void numpunct<char>::_M_initialize_numpunct(__c_locale __cloc); #ifdef _GLIBCPP_USE_WCHAR_T template<> + numpunct<wchar_t>::~numpunct(); + + template<> void numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc); #endif @@ -647,6 +655,7 @@ namespace std virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const; + virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, long&) const; @@ -692,6 +701,23 @@ namespace std template<typename _CharT, typename _InIter> locale::id num_get<_CharT, _InIter>::id; +#if 0 + // Partial specialization for istreambuf_iterator, so can use traits_type. + template<typename _CharT> + class num_get<_CharT, istreambuf_iterator<_CharT> >; + + iter_type + _M_extract_float(iter_type, iter_type, ios_base&, ios_base::iostate&, + string& __xtrc) const; + + iter_type + _M_extract_int(iter_type, iter_type, ios_base&, ios_base::iostate&, + string& __xtrc, int& __base) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const; +#endif + template<typename _CharT, typename _OutIter> class num_put : public locale::facet, public __num_base { @@ -819,9 +845,8 @@ namespace std explicit collate(size_t __refs = 0) : locale::facet(__refs) - { _M_c_locale_collate = _S_clone_c_locale(_S_c_locale); } + { _M_c_locale_collate = _S_c_locale; } - // Non-standard. explicit collate(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) @@ -842,10 +867,10 @@ namespace std // Used to abstract out _CharT bits in virtual member functions, below. int - _M_compare_helper(const _CharT*, const _CharT*) const; + _M_compare(const _CharT*, const _CharT*) const; size_t - _M_transform_helper(_CharT*, const _CharT*, size_t) const; + _M_transform(_CharT*, const _CharT*, size_t) const; protected: virtual @@ -869,21 +894,20 @@ namespace std // Specializations. template<> int - collate<char>::_M_compare_helper(const char*, const char*) const; + collate<char>::_M_compare(const char*, const char*) const; template<> size_t - collate<char>::_M_transform_helper(char*, const char*, size_t) const; + collate<char>::_M_transform(char*, const char*, size_t) const; #ifdef _GLIBCPP_USE_WCHAR_T template<> int - collate<wchar_t>::_M_compare_helper(const wchar_t*, const wchar_t*) const; + collate<wchar_t>::_M_compare(const wchar_t*, const wchar_t*) const; template<> size_t - collate<wchar_t>::_M_transform_helper(wchar_t*, const wchar_t*, - size_t) const; + collate<wchar_t>::_M_transform(wchar_t*, const wchar_t*, size_t) const; #endif template<typename _CharT> @@ -928,7 +952,7 @@ namespace std protected: __c_locale _M_c_locale_timepunct; - const char* _M_name_timepunct; + char* _M_name_timepunct; const _CharT* _M_date_format; const _CharT* _M_date_era_format; const _CharT* _M_time_format; @@ -987,18 +1011,14 @@ namespace std public: explicit - __timepunct(size_t __refs = 0) - : locale::facet(__refs), _M_name_timepunct("C") - { _M_initialize_timepunct(); } + __timepunct(size_t __refs = 0); explicit - __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0) - : locale::facet(__refs), _M_name_timepunct(__s) - { _M_initialize_timepunct(__cloc); } + __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0); void - _M_put_helper(_CharT* __s, size_t __maxlen, const _CharT* __format, - const tm* __tm) const; + _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format, + const tm* __tm) const; void _M_date_formats(const _CharT** __date) const @@ -1091,11 +1111,7 @@ namespace std protected: virtual - ~__timepunct() - { - if (_M_c_locale_timepunct) - _S_destroy_c_locale(_M_c_locale_timepunct); - } + ~__timepunct(); // For use at construction time only. void @@ -1116,8 +1132,7 @@ namespace std template<> void - __timepunct<char>::_M_put_helper(char*, size_t, const char*, - const tm*) const; + __timepunct<char>::_M_put(char*, size_t, const char*, const tm*) const; #ifdef _GLIBCPP_USE_WCHAR_T template<> @@ -1130,14 +1145,16 @@ namespace std template<> void - __timepunct<wchar_t>::_M_put_helper(wchar_t*, size_t, const wchar_t*, - const tm*) const; + __timepunct<wchar_t>::_M_put(wchar_t*, size_t, const wchar_t*, + const tm*) const; #endif // Generic. template<typename _CharT> const _CharT* __timepunct<_CharT>::_S_timezones[14]; + // Include host and configuration specific timepunct functions. + #include <bits/time_members.h> template<typename _CharT, typename _InIter> class time_get : public locale::facet, public time_base @@ -1328,19 +1345,19 @@ namespace std typedef _CharT char_type; typedef basic_string<_CharT> string_type; - static const bool intl = _Intl; - static locale::id id; + static const bool intl = _Intl; + static locale::id id; private: - char_type _M_decimal_point; - char_type _M_thousands_sep; - string _M_grouping; - string_type _M_curr_symbol; - string_type _M_positive_sign; - string_type _M_negative_sign; - int _M_frac_digits; - pattern _M_pos_format; - pattern _M_neg_format; + const char* _M_grouping; + char_type _M_decimal_point; + char_type _M_thousands_sep; + const char_type* _M_curr_symbol; + const char_type* _M_positive_sign; + const char_type* _M_negative_sign; + int _M_frac_digits; + pattern _M_pos_format; + pattern _M_neg_format; public: explicit @@ -1348,8 +1365,9 @@ namespace std { _M_initialize_moneypunct(); } explicit - moneypunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) - { _M_initialize_moneypunct(__cloc); } + moneypunct(__c_locale __cloc, const char* __s, size_t __refs = 0) + : locale::facet(__refs) + { _M_initialize_moneypunct(__cloc, __s); } char_type decimal_point() const @@ -1389,7 +1407,7 @@ namespace std protected: virtual - ~moneypunct() { } + ~moneypunct(); virtual char_type do_decimal_point() const @@ -1429,7 +1447,8 @@ namespace std // For use at construction time only. void - _M_initialize_moneypunct(__c_locale __cloc = NULL); + _M_initialize_moneypunct(__c_locale __cloc = NULL, + const char* __name = NULL); }; template<typename _CharT, bool _Intl> @@ -1438,22 +1457,36 @@ namespace std template<typename _CharT, bool _Intl> const bool moneypunct<_CharT, _Intl>::intl; + template<> + moneypunct<char, true>::~moneypunct(); + + template<> + moneypunct<char, false>::~moneypunct(); + template<> void - moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct<char, true>::_M_initialize_moneypunct(__c_locale, const char*); template<> void - moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct<char, false>::_M_initialize_moneypunct(__c_locale, const char*); #ifdef _GLIBCPP_USE_WCHAR_T + template<> + moneypunct<wchar_t, true>::~moneypunct(); + + template<> + moneypunct<wchar_t, false>::~moneypunct(); + template<> void - moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale, + const char*); template<> void - moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale, + const char*); #endif template<typename _CharT, bool _Intl> @@ -1581,27 +1614,17 @@ namespace std // Underlying "C" library locale information saved from // initialization, needed by messages_byname as well. __c_locale _M_c_locale_messages; -#if 1 - // Only needed if glibc < 2.3 - const char* _M_name_messages; -#endif + char* _M_name_messages; public: static locale::id id; explicit - messages(size_t __refs = 0) - : locale::facet(__refs), _M_name_messages("C") - { _M_c_locale_messages = _S_clone_c_locale(_S_c_locale); } + messages(size_t __refs = 0); // Non-standard. explicit - messages(__c_locale __cloc, const char* __name, size_t __refs = 0) - : locale::facet(__refs) - { - _M_name_messages = __name; - _M_c_locale_messages = _S_clone_c_locale(__cloc); - } + messages(__c_locale __cloc, const char* __s, size_t __refs = 0); catalog open(const basic_string<char>& __s, const locale& __loc) const @@ -1621,8 +1644,7 @@ namespace std protected: virtual - ~messages() - { _S_destroy_c_locale(_M_c_locale_messages); } + ~messages(); virtual catalog do_open(const basic_string<char>&, const locale&) const; @@ -1690,8 +1712,11 @@ namespace std string messages<char>::do_get(catalog, int, int, const string&) const; - // Include host and configuration specific messages virtual functions. - #include <bits/messages_members.h> +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + wstring + messages<wchar_t>::do_get(catalog, int, int, const wstring&) const; +#endif template<typename _CharT> class messages_byname : public messages<_CharT> @@ -1701,13 +1726,7 @@ namespace std typedef basic_string<_CharT> string_type; explicit - messages_byname(const char* __s, size_t __refs = 0) - : messages<_CharT>(__refs) - { - _M_name_messages = __s; - _S_destroy_c_locale(_M_c_locale_messages); - _S_create_c_locale(_M_c_locale_messages, __s); - } + messages_byname(const char* __s, size_t __refs = 0); protected: virtual @@ -1715,6 +1734,9 @@ namespace std { } }; + // Include host and configuration specific messages functions. + #include <bits/messages_members.h> + // Subclause convenience interfaces, inlines. // NB: These are inline because, when used in a loop, some compilers diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 02ae96eeb51..1bf3d7ce796 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -41,9 +41,7 @@ #include <cmath> // For ceil #include <cctype> // For isspace #include <limits> // For numeric_limits -#include <memory> // For auto_ptr #include <bits/streambuf_iterator.h> -#include <vector> #include <typeinfo> // For bad_cast. namespace std @@ -72,21 +70,20 @@ namespace std const _Facet& use_facet(const locale& __loc) { - size_t __i = _Facet::id._M_index; - locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets; - const locale::facet* __fp = (*__facet)[__i]; - if (__fp == 0 || __i >= __facet->size()) + size_t __i = _Facet::id._M_id(); + locale::facet** __facets = __loc._M_impl->_M_facets; + if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) __throw_bad_cast(); - return static_cast<const _Facet&>(*__fp); + return static_cast<const _Facet&>(*__facets[__i]); } template<typename _Facet> bool has_facet(const locale& __loc) throw() { - size_t __i = _Facet::id._M_index; - locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets; - return (__i < __facet->size() && (*__facet)[__i] != 0); + size_t __i = _Facet::id._M_id(); + locale::facet** __facets = __loc._M_impl->_M_facets; + return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } @@ -97,6 +94,7 @@ namespace std _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, string& __xtrc) const { + typedef char_traits<_CharT> __traits_type; const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); @@ -106,7 +104,8 @@ namespace std const char_type __minus = __ctype.widen('-'); int __pos = 0; char_type __c = *__beg; - if ((__c == __plus || __c == __minus) && __beg != __end) + if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) + && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; @@ -116,7 +115,7 @@ namespace std // Next, strip leading zeros. const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); bool __found_zero = false; - while (__c == __zero && __beg != __end) + while (__traits_type::eq(__c, __zero) && __beg != __end) { __c = *(++__beg); __found_zero = true; @@ -144,11 +143,10 @@ namespace std while (__beg != __end) { // Only look in digits. - typedef char_traits<_CharT> __traits_type; const char_type* __p = __traits_type::find(__watoms, 10, __c); // NB: strchr returns true for __c == 0x0 - if (__p && __c) + if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. ++__pos; @@ -156,7 +154,8 @@ namespace std ++__sep_pos; __c = *(++__beg); } - else if (__c == __sep && __check_grouping && !__found_dec) + else if (__traits_type::eq(__c, __sep) + && __check_grouping && !__found_dec) { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands separators. @@ -172,15 +171,20 @@ namespace std break; } } - else if (__c == __dec && !__found_dec) + else if (__traits_type::eq(__c, __dec) && !__found_dec) { - __found_grouping += static_cast<char>(__sep_pos); + // According to the standard, if no grouping chars are seen, + // no grouping check is applied. Therefore __found_grouping + // must be adjusted only if __dec comes after some __sep. + if (__found_grouping.size()) + __found_grouping += static_cast<char>(__sep_pos); ++__pos; __xtrc += '.'; __c = *(++__beg); __found_dec = true; } - else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E]) + else if ((__traits_type::eq(__c, __watoms[_M_e]) + || __traits_type::eq(__c, __watoms[_M_E])) && !__found_sci && __pos) { // Scientific notation. @@ -189,7 +193,8 @@ namespace std __c = *(++__beg); // Remove optional plus or minus sign, if they exist. - if (__c == __plus || __c == __minus) + if (__traits_type::eq(__c, __plus) + || __traits_type::eq(__c, __minus)) { ++__pos; __xtrc += __ctype.narrow(__c, char()); @@ -227,6 +232,7 @@ namespace std _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, string& __xtrc, int& __base) const { + typedef char_traits<_CharT> __traits_type; const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); @@ -240,10 +246,13 @@ namespace std else __base = 10; - // First check for sign. + // First check for sign. int __pos = 0; char_type __c = *__beg; - if ((__c == __ctype.widen('+') || __c == __ctype.widen('-')) + const char_type __plus = __ctype.widen('+'); + const char_type __minus = __ctype.widen('-'); + + if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); @@ -258,7 +267,7 @@ namespace std if (__base == 10) { bool __found_zero = false; - while (__c == __zero && __beg != __end) + while (__traits_type::eq(__c, __zero) && __beg != __end) { __c = *(++__beg); __found_zero = true; @@ -269,7 +278,9 @@ namespace std ++__pos; if (__basefield == 0) { - if ((__c == __x || __c == __X) && __beg != __end) + if ((__traits_type::eq(__c, __x) + || __traits_type::eq(__c, __X)) + && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; @@ -283,12 +294,13 @@ namespace std } else if (__base == 16) { - if (__c == __zero && __beg != __end) + if (__traits_type::eq(__c, __zero) && __beg != __end) { __xtrc += _S_atoms[_M_zero]; ++__pos; __c = *(++__beg); - if ((__c == __x || __c == __X) && __beg != __end) + if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) + && __beg != __end) { __xtrc += __ctype.narrow(__c, char()); ++__pos; @@ -310,16 +322,15 @@ namespace std __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); string __found_grouping; const string __grouping = __np.grouping(); - bool __check_grouping = __grouping.size() && __base == 10; + bool __check_grouping = __grouping.size(); int __sep_pos = 0; const char_type __sep = __np.thousands_sep(); while (__beg != __end) { - typedef char_traits<_CharT> __traits_type; const char_type* __p = __traits_type::find(__watoms, __len, __c); // NB: strchr returns true for __c == 0x0 - if (__p && __c) + if (__p && !__traits_type::eq(__c, char_type())) { // Try first for acceptable digit; record it if found. __xtrc += _S_atoms[__p - __watoms]; @@ -327,7 +338,7 @@ namespace std ++__sep_pos; __c = *(++__beg); } - else if (__c == __sep && __check_grouping) + else if (__traits_type::eq(__c, __sep) && __check_grouping) { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands separators. @@ -393,19 +404,25 @@ namespace std // Parse bool values as alphanumeric else { + typedef char_traits<_CharT> __traits_type; + typedef basic_string<_CharT> __string_type; + locale __loc = __io.getloc(); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - const char_type* __true = __np.truename().c_str(); - const char_type* __false = __np.falsename().c_str(); - - const size_t __truen = __np.truename().size() - 1; - const size_t __falsen = __np.falsename().size() - 1; + const __string_type __true = __np.truename(); + const __string_type __false = __np.falsename(); + const char_type* __trues = __true.c_str(); + const char_type* __falses = __false.c_str(); + const size_t __truen = __true.size() - 1; + const size_t __falsen = __false.size() - 1; for (size_t __n = 0; __beg != __end; ++__n) { char_type __c = *__beg++; - bool __testf = __n <= __falsen ? __c == __false[__n] : false; - bool __testt = __n <= __truen ? __c == __true[__n] : false; + bool __testf = __n <= __falsen + ? __traits_type::eq(__c, __falses[__n]) : false; + bool __testt = __n <= __truen + ? __traits_type::eq(__c, __trues[__n]) : false; if (!(__testf || __testt)) { __err |= ios_base::failbit; @@ -589,16 +606,15 @@ namespace std return __beg; } - - // The following code uses sprintf() to convert floating point - // values for insertion into a stream. An optimization would be to - // replace sprintf() with code that works directly on a wide buffer - // and then use __pad to do the padding. It would be good - // to replace sprintf() anyway to avoid accidental buffer overruns - // and to gain back the efficiency that C++ provides by knowing up - // front the type of the values to insert. This implementation - // follows the C++ standard fairly directly as outlined in 22.2.2.2 - // [lib.locale.num.put] + // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99 + // is not defined) to convert floating point values for insertion into a + // stream. An optimization would be to replace them with code that works + // directly on a wide buffer and then use __pad to do the padding. + // It would be good to replace them anyway to gain back the efficiency + // that C++ provides by knowing up front the type of the values to insert. + // Also, sprintf is dangerous since may lead to accidental buffer overruns. + // This implementation follows the C++ standard fairly directly as + // outlined in 22.2.2.2 [lib.locale.num.put] template<typename _CharT, typename _OutIter> template<typename _ValueT> _OutIter @@ -606,15 +622,50 @@ namespace std _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { - const int __max_digits = numeric_limits<_ValueT>::digits10; + // Note: digits10 is rounded down: we need to add 1 to ensure + // we get the full available precision. + // Then, in general, one more 1 needs to be added since, when the + // %{g,G} conversion specifiers are chosen inside _S_format_float, the + // precision field is "the maximum number of significant digits", *not* + // the "number of digits to appear after the decimal point", as happens + // for %{e,E,f,F} (C99, 7.19.6.1,4). + const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; streamsize __prec = __io.precision(); - // Protect against sprintf() buffer overflows. + if (__prec > static_cast<streamsize>(__max_digits)) __prec = static_cast<streamsize>(__max_digits); // Long enough for the max format spec. char __fbuf[16]; + // [22.2.2.2.2] Stage 1, numeric conversion to character. + int __len; +#ifdef _GLIBCPP_USE_C99 + // First try a buffer perhaps big enough (for sure sufficient for + // non-ios_base::fixed outputs) + int __cs_size = __max_digits * 3; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + + const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); + if (__fp) + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); + else + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); + + // If the buffer was not large enough, try again with the correct size. + if (__len >= __cs_size) + { + __cs_size = __len + 1; + __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + if (__fp) + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); + else + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale); + } +#else // Consider the possibility of long ios_base::fixed outputs const bool __fixed = __io.flags() & ios_base::fixed; const int __max_exp = numeric_limits<_ValueT>::max_exponent10; @@ -627,12 +678,11 @@ namespace std : __max_digits * 3; char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); - int __len; - // [22.2.2.2.2] Stage 1, numeric conversion to character. if (_S_format_float(__io, __fbuf, __mod, __prec)) - __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale, __prec); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); else - __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); +#endif return _M_widen_float(__s, __io, __fill, __cs, __len); } @@ -644,13 +694,30 @@ namespace std char __modl, _ValueT __v) const { // [22.2.2.2.2] Stage 1, numeric conversion to character. - // Leave room for "+/-," "0x," and commas. This size is - // arbitrary, but should work. - char __cs[64]; + // Long enough for the max format spec. char __fbuf[16]; _S_format_int(__io, __fbuf, __mod, __modl); - int __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale); +#ifdef _GLIBCPP_USE_C99 + // First try a buffer perhaps big enough. + int __cs_size = 64; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale); + // If the buffer was not large enough, try again with the correct size. + if (__len >= __cs_size) + { + __cs_size = __len + 1; + __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale); + } +#else + // Leave room for "+/-," "0x," and commas. This size is + // arbitrary, but should be largely sufficient. + char __cs[128]; + int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); +#endif return _M_widen_int(__s, __io, __fill, __cs, __len); } @@ -660,6 +727,7 @@ namespace std _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, int __len) const { + typedef char_traits<_CharT> __traits_type; // [22.2.2.2.2] Stage 2, convert to char_type, using correct // numpunct.decimal_point() values for '.' and adding grouping. const locale __loc = __io.getloc(); @@ -675,7 +743,7 @@ namespace std // Replace decimal point. const _CharT* __p; const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.'))) + if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) __ws[__p - __ws] = __np.decimal_point(); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS @@ -696,7 +764,7 @@ namespace std // Tack on decimal part. if (__p) { - char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __traits_type::copy(__p2, __p, __len - __declen); __newlen += __len - __declen; } @@ -726,18 +794,35 @@ namespace std * __len * 2)); __ctype.widen(__cs, __cs + __len, __ws); - // Add grouping, if necessary. + // Add grouping, if necessary. const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); const string __grouping = __np.grouping(); - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - bool __dec = __basefield != ios_base::oct - && __basefield != ios_base::hex; - if (__grouping.size() && __dec) + const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; + if (__grouping.size()) { + // By itself __add_grouping cannot deal correctly with __ws when + // ios::showbase is set and ios_base::oct || ios_base::hex. + // Therefore we take care "by hand" of the initial 0, 0x or 0X. + // However, remember that the latter do not occur if the number + // printed is '0' (__len == 1). + streamsize __off = 0; + if ((__io.flags() & ios_base::showbase) && __len > 1) + if (__basefield == ios_base::oct) + { + __off = 1; + *__ws2 = *__ws; + } + else if (__basefield == ios_base::hex) + { + __off = 2; + *__ws2 = *__ws; + *(__ws2 + 1) = *(__ws + 1); + } _CharT* __p; - __p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(), + __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), + __grouping.c_str(), __grouping.c_str() + __grouping.size(), - __ws, __ws + __len); + __ws + __off, __ws + __len); __len = __p - __ws2; // Switch strings. __ws = __ws2; @@ -753,13 +838,15 @@ namespace std _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, int __len) const { + typedef char_traits<_CharT> __traits_type; // [22.2.2.2.2] Stage 3. streamsize __w = __io.width(); _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); if (__w > static_cast<streamsize>(__len)) { - __pad(__io, __fill, __ws2, __ws, __w, __len, true); + __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, + __w, __len, true); __len = static_cast<int>(__w); // Switch strings. __ws = __ws2; @@ -782,25 +869,19 @@ namespace std if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; - __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv); + __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); } else { + typedef basic_string<_CharT> __string_type; locale __loc = __io.getloc(); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - const char_type* __ws; - int __len; + __string_type __name; if (__v) - { - __ws = __np.truename().c_str(); - __len = __np.truename().size(); - } + __name = __np.truename(); else - { - __ws = __np.falsename().c_str(); - __len = __np.falsename().size(); - } - __s = _M_insert(__s, __io, __fill, __ws, __len); + __name = __np.falsename(); + __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); } return __s; } @@ -809,14 +890,14 @@ namespace std _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); } + { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } template<typename _CharT, typename _OutIter> _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long __v) const - { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); } + { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } #ifdef _GLIBCPP_USE_LONG_LONG template<typename _CharT, typename _OutIter> @@ -837,7 +918,7 @@ namespace std _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const - { return _M_convert_float(__s, __io, __fill, char_type(), __v); } + { return _M_convert_float(__s, __io, __fill, char(), __v); } template<typename _CharT, typename _OutIter> _OutIter @@ -858,7 +939,7 @@ namespace std __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); try { - __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), + __s = _M_convert_int(__s, __io, __fill, 'u', char(), reinterpret_cast<unsigned long>(__v)); __io.flags(__flags); } @@ -881,7 +962,7 @@ namespace std __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); const int __n = numeric_limits<long double>::digits10; - char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n)); + char* __cs = static_cast<char*>(__builtin_alloca(__n)); const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); const _CharT* __wcs = __str.c_str(); @@ -943,15 +1024,16 @@ namespace std switch (__which) { case money_base::symbol: - if (__io.flags() & ios_base::showbase - || __i < 2 - || (__i == 2 && static_cast<part>(__p.field[3]) != money_base::none) - || __sign.size() > 1) + if (__io.flags() & ios_base::showbase + || __i < 2 || __sign.size() > 1 + || ((static_cast<part>(__p.field[3]) != money_base::none) + && __i == 2)) { - // According to 22.2.6.1.2.2, symbol is required if - // (__io.flags() & ios_base::showbase), otherwise is optional - // and consumed only if other characters are needed to complete - // the format. + // According to 22.2.6.1.2.2, symbol is required + // if (__io.flags() & ios_base::showbase), + // otherwise is optional and consumed only if + // other characters are needed to complete the + // format. const string_type __symbol = __intl ? __mpt.curr_symbol() : __mpf.curr_symbol(); size_type __len = __symbol.size(); @@ -962,7 +1044,8 @@ namespace std __c = *(++__beg); ++__j; } - // When (__io.flags() & ios_base::showbase) symbol is required. + // When (__io.flags() & ios_base::showbase) + // symbol is required. if (__j != __len && (__io.flags() & ios_base::showbase)) __testvalid = false; } @@ -1091,11 +1174,29 @@ namespace std long double __units) const { const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - const int __n = numeric_limits<long double>::digits10; - char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n)); - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); - int __len = __convert_from_v(__cs, "%.01Lf", __units, _S_c_locale); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); +#ifdef _GLIBCPP_USE_C99 + // First try a buffer perhaps big enough. + int __cs_size = 64; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, + _S_c_locale); + // If the buffer was not large enough, try again with the correct size. + if (__len >= __cs_size) + { + __cs_size = __len + 1; + __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, + _S_c_locale); + } +#else + // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, + // decimal digit, '\0'. + const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); +#endif + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); __ctype.widen(__cs, __cs + __len, __ws); string_type __digits(__ws); return this->do_put(__s, __intl, __io, __fill, __digits); @@ -1187,8 +1288,9 @@ namespace std : __mpf.thousands_sep(); const char* __gbeg = __grouping.c_str(); const char* __gend = __gbeg + __grouping.size(); - const int __n = numeric_limits<long double>::digits10 * 2; - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); + const int __n = (__end - __beg) * 2; + _CharT* __ws2 = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, __gend, __beg, __end); __value.insert(0, __ws2, __ws_end - __ws2); @@ -1513,7 +1615,7 @@ namespace std const _CharT** __names, size_t __indexlen, ios_base::iostate& __err) const { - typedef char_traits<char_type> __traits_type; + typedef char_traits<_CharT> __traits_type; int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); size_t __nmatches = 0; size_t __pos = 0; @@ -1531,7 +1633,7 @@ namespace std // Find smallest matching string. size_t __minlen = 10; for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) - __minlen = min(__minlen, + __minlen = min(__minlen, __traits_type::length(__names[__matches[__i2]])); if (__pos < __minlen && __beg != __end) @@ -1608,7 +1710,7 @@ namespace std do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, tm* __tm) const { - typedef char_traits<char_type> __traits_type; + typedef char_traits<_CharT> __traits_type; locale __loc = __io.getloc(); __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); const char_type* __days[7]; @@ -1651,7 +1753,7 @@ namespace std do_get_monthname(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, tm* __tm) const { - typedef char_traits<char_type> __traits_type; + typedef char_traits<_CharT> __traits_type; locale __loc = __io.getloc(); __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); const char_type* __months[12]; @@ -1776,7 +1878,8 @@ namespace std // NB: This size is arbitrary. Should this be a data member, // initialized at construction? const size_t __maxlen = 64; - char_type* __res = static_cast<char_type*>(__builtin_alloca(__maxlen)); + char_type* __res = + static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); // NB: In IEE 1003.1-200x, and perhaps other locale models, it // is possible that the format character will be longer than one @@ -1797,7 +1900,7 @@ namespace std __fmt[3] = char_type(); } - __tp._M_put_helper(__res, __maxlen, __fmt, __tm); + __tp._M_put(__res, __maxlen, __fmt, __tm); // Write resulting, fully-formatted string to output iterator. size_t __len = char_traits<char_type>::length(__res); @@ -1810,13 +1913,13 @@ namespace std // Generic version does nothing. template<typename _CharT> int - collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const + collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const { return 0; } // Generic version does nothing. template<typename _CharT> size_t - collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const + collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const { return 0; } template<typename _CharT> @@ -1827,7 +1930,7 @@ namespace std { const string_type __one(__lo1, __hi1); const string_type __two(__lo2, __hi2); - return _M_compare_helper(__one.c_str(), __two.c_str()); + return _M_compare(__one.c_str(), __two.c_str()); } template<typename _CharT> @@ -1835,16 +1938,17 @@ namespace std collate<_CharT>:: do_transform(const _CharT* __lo, const _CharT* __hi) const { - size_t __len = __hi - __lo; - _CharT* __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform_helper(__c, __lo, __len); + size_t __len = (__hi - __lo) * 2; + // First try a buffer perhaps big enough. + _CharT* __c = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); + size_t __res = _M_transform(__c, __lo, __len); + // If the buffer was not large enough, try again with the correct size. if (__res >= __len) { - // Try to increment size of translated string. - size_t __len2 = __len * 2; - _CharT* __c2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len2)); - __res = _M_transform_helper(__c2, __lo, __len); - // XXX Throw exception if still indeterminate? + __c = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); + _M_transform(__c, __lo, __res + 1); } return string_type(__c); } @@ -1870,20 +1974,12 @@ namespace std const __c_locale& __cloc, int __base = 10); // Convert numeric value of type _Tv to string and return length of string. + // If snprintf is available use it, otherwise fall back to the unsafe sprintf + // which, in general, can be dangerous and should be avoided. template<typename _Tv> int - __convert_from_v(char* __out, const char* __fmt, _Tv __v, - const __c_locale&, int __prec = -1) - { - int __ret; - const char* __old = setlocale(LC_ALL, "C"); - if (__prec >= 0) - __ret = sprintf(__out, __fmt, __prec, __v); - else - __ret = sprintf(__out, __fmt, __v); - setlocale(LC_ALL, __old); - return __ret; - } + __convert_from_v(char* __out, const int __size, const char* __fmt, + _Tv __v, const __c_locale&, int __prec = -1); // Construct correctly padded string, as per 22.2.2.2.2 // Assumes @@ -1893,22 +1989,31 @@ namespace std // internal-adjusted objects are padded according to the rules below // concerning 0[xX] and +-, otherwise, exactly as right-adjusted // ones are. + + // NB: Of the two parameters, _CharT can be deduced from the + // function arguments. The other (_Traits) has to be explicitly specified. template<typename _CharT, typename _Traits> - void - __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, - const streamsize __newlen, const streamsize __oldlen, - const bool __num) + struct __pad { - typedef _CharT char_type; - typedef _Traits traits_type; - typedef typename traits_type::int_type int_type; - - int_type __plen = static_cast<size_t>(__newlen - __oldlen); - char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen)); - traits_type::assign(__pads, __plen, __fill); + static void + _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, + const _CharT* __olds, const streamsize __newlen, + const streamsize __oldlen, const bool __num); + }; - char_type* __beg; - char_type* __end; + template<typename _CharT, typename _Traits> + void + __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, + _CharT* __news, const _CharT* __olds, + const streamsize __newlen, + const streamsize __oldlen, const bool __num) + { + size_t __plen = static_cast<size_t>(__newlen - __oldlen); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); + _Traits::assign(__pads, __plen, __fill); + + _CharT* __beg; + _CharT* __end; size_t __mod = 0; size_t __beglen; //either __plen or __oldlen ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; @@ -1916,7 +2021,7 @@ namespace std if (__adjust == ios_base::left) { // Padding last. - __beg = const_cast<char_type*>(__olds); + __beg = const_cast<_CharT*>(__olds); __beglen = __oldlen; __end = __pads; } @@ -1927,12 +2032,14 @@ namespace std // Who came up with these rules, anyway? Jeeze. locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - const char_type __minus = __ctype.widen('-'); - const char_type __plus = __ctype.widen('+'); - bool __testsign = __olds[0] == __minus || __olds[0] == __plus; - bool __testhex = __ctype.widen('0') == __olds[0] - && (__ctype.widen('x') == __olds[1] - || __ctype.widen('X') == __olds[1]); + const _CharT __minus = __ctype.widen('-'); + const _CharT __plus = __ctype.widen('+'); + bool __testsign = _Traits::eq(__olds[0], __minus) + || _Traits::eq(__olds[0], __plus); + + bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) + && (_Traits::eq(__ctype.widen('x'), __olds[1]) + || _Traits::eq(__ctype.widen('X'), __olds[1])); if (__testhex) { __news[0] = __olds[0]; @@ -1941,23 +2048,23 @@ namespace std __news += 2; __beg = __pads; __beglen = __plen; - __end = const_cast<char_type*>(__olds + __mod); + __end = const_cast<_CharT*>(__olds + __mod); } else if (__testsign) { - __news[0] = __olds[0] == __plus ? __plus : __minus; + _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; ++__mod; ++__news; __beg = __pads; __beglen = __plen; - __end = const_cast<char_type*>(__olds + __mod); + __end = const_cast<_CharT*>(__olds + __mod); } else { // Padding first. __beg = __pads; __beglen = __plen; - __end = const_cast<char_type*>(__olds); + __end = const_cast<_CharT*>(__olds); } } else @@ -1965,23 +2072,11 @@ namespace std // Padding first. __beg = __pads; __beglen = __plen; - __end = const_cast<char_type*>(__olds); + __end = const_cast<_CharT*>(__olds); } - traits_type::copy(__news, __beg, __beglen); - traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod); - } - - // NB: Can't have default argument on non-member template, and - // num_put doesn't have a _Traits template parameter, so this - // forwarding template adds in the default template argument. - template<typename _CharT> - void - __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, - const streamsize __newlen, const streamsize __oldlen, - const bool __num) - { - return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds, - __newlen, __oldlen, __num); + _Traits::copy(__news, __beg, __beglen); + _Traits::copy(__news + __beglen, __end, + __newlen - __beglen - __mod); } // Used by both numeric and monetary facets. @@ -2048,51 +2143,255 @@ namespace std extern template class moneypunct<char, true>; extern template class moneypunct_byname<char, false>; extern template class moneypunct_byname<char, true>; - extern template class money_get<char, istreambuf_iterator<char> >; - extern template class money_put<char, ostreambuf_iterator<char> >; + extern template class money_get<char>; + extern template class money_put<char>; + extern template class numpunct<char>; + extern template class numpunct_byname<char>; + extern template class num_get<char>; + extern template class num_put<char>; + extern template class __timepunct<char>; + extern template class time_put<char>; + extern template class time_put_byname<char>; + extern template class time_get<char>; + extern template class time_get_byname<char>; + extern template class messages<char>; + extern template class messages_byname<char>; + extern template class ctype_byname<char>; + extern template class codecvt_byname<char, char, mbstate_t>; + extern template class collate<char>; + extern template class collate_byname<char>; + + extern template + const codecvt<char, char, mbstate_t>& + use_facet<codecvt<char, char, mbstate_t> >(const locale&); + + extern template + const collate<char>& + use_facet<collate<char> >(const locale&); + + extern template + const numpunct<char>& + use_facet<numpunct<char> >(const locale&); + + extern template + const num_put<char>& + use_facet<num_put<char> >(const locale&); + + extern template + const num_get<char>& + use_facet<num_get<char> >(const locale&); + + extern template + const moneypunct<char, true>& + use_facet<moneypunct<char, true> >(const locale&); + + extern template + const moneypunct<char, false>& + use_facet<moneypunct<char, false> >(const locale&); + + extern template + const money_put<char>& + use_facet<money_put<char> >(const locale&); + + extern template + const money_get<char>& + use_facet<money_get<char> >(const locale&); + + extern template + const __timepunct<char>& + use_facet<__timepunct<char> >(const locale&); + + extern template + const time_put<char>& + use_facet<time_put<char> >(const locale&); + + extern template + const time_get<char>& + use_facet<time_get<char> >(const locale&); + + extern template + const messages<char>& + use_facet<messages<char> >(const locale&); + + extern template + bool + has_facet<ctype<char> >(const locale&); + + extern template + bool + has_facet<codecvt<char, char, mbstate_t> >(const locale&); + + extern template + bool + has_facet<collate<char> >(const locale&); + + extern template + bool + has_facet<numpunct<char> >(const locale&); + + extern template + bool + has_facet<num_put<char> >(const locale&); + + extern template + bool + has_facet<num_get<char> >(const locale&); + + extern template + bool + has_facet<moneypunct<char> >(const locale&); + + extern template + bool + has_facet<money_put<char> >(const locale&); + + extern template + bool + has_facet<money_get<char> >(const locale&); + + extern template + bool + has_facet<__timepunct<char> >(const locale&); + + extern template + bool + has_facet<time_put<char> >(const locale&); + + extern template + bool + has_facet<time_get<char> >(const locale&); + + extern template + bool + has_facet<messages<char> >(const locale&); + +#ifdef _GLIBCPP_USE_WCHAR_T extern template class moneypunct<wchar_t, false>; extern template class moneypunct<wchar_t, true>; extern template class moneypunct_byname<wchar_t, false>; extern template class moneypunct_byname<wchar_t, true>; - extern template class money_get<wchar_t, istreambuf_iterator<wchar_t> >; - extern template class money_put<wchar_t, ostreambuf_iterator<wchar_t> >; - extern template class numpunct<char>; - extern template class numpunct_byname<char>; - extern template class num_get<char, istreambuf_iterator<char> >; - extern template class num_put<char, ostreambuf_iterator<char> >; + extern template class money_get<wchar_t>; + extern template class money_put<wchar_t>; extern template class numpunct<wchar_t>; extern template class numpunct_byname<wchar_t>; - extern template class num_get<wchar_t, istreambuf_iterator<wchar_t> >; - extern template class num_put<wchar_t, ostreambuf_iterator<wchar_t> >; - extern template class __timepunct<char>; - extern template class time_put<char, ostreambuf_iterator<char> >; - extern template class time_put_byname<char, ostreambuf_iterator<char> >; - extern template class time_get<char, istreambuf_iterator<char> >; - extern template class time_get_byname<char, istreambuf_iterator<char> >; + extern template class num_get<wchar_t>; + extern template class num_put<wchar_t>; extern template class __timepunct<wchar_t>; - extern template class time_put<wchar_t, ostreambuf_iterator<wchar_t> >; - extern template class time_put_byname<wchar_t, ostreambuf_iterator<wchar_t> >; - extern template class time_get<wchar_t, istreambuf_iterator<wchar_t> >; - extern template class time_get_byname<wchar_t, istreambuf_iterator<wchar_t> >; - extern template class messages<char>; - extern template class messages_byname<char>; + extern template class time_put<wchar_t>; + extern template class time_put_byname<wchar_t>; + extern template class time_get<wchar_t>; + extern template class time_get_byname<wchar_t>; extern template class messages<wchar_t>; extern template class messages_byname<wchar_t>; - extern template class ctype_byname<char>; extern template class ctype_byname<wchar_t>; - extern template class codecvt_byname<char, char, mbstate_t>; extern template class codecvt_byname<wchar_t, char, mbstate_t>; - extern template class collate<char>; - extern template class collate_byname<char>; extern template class collate<wchar_t>; extern template class collate_byname<wchar_t>; -} // namespace std -#endif + extern template + const codecvt<wchar_t, char, mbstate_t>& + use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); + + extern template + const collate<wchar_t>& + use_facet<collate<wchar_t> >(const locale&); + + extern template + const numpunct<wchar_t>& + use_facet<numpunct<wchar_t> >(const locale&); + + extern template + const num_put<wchar_t>& + use_facet<num_put<wchar_t> >(const locale&); + + extern template + const num_get<wchar_t>& + use_facet<num_get<wchar_t> >(const locale&); + + extern template + const moneypunct<wchar_t, true>& + use_facet<moneypunct<wchar_t, true> >(const locale&); + + extern template + const moneypunct<wchar_t, false>& + use_facet<moneypunct<wchar_t, false> >(const locale&); + + extern template + const money_put<wchar_t>& + use_facet<money_put<wchar_t> >(const locale&); + + extern template + const money_get<wchar_t>& + use_facet<money_get<wchar_t> >(const locale&); + + extern template + const __timepunct<wchar_t>& + use_facet<__timepunct<wchar_t> >(const locale&); + + extern template + const time_put<wchar_t>& + use_facet<time_put<wchar_t> >(const locale&); + + extern template + const time_get<wchar_t>& + use_facet<time_get<wchar_t> >(const locale&); + + extern template + const messages<wchar_t>& + use_facet<messages<wchar_t> >(const locale&); + + extern template + bool + has_facet<ctype<wchar_t> >(const locale&); + + extern template + bool + has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); + + extern template + bool + has_facet<collate<wchar_t> >(const locale&); + + extern template + bool + has_facet<numpunct<wchar_t> >(const locale&); + + extern template + bool + has_facet<num_put<wchar_t> >(const locale&); + + extern template + bool + has_facet<num_get<wchar_t> >(const locale&); + + extern template + bool + has_facet<moneypunct<wchar_t> >(const locale&); + extern template + bool + has_facet<money_put<wchar_t> >(const locale&); + extern template + bool + has_facet<money_get<wchar_t> >(const locale&); + extern template + bool + has_facet<__timepunct<wchar_t> >(const locale&); + extern template + bool + has_facet<time_put<wchar_t> >(const locale&); + extern template + bool + has_facet<time_get<wchar_t> >(const locale&); + extern template + bool + has_facet<messages<wchar_t> >(const locale&); +#endif +} // namespace std +#endif diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h index 172adae2e04..dedc7645236 100644 --- a/libstdc++-v3/include/bits/localefwd.h +++ b/libstdc++-v3/include/bits/localefwd.h @@ -46,23 +46,13 @@ #include <bits/c++locale.h> // Defines __c_locale, config-specific includes #include <climits> // For CHAR_BIT #include <cctype> // For isspace, etc. -#include <string> // For string +#include <string> // For string. #include <bits/functexcept.h> - #include <bits/atomicity.h> namespace std { - // NB: Don't instantiate required wchar_t facets if no wchar_t support. -#ifdef _GLIBCPP_USE_WCHAR_T -# define _GLIBCPP_NUM_FACETS 28 -#else -# define _GLIBCPP_NUM_FACETS 14 -#endif - // 22.1.1 Locale - template<typename _Tp, typename _Alloc> - class vector; class locale; // 22.1.3 Convenience interfaces @@ -217,8 +207,8 @@ namespace std static const category time = 1L << 3; static const category monetary = 1L << 4; static const category messages = 1L << 5; - static const category all = (collate | ctype | monetary | - numeric | time | messages); + static const category all = (ctype | numeric | collate | + time | monetary | messages); // Construct/copy/destroy: locale() throw(); @@ -226,7 +216,7 @@ namespace std locale(const locale& __other) throw(); explicit - locale(const char* __std_name); + locale(const char* __s); locale(const locale& __base, const char* __s, category __cat); @@ -274,11 +264,29 @@ namespace std // The "C" reference locale static _Impl* _S_classic; - // Current global reference locale + // Current global locale static _Impl* _S_global; - static const size_t _S_num_categories = 6; - static const size_t _S_num_facets = _GLIBCPP_NUM_FACETS; + // Number of standard categories. For C++, these categories are + // collate, ctype, monetary, numeric, time, and messages. These + // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE, + // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE + // 1003.1-2001) specifies LC_MESSAGES. + static const size_t _S_categories_size = 6; + + // In addition to the standard categories, the underlying + // operating system is allowed to define extra LC_* + // macros. For GNU systems, the following are also valid: + // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT, + // and LC_IDENTIFICATION. + static const size_t _S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES; + + // Names of underlying locale categories. + // NB: locale::global() has to know how to modify all the + // underlying categories, not just the ones required by the C++ + // standard. + static const char* _S_categories[_S_categories_size + + _S_extra_categories_size]; explicit locale(_Impl*) throw(); @@ -302,9 +310,6 @@ namespace std class locale::_Impl { public: - // Types. - typedef vector<facet*, allocator<facet*> > __vec_facet; - // Friends. friend class locale; friend class locale::facet; @@ -320,8 +325,11 @@ namespace std private: // Data Members. _Atomic_word _M_references; - __vec_facet* _M_facets; - string _M_names[_S_num_categories]; + facet** _M_facets; + size_t _M_facets_size; + + char* _M_names[_S_categories_size + + _S_extra_categories_size]; static const locale::id* const _S_id_ctype[]; static const locale::id* const _S_id_numeric[]; static const locale::id* const _S_id_collate[]; @@ -347,15 +355,24 @@ namespace std } _Impl(const _Impl&, size_t); - _Impl(string __name, size_t); + _Impl(const char*, size_t); + _Impl(facet**, size_t, bool); + ~_Impl() throw(); + _Impl(const _Impl&); // Not defined. + + void + operator=(const _Impl&); // Not defined. + inline bool _M_check_same_name() { bool __ret = true; - for (size_t i = 0; i < _S_num_categories - 1; ++i) - __ret &= _M_names[i] == _M_names[i + 1]; + for (size_t __i = 0; + __ret && __i < _S_categories_size + _S_extra_categories_size - 1; + ++__i) + __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0); return __ret; } @@ -382,25 +399,33 @@ namespace std { _M_impl = new _Impl(*__other._M_impl, 1); _M_impl->_M_install_facet(&_Facet::id, __f); - for (size_t __i = 0; __i < _S_num_categories; ++__i) - _M_impl->_M_names[__i] = "*"; + for (size_t __i = 0; + __i < _S_categories_size + _S_extra_categories_size; ++__i) + { + delete [] _M_impl->_M_names[__i]; + char* __new = new char[2]; + strcpy(__new, "*"); + _M_impl->_M_names[__i] = __new; + } } // 22.1.1.1.2 Class locale::facet class locale::facet { + private: friend class locale; friend class locale::_Impl; - friend class __enc_traits; - private: _Atomic_word _M_references; protected: - // Contains data from the underlying "C" library for default "C" - // or "POSIX" locale. - static __c_locale _S_c_locale; - + // Contains data from the underlying "C" library for for the + // classic locale. + static __c_locale _S_c_locale; + + // String literal for the name of the classic locale. + static char _S_c_name[2]; + explicit facet(size_t __refs = 0) throw(); @@ -408,7 +433,8 @@ namespace std ~facet(); static void - _S_create_c_locale(__c_locale& __cloc, const char* __s); + _S_create_c_locale(__c_locale& __cloc, const char* __s, + __c_locale __old = 0); static __c_locale _S_clone_c_locale(__c_locale& __cloc); @@ -448,18 +474,26 @@ namespace std // function (even an inline) would be undefined. mutable size_t _M_index; - // Last id number assigned + // Last id number assigned. static _Atomic_word _S_highwater; void - operator=(const id&); // not defined + operator=(const id&); // Not defined. - id(const id&); // not defined + id(const id&); // Not defined. public: // NB: This class is always a static data member, and thus can be // counted on to be zero-initialized. id(); + + inline size_t + _M_id() const + { + if (!_M_index) + _M_index = 1 + __exchange_and_add(&_S_highwater, 1); + return _M_index - 1; + } }; template<typename _Facet> diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc index 91c1b124805..e42eca29192 100644 --- a/libstdc++-v3/include/bits/ostream.tcc +++ b/libstdc++-v3/include/bits/ostream.tcc @@ -119,19 +119,11 @@ namespace std basic_ostream<_CharT, _Traits>::operator<<(__streambuf_type* __sbin) { sentry __cerb(*this); - if (__cerb) + if (__cerb && __sbin) { try { - streamsize __xtrct = 0; - if (__sbin) - { - __streambuf_type* __sbout = this->rdbuf(); - __xtrct = __copy_streambufs(*this, __sbin, __sbout); - } - else - this->setstate(ios_base::badbit); - if (!__xtrct) + if (!__copy_streambufs(*this, __sbin, this->rdbuf())) this->setstate(ios_base::failbit); } catch(exception& __fail) @@ -143,6 +135,8 @@ namespace std __throw_exception_again; } } + else if (!__sbin) + this->setstate(ios_base::badbit); return *this; } @@ -185,7 +179,7 @@ namespace std if (_M_check_facet(_M_fnumput)) { bool __b = false; - if (__fmt & ios_base::oct || __fmt & ios_base::hex) + if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) { unsigned long __l = static_cast<unsigned long>(__n); __b = _M_fnumput->put(*this, *this, __c, __l).failed(); @@ -248,7 +242,7 @@ namespace std if (_M_check_facet(_M_fnumput)) { bool __b = false; - if (__fmt & ios_base::oct || __fmt & ios_base::hex) + if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) { unsigned long long __l; __l = static_cast<unsigned long long>(__n); @@ -419,9 +413,7 @@ namespace std basic_ostream<_CharT, _Traits>::tellp() { pos_type __ret = pos_type(-1); - bool __testok = this->fail() != true; - - if (__testok) + if (!this->fail()) __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out); return __ret; } @@ -431,9 +423,7 @@ namespace std basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::seekp(pos_type __pos) { - bool __testok = this->fail() != true; - - if (__testok) + if (!this->fail()) { #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 136. seekp, seekg setting wrong streams? @@ -452,9 +442,7 @@ namespace std basic_ostream<_CharT, _Traits>:: seekp(off_type __off, ios_base::seekdir __d) { - bool __testok = this->fail() != true; - - if (__testok) + if (!this->fail()) { #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 136. seekp, seekg setting wrong streams? @@ -464,8 +452,8 @@ namespace std // 129. Need error indication from seekp() and seekg() if (__err == pos_type(off_type(-1))) this->setstate(ios_base::failbit); - } #endif + } return *this; } @@ -481,12 +469,13 @@ namespace std try { streamsize __w = __out.width(); - _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__w + 1))); __pads[0] = __c; streamsize __len = 1; if (__w > __len) { - __pad(__out, __out.fill(), __pads, &__c, __w, __len, false); + __pad<_CharT, _Traits>::_S_pad(__out, __out.fill(), __pads, + &__c, __w, __len, false); __len = __w; } __out.write(__pads, __len); @@ -521,7 +510,8 @@ namespace std streamsize __len = 1; if (__w > __len) { - __pad(__out, __out.fill(), __pads, &__c, __w, __len, false); + __pad<char, _Traits>::_S_pad(__out, __out.fill(), __pads, + &__c, __w, __len, false); __len = __w; } __out.write(__pads, __len); @@ -545,7 +535,7 @@ namespace std { typedef basic_ostream<_CharT, _Traits> __ostream_type; typename __ostream_type::sentry __cerb(__out); - if (__cerb) + if (__cerb && __s) { try { @@ -554,7 +544,8 @@ namespace std streamsize __len = static_cast<streamsize>(_Traits::length(__s)); if (__w > __len) { - __pad(__out, __out.fill(), __pads, __s, __w, __len, false); + __pad<_CharT, _Traits>::_S_pad(__out, __out.fill(), __pads, + __s, __w, __len, false); __s = __pads; __len = __w; } @@ -570,6 +561,8 @@ namespace std __throw_exception_again; } } + else if (!__s) + __out.setstate(ios_base::badbit); return __out; } @@ -581,14 +574,14 @@ namespace std #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 167. Improper use of traits_type::length() // Note that this is only in 'Review' status. - typedef char_traits<char> __ctraits_type; + typedef char_traits<char> __traits_type; #endif typename __ostream_type::sentry __cerb(__out); - if (__cerb) + if (__cerb && __s) { - size_t __clen = __ctraits_type::length(__s); + size_t __clen = __traits_type::length(__s); _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__clen + 1))); - for (size_t __i = 0; __i <= __clen; ++__i) + for (size_t __i = 0; __i < __clen; ++__i) __ws[__i] = __out.widen(__s[__i]); _CharT* __str = __ws; @@ -600,7 +593,8 @@ namespace std if (__w > __len) { - __pad(__out, __out.fill(), __pads, __ws, __w, __len, false); + __pad<_CharT, _Traits>::_S_pad(__out, __out.fill(), __pads, + __ws, __w, __len, false); __str = __pads; __len = __w; } @@ -616,6 +610,8 @@ namespace std __throw_exception_again; } } + else if (!__s) + __out.setstate(ios_base::badbit); return __out; } @@ -626,16 +622,18 @@ namespace std { typedef basic_ostream<char, _Traits> __ostream_type; typename __ostream_type::sentry __cerb(__out); - if (__cerb) + if (__cerb && __s) { try { streamsize __w = __out.width(); char* __pads = static_cast<char*>(__builtin_alloca(__w)); streamsize __len = static_cast<streamsize>(_Traits::length(__s)); + if (__w > __len) { - __pad(__out, __out.fill(), __pads, __s, __w, __len, false); + __pad<char, _Traits>::_S_pad(__out, __out.fill(), __pads, + __s, __w, __len, false); __s = __pads; __len = __w; } @@ -651,6 +649,8 @@ namespace std __throw_exception_again; } } + else if (!__s) + __out.setstate(ios_base::badbit); return __out; } @@ -673,7 +673,8 @@ namespace std #endif if (__w > __len) { - __pad(__out, __out.fill(), __pads, __s, __w, __len, false); + __pad<_CharT, _Traits>::_S_pad(__out, __out.fill(), __pads, __s, + __w, __len, false); __s = __pads; __len = __w; } @@ -699,6 +700,7 @@ namespace std extern template ostream& operator<<(ostream&, const unsigned char*); extern template ostream& operator<<(ostream&, const signed char*); +#ifdef _GLIBCPP_USE_WCHAR_T extern template class basic_ostream<wchar_t>; extern template wostream& endl(wostream&); extern template wostream& ends(wostream&); @@ -707,4 +709,5 @@ namespace std extern template wostream& operator<<(wostream&, char); extern template wostream& operator<<(wostream&, const wchar_t*); extern template wostream& operator<<(wostream&, const char*); +#endif } // namespace std diff --git a/libstdc++-v3/include/bits/slice_array.h b/libstdc++-v3/include/bits/slice_array.h index c8908f8bb53..cca3e63f0ae 100644 --- a/libstdc++-v3/include/bits/slice_array.h +++ b/libstdc++-v3/include/bits/slice_array.h @@ -120,7 +120,8 @@ namespace std inline slice_array<_Tp>& slice_array<_Tp>::operator=(const slice_array<_Tp>& __a) { - __valarray_copy(_M_array, _M_sz, _M_stride, __a._M_array, __a._M_stride); + __valarray_copy(__a._M_array, __a._M_sz, __a._M_stride, + _M_array, _M_stride); return *this; } diff --git a/libstdc++-v3/include/bits/sstream.tcc b/libstdc++-v3/include/bits/sstream.tcc index f83bb697dcc..606705c02e9 100644 --- a/libstdc++-v3/include/bits/sstream.tcc +++ b/libstdc++-v3/include/bits/sstream.tcc @@ -95,13 +95,13 @@ namespace std __len *= 2; if (__testwrite) - __ret = this->sputc(__c); + __ret = this->sputc(traits_type::to_char_type(__c)); else if (__len <= _M_string.max_size()) { // Force-allocate, re-sync. _M_string = this->str(); _M_string.reserve(__len); - _M_buf_size = static_cast<int_type>(__len); + _M_buf_size = __len; _M_really_sync(_M_in_cur - _M_in_beg, _M_out_cur - _M_out_beg); *_M_out_cur = traits_type::to_char_type(__c); @@ -121,11 +121,13 @@ namespace std seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) { pos_type __ret = pos_type(off_type(-1)); - bool __testin = __mode & ios_base::in && _M_mode & ios_base::in; - bool __testout = __mode & ios_base::out && _M_mode & ios_base::out; + bool __testin = (ios_base::in & _M_mode & __mode) != 0; + bool __testout = (ios_base::out & _M_mode & __mode) != 0; bool __testboth = __testin && __testout && __way != ios_base::cur; - - if (_M_buf_size && ((__testin != __testout) || __testboth)) + __testin &= !(__mode & ios_base::out); + __testout &= !(__mode & ios_base::in); + + if (_M_buf_size && (__testin || __testout || __testboth)) { char_type* __beg = _M_buf; char_type* __curi = NULL; @@ -133,12 +135,12 @@ namespace std char_type* __endi = NULL; char_type* __endo = NULL; - if (__testin) + if (__testin || __testboth) { __curi = this->gptr(); __endi = this->egptr(); } - if (__testout) + if (__testout || __testboth) { __curo = this->pptr(); __endo = this->epptr(); @@ -157,13 +159,13 @@ namespace std __newoffo = __endo - __beg; } - if (__testin + if ((__testin || __testboth) && __newoffi + __off >= 0 && __endi - __beg >= __newoffi + __off) { _M_in_cur = __beg + __newoffi + __off; __ret = pos_type(__newoffi); } - if (__testout + if ((__testout || __testboth) && __newoffo + __off >= 0 && __endo - __beg >= __newoffo + __off) { _M_out_cur_move(__newoffo + __off - (_M_out_cur - __beg)); @@ -179,33 +181,44 @@ namespace std seekpos(pos_type __sp, ios_base::openmode __mode) { pos_type __ret = pos_type(off_type(-1)); - off_type __pos = __sp._M_position(); - char_type* __beg = NULL; - char_type* __end = NULL; - bool __testin = __mode & ios_base::in && _M_mode & ios_base::in; - bool __testout = __mode & ios_base::out && _M_mode & ios_base::out; - if (__testin) - { - __beg = this->eback(); - __end = this->egptr(); - } - if (__testout) + if (_M_buf_size) { - __beg = this->pbase(); - __end = _M_buf + _M_buf_size; - } - - if (0 <= __pos && __pos <= __end - __beg) - { - // Need to set both of these if applicable - if (__testin) - _M_in_cur = _M_in_beg + __pos; - if (__testout) - _M_out_cur_move((__pos) - (_M_out_cur - __beg)); - __ret = pos_type(off_type(__pos)); + off_type __pos = __sp; // Use streamoff operator to do conversion. + char_type* __beg = NULL; + char_type* __end = NULL; + bool __testin = (ios_base::in & _M_mode & __mode) != 0; + bool __testout = (ios_base::out & _M_mode & __mode) != 0; + bool __testboth = __testin && __testout; + __testin &= !(__mode & ios_base::out); + __testout &= !(__mode & ios_base::in); + + // NB: Ordered. + bool __testposi = false; + bool __testposo = false; + if (__testin || __testboth) + { + __beg = this->eback(); + __end = this->egptr(); + if (0 <= __pos && __pos <= __end - __beg) + __testposi = true; + } + if (__testout || __testboth) + { + __beg = this->pbase(); + __end = _M_buf + _M_buf_size; + if (0 <= __pos && __pos <= __end - __beg) + __testposo = true; + } + if (__testposi || __testposo) + { + if (__testposi) + _M_in_cur = _M_in_beg + __pos; + if (__testposo) + _M_out_cur_move((__pos) - (_M_out_cur - __beg)); + __ret = pos_type(off_type(__pos)); + } } - return __ret; } @@ -213,13 +226,16 @@ namespace std // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. extern template class basic_stringbuf<char>; - extern template class basic_stringbuf<wchar_t>; extern template class basic_istringstream<char>; - extern template class basic_istringstream<wchar_t>; extern template class basic_ostringstream<char>; - extern template class basic_ostringstream<wchar_t>; extern template class basic_stringstream<char>; + +#ifdef _GLIBCPP_USE_WCHAR_T + extern template class basic_stringbuf<wchar_t>; + extern template class basic_istringstream<wchar_t>; + extern template class basic_ostringstream<wchar_t>; extern template class basic_stringstream<wchar_t>; +#endif } // namespace std #endif diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 1eee7b37b11..009c409b6fb 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -120,7 +120,7 @@ namespace std __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp) { // concept requirements - __glibcpp_function_requires(_BinaryFunctionConcept<_Compare, bool, _Tp, _Tp>) + __glibcpp_function_requires(_BinaryFunctionConcept<_Compare,bool,_Tp,_Tp>) if (__comp(__a, __b)) if (__comp(__b, __c)) return __b; @@ -144,8 +144,7 @@ namespace std * @return @p f. * * Applies the function object @p f to each element in the range - * @p [first,last). - * @p f must not modify its argument. + * @p [first,last). @p f must not modify the order of the sequence. * If @p f has a return value it is ignored. */ template<typename _InputIter, typename _Function> @@ -160,9 +159,9 @@ namespace std } /** - * @maint + * @if maint * This is an overload used by find() for the Input Iterator case. - * @endmaint + * @endif */ template<typename _InputIter, typename _Tp> inline _InputIter @@ -176,9 +175,9 @@ namespace std } /** - * @maint + * @if maint * This is an overload used by find_if() for the Input Iterator case. - * @endmaint + * @endif */ template<typename _InputIter, typename _Predicate> inline _InputIter @@ -192,9 +191,9 @@ namespace std } /** - * @maint + * @if maint * This is an overload used by find() for the RAI case. - * @endmaint + * @endif */ template<typename _RandomAccessIter, typename _Tp> _RandomAccessIter @@ -236,9 +235,9 @@ namespace std } /** - * @maint + * @if maint * This is an overload used by find_if() for the RAI case. - * @endmaint + * @endif */ template<typename _RandomAccessIter, typename _Predicate> _RandomAccessIter @@ -1088,10 +1087,10 @@ namespace std } /** - * @maint + * @if maint * This is an uglified unique_copy(_InputIter, _InputIter, _OutputIter) * overloaded for output iterators. - * @endmaint + * @endif */ template<typename _InputIter, typename _OutputIter> _OutputIter @@ -1111,10 +1110,10 @@ namespace std } /** - * @maint + * @if maint * This is an uglified unique_copy(_InputIter, _InputIter, _OutputIter) * overloaded for forward iterators. - * @endmaint + * @endif */ template<typename _InputIter, typename _ForwardIter> _ForwardIter @@ -1140,6 +1139,8 @@ namespace std * Copies each element in the range @p [first,last) to the range * beginning at @p result, except that only the first element is copied * from groups of consecutive elements that compare equal. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. */ template<typename _InputIter, typename _OutputIter> inline _OutputIter @@ -1160,11 +1161,11 @@ namespace std } /** - * @maint + * @if maint * This is an uglified * unique_copy(_InputIter, _InputIter, _OutputIter, _BinaryPredicate) * overloaded for output iterators. - * @endmaint + * @endif */ template<typename _InputIter, typename _OutputIter, typename _BinaryPredicate> _OutputIter @@ -1189,11 +1190,11 @@ namespace std } /** - * @maint + * @if maint * This is an uglified * unique_copy(_InputIter, _InputIter, _OutputIter, _BinaryPredicate) * overloaded for forward iterators. - * @endmaint + * @endif */ template<typename _InputIter, typename _ForwardIter, typename _BinaryPredicate> _ForwardIter @@ -1302,10 +1303,10 @@ __result, __binary_pred, _IterType()); } /** - * @maint + * @if maint * This is an uglified reverse(_BidirectionalIter, _BidirectionalIter) * overloaded for bidirectional iterators. - * @endmaint + * @endif */ template<typename _BidirectionalIter> void @@ -1320,10 +1321,10 @@ __result, __binary_pred, _IterType()); } /** - * @maint + * @if maint * This is an uglified reverse(_BidirectionalIter, _BidirectionalIter) * overloaded for bidirectional iterators. - * @endmaint + * @endif */ template<typename _RandomAccessIter> void @@ -1388,8 +1389,13 @@ __result, __binary_pred, _IterType()); return __result; } - /// This is a helper function for the rotate algorithm specialized on RAIs. + /** + * @if maint + * This is a helper function for the rotate algorithm specialized on RAIs. + * It returns the greatest common divisor of two integer values. + * @endif + */ template<typename _EuclideanRingElement> _EuclideanRingElement __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) @@ -1402,6 +1408,11 @@ __result, __binary_pred, _IterType()); return __m; } + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ template<typename _ForwardIter> void __rotate(_ForwardIter __first, @@ -1430,6 +1441,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ template<typename _BidirectionalIter> void __rotate(_BidirectionalIter __first, @@ -1458,6 +1474,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ template<typename _RandomAccessIter> void __rotate(_RandomAccessIter __first, @@ -1519,6 +1540,24 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Rotate the elements of a sequence. + * @param first A forward iterator. + * @param middle A forward iterator. + * @param last A forward iterator. + * @return Nothing. + * + * Rotates the elements of the range @p [first,last) by @p (middle-first) + * positions so that the element at @p middle is moved to @p first, the + * element at @p middle+1 is moved to @first+1 and so on for each element + * in the range @p [first,last). + * + * This effectively swaps the ranges @p [first,middle) and + * @p [middle,last). + * + * Performs @p *(first+(n+(last-middle))%(last-first))=*(first+n) for + * each @p n in the range @p [0,last-first). + */ template<typename _ForwardIter> inline void rotate(_ForwardIter __first, _ForwardIter __middle, _ForwardIter __last) @@ -1530,6 +1569,23 @@ __result, __binary_pred, _IterType()); __rotate(__first, __middle, __last, _IterType()); } + /** + * @brief Copy a sequence, rotating its elements. + * @param first A forward iterator. + * @param middle A forward iterator. + * @param last A forward iterator. + * @param result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements of the range @p [first,last) to the range + * beginning at @result, rotating the copied elements by @p (middle-first) + * positions so that the element at @p middle is moved to @p result, the + * element at @p middle+1 is moved to @result+1 and so on for each element + * in the range @p [first,last). + * + * Performs @p *(result+(n+(last-middle))%(last-first))=*(first+n) for + * each @p n in the range @p [0,last-first). + */ template<typename _ForwardIter, typename _OutputIter> _OutputIter rotate_copy(_ForwardIter __first, _ForwardIter __middle, @@ -1543,9 +1599,16 @@ __result, __binary_pred, _IterType()); return copy(__first, __middle, copy(__middle, __last, __result)); } - // Return a random number in the range [0, __n). This function encapsulates - // whether we're using rand (part of the standard C library) or lrand48 - // (not standard, but a much better choice whenever it's available). + + /** + * @if maint + * Return a random number in the range [0, __n). This function encapsulates + * whether we're using rand (part of the standard C library) or lrand48 + * (not standard, but a much better choice whenever it's available). + * + * XXX There is no corresponding encapsulation fn to seed the generator. + * @endif + */ template<typename _Distance> inline _Distance __random_number(_Distance __n) @@ -1557,8 +1620,17 @@ __result, __binary_pred, _IterType()); #endif } - /// 25.2.11 random_shuffle(). + /** + * @brief Randomly shuffle the elements of a sequence. + * @param first A forward iterator. + * @param last A forward iterator. + * @return Nothing. + * + * Reorder the elements in the range @p [first,last) using a random + * distribution, so that every possible ordering of the sequence is + * equally likely. + */ template<typename _RandomAccessIter> inline void random_shuffle(_RandomAccessIter __first, _RandomAccessIter __last) @@ -1572,6 +1644,19 @@ __result, __binary_pred, _IterType()); iter_swap(__i, __first + __random_number((__i - __first) + 1)); } + /** + * @brief Shuffle the elements of a sequence using a random number + * generator. + * @param first A forward iterator. + * @param last A forward iterator. + * @param rand The RNG functor or function. + * @return Nothing. + * + * Reorders the elements in the range @p [first,last) using @p rand to + * provide a random distribution. Calling @p rand(N) for a positive + * integer @p N should return a randomly chosen integer from the + * range [0,N). + */ template<typename _RandomAccessIter, typename _RandomNumberGenerator> void random_shuffle(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1586,8 +1671,12 @@ __result, __binary_pred, _IterType()); iter_swap(__i, __first + __rand((__i - __first) + 1)); } - // partition, stable_partition, and their auxiliary functions + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _ForwardIter, typename _Predicate> _ForwardIter __partition(_ForwardIter __first, _ForwardIter __last, @@ -1610,6 +1699,11 @@ __result, __binary_pred, _IterType()); return __first; } + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _BidirectionalIter, typename _Predicate> _BidirectionalIter __partition(_BidirectionalIter __first, _BidirectionalIter __last, @@ -1637,6 +1731,20 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence. + * @param first A forward iterator. + * @param last A forward iterator. + * @param pred A predicate functor. + * @return An iterator @p middle such that @p pred(i) is true for each + * iterator @p i in the range @p [first,middle) and false for each @p i + * in the range @p [middle,last). + * + * @p pred must not modify its operand. @p partition() does not preserve + * the relative ordering of elements in each group, use + * @p stable_partition() if this is needed. + */ template<typename _ForwardIter, typename _Predicate> inline _ForwardIter partition(_ForwardIter __first, _ForwardIter __last, @@ -1651,6 +1759,11 @@ __result, __binary_pred, _IterType()); } + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _ForwardIter, typename _Predicate, typename _Distance> _ForwardIter __inplace_stable_partition(_ForwardIter __first, _ForwardIter __last, @@ -1671,6 +1784,11 @@ __result, __binary_pred, _IterType()); return __begin; } + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _ForwardIter, typename _Pointer, typename _Predicate, typename _Distance> _ForwardIter @@ -1711,6 +1829,22 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence, preserving relative ordering. + * @param first A forward iterator. + * @param last A forward iterator. + * @param pred A predicate functor. + * @return An iterator @p middle such that @p pred(i) is true for each + * iterator @p i in the range @p [first,middle) and false for each @p i + * in the range @p [middle,last). + * + * Performs the same function as @p partition() with the additional + * guarantee that the relative ordering of elements in each group is + * preserved, so any two elements @p x and @p y in the range + * @p [first,last) such that @p pred(x)==pred(y) will have the same + * relative ordering after calling @p stable_partition(). + */ template<typename _ForwardIter, typename _Predicate> _ForwardIter stable_partition(_ForwardIter __first, _ForwardIter __last, @@ -1739,6 +1873,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _RandomAccessIter, typename _Tp> _RandomAccessIter __unguarded_partition(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1757,6 +1896,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function... + * @endif + */ template<typename _RandomAccessIter, typename _Tp, typename _Compare> _RandomAccessIter __unguarded_partition(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1775,10 +1919,20 @@ __result, __binary_pred, _IterType()); } } - extern const int __stl_threshold; - // sort() and its auxiliary functions. + /** + * @if maint + * @doctodo + * This controls some aspect of the sort routines. + * @endif + */ + enum { _M_threshold = 16 }; + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Tp> void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val) @@ -1793,6 +1947,11 @@ __result, __binary_pred, _IterType()); *__last = __val; } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Tp, typename _Compare> void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val, _Compare __comp) @@ -1807,6 +1966,11 @@ __result, __binary_pred, _IterType()); *__last = __val; } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter> void __insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) @@ -1825,6 +1989,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Compare> void __insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1844,6 +2013,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter> inline void __unguarded_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) @@ -1854,6 +2028,11 @@ __result, __binary_pred, _IterType()); __unguarded_linear_insert(__i, _ValueType(*__i)); } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Compare> inline void __unguarded_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1865,31 +2044,46 @@ __result, __binary_pred, _IterType()); __unguarded_linear_insert(__i, _ValueType(*__i), __comp); } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter> void __final_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) { - if (__last - __first > __stl_threshold) { - __insertion_sort(__first, __first + __stl_threshold); - __unguarded_insertion_sort(__first + __stl_threshold, __last); + if (__last - __first > _M_threshold) { + __insertion_sort(__first, __first + _M_threshold); + __unguarded_insertion_sort(__first + _M_threshold, __last); } else __insertion_sort(__first, __last); } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Compare> void __final_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, _Compare __comp) { - if (__last - __first > __stl_threshold) { - __insertion_sort(__first, __first + __stl_threshold, __comp); - __unguarded_insertion_sort(__first + __stl_threshold, __last, __comp); + if (__last - __first > _M_threshold) { + __insertion_sort(__first, __first + _M_threshold, __comp); + __unguarded_insertion_sort(__first + _M_threshold, __last, __comp); } else __insertion_sort(__first, __last, __comp); } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _Size> inline _Size __lg(_Size __n) @@ -1899,6 +2093,11 @@ __result, __binary_pred, _IterType()); return __k; } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Size> void __introsort_loop(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1906,7 +2105,7 @@ __result, __binary_pred, _IterType()); { typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; - while (__last - __first > __stl_threshold) { + while (__last - __first > _M_threshold) { if (__depth_limit == 0) { partial_sort(__first, __last, __last); return; @@ -1922,6 +2121,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ template<typename _RandomAccessIter, typename _Size, typename _Compare> void __introsort_loop(_RandomAccessIter __first, _RandomAccessIter __last, @@ -1929,7 +2133,7 @@ __result, __binary_pred, _IterType()); { typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; - while (__last - __first > __stl_threshold) { + while (__last - __first > _M_threshold) { if (__depth_limit == 0) { partial_sort(__first, __last, __last, __comp); return; @@ -1946,6 +2150,19 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Sort the elements of a sequence. + * @param first An iterator. + * @param last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [first,last) in ascending order, + * such that @p *(i+1)<*i is false for each iterator @p i in the range + * @p [first,last-1). + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ template<typename _RandomAccessIter> inline void sort(_RandomAccessIter __first, _RandomAccessIter __last) @@ -1963,6 +2180,20 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Sort the elements of a sequence using a predicate for comparison. + * @param first An iterator. + * @param last Another iterator. + * @param comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [first,last) in ascending order, + * such that @p comp(*(i+1),*i) is false for every iterator @p i in the + * range @p [first,last-1). + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ template<typename _RandomAccessIter, typename _Compare> inline void sort(_RandomAccessIter __first, _RandomAccessIter __last, _Compare __comp) @@ -1980,8 +2211,12 @@ __result, __binary_pred, _IterType()); } } - // stable_sort() and its auxiliary functions. + /** + * @if maint + * This is a helper function for the stable sorting routines. + * @endif + */ template<typename _RandomAccessIter> void __inplace_stable_sort(_RandomAccessIter __first, _RandomAccessIter __last) @@ -1998,6 +2233,11 @@ __result, __binary_pred, _IterType()); __last - __middle); } + /** + * @if maint + * This is a helper function for the stable sorting routines. + * @endif + */ template<typename _RandomAccessIter, typename _Compare> void __inplace_stable_sort(_RandomAccessIter __first, _RandomAccessIter __last, @@ -2060,7 +2300,7 @@ __result, __binary_pred, _IterType()); __comp); } - extern const int __stl_chunk_size; + enum { _M_chunk_size = 7 }; template<typename _RandomAccessIter, typename _Distance> void @@ -2096,7 +2336,7 @@ __result, __binary_pred, _IterType()); _Distance __len = __last - __first; _Pointer __buffer_last = __buffer + __len; - _Distance __step_size = __stl_chunk_size; + _Distance __step_size = _M_chunk_size; __chunk_insertion_sort(__first, __last, __step_size); while (__step_size < __len) { @@ -2117,7 +2357,7 @@ __result, __binary_pred, _IterType()); _Distance __len = __last - __first; _Pointer __buffer_last = __buffer + __len; - _Distance __step_size = __stl_chunk_size; + _Distance __step_size = _M_chunk_size; __chunk_insertion_sort(__first, __last, __step_size, __comp); while (__step_size < __len) { @@ -2171,6 +2411,22 @@ __result, __binary_pred, _IterType()); __comp); } + /** + * @brief Sort the elements of a sequence, preserving the relative order + * of equivalent elements. + * @param first An iterator. + * @param last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [first,last) in ascending order, + * such that @p *(i+1)<*i is false for each iterator @p i in the range + * @p [first,last-1). + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [first,last) such that + * @p x<y is false and @p y<x is false will have the same relative + * ordering after calling @p stable_sort(). + */ template<typename _RandomAccessIter> inline void stable_sort(_RandomAccessIter __first, _RandomAccessIter __last) @@ -2190,6 +2446,23 @@ __result, __binary_pred, _IterType()); __stable_sort_adaptive(__first, __last, buf.begin(), _DistanceType(buf.size())); } + /** + * @brief Sort the elements of a sequence using a predicate for comparison, + * preserving the relative order of equivalent elements. + * @param first An iterator. + * @param last Another iterator. + * @param comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [first,last) in ascending order, + * such that @p comp(*(i+1),*i) is false for each iterator @p i in the + * range @p [first,last-1). + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [first,last) such that + * @p comp(x,y) is false and @p comp(y,x) is false will have the same + * relative ordering after calling @p stable_sort(). + */ template<typename _RandomAccessIter, typename _Compare> inline void stable_sort(_RandomAccessIter __first, _RandomAccessIter __last, _Compare __comp) @@ -2211,6 +2484,21 @@ __result, __binary_pred, _IterType()); __comp); } + /** + * @brief Sort the smallest elements of a sequence. + * @param first An iterator. + * @param middle Another iterator. + * @param last Another iterator. + * @return Nothing. + * + * Sorts the smallest @p (middle-first) elements in the range + * @p [first,last) and moves them to the range @p [first,middle). The + * order of the remaining elements in the range @p [middle,last) is + * undefined. + * After the sort if @p i and @j are iterators in the range + * @p [first,middle) such that @i precedes @j and @k is an iterator in + * the range @p [middle,last) then @p *j<*i and @p *k<*i are both false. + */ template<typename _RandomAccessIter> void partial_sort(_RandomAccessIter __first, @@ -2231,6 +2519,24 @@ __result, __binary_pred, _IterType()); sort_heap(__first, __middle); } + /** + * @brief Sort the smallest elements of a sequence using a predicate + * for comparison. + * @param first An iterator. + * @param middle Another iterator. + * @param last Another iterator. + * @param comp A comparison functor. + * @return Nothing. + * + * Sorts the smallest @p (middle-first) elements in the range + * @p [first,last) and moves them to the range @p [first,middle). The + * order of the remaining elements in the range @p [middle,last) is + * undefined. + * After the sort if @p i and @j are iterators in the range + * @p [first,middle) such that @i precedes @j and @k is an iterator in + * the range @p [middle,last) then @p *comp(j,*i) and @p comp(*k,*i) + * are both false. + */ template<typename _RandomAccessIter, typename _Compare> void partial_sort(_RandomAccessIter __first, @@ -2253,6 +2559,23 @@ __result, __binary_pred, _IterType()); sort_heap(__first, __middle, __comp); } + /** + * @brief Copy the smallest elements of a sequence. + * @param first An iterator. + * @param last Another iterator. + * @param result_first A random-access iterator. + * @param result_last Another random-access iterator. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [first,last) + * to the range beginning at @p result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (last-first) and + * @p (result_last-result_first). + * After the sort if @p i and @j are iterators in the range + * @p [result_first,result_first+N) such that @i precedes @j then + * @p *j<*i is false. + * The value returned is @p result_first+N. + */ template<typename _InputIter, typename _RandomAccessIter> _RandomAccessIter partial_sort_copy(_InputIter __first, _InputIter __last, @@ -2288,6 +2611,25 @@ __result, __binary_pred, _IterType()); return __result_real_last; } + /** + * @brief Copy the smallest elements of a sequence using a predicate for + * comparison. + * @param first An input iterator. + * @param last Another input iterator. + * @param result_first A random-access iterator. + * @param result_last Another random-access iterator. + * @param comp A comparison functor. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [first,last) + * to the range beginning at @p result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (last-first) and + * @p (result_last-result_first). + * After the sort if @p i and @j are iterators in the range + * @p [result_first,result_first+N) such that @i precedes @j then + * @p comp(*j,*i) is false. + * The value returned is @p result_first+N. + */ template<typename _InputIter, typename _RandomAccessIter, typename _Compare> _RandomAccessIter partial_sort_copy(_InputIter __first, _InputIter __last, @@ -2326,6 +2668,21 @@ __result, __binary_pred, _IterType()); return __result_real_last; } + /** + * @brief Sort a sequence just enough to find a particular position. + * @param first An iterator. + * @param nth Another iterator. + * @param last Another iterator. + * @return Nothing. + * + * Rearranges the elements in the range @p [first,last) so that @p *nth + * is the same element that would have been in that position had the + * whole sequence been sorted. + * whole sequence been sorted. The elements either side of @p *nth are + * not completely sorted, but for any iterator @i in the range + * @p [first,nth) and any iterator @j in the range @p [nth,last) it + * holds that @p *j<*i is false. + */ template<typename _RandomAccessIter> void nth_element(_RandomAccessIter __first, @@ -2352,6 +2709,22 @@ __result, __binary_pred, _IterType()); __insertion_sort(__first, __last); } + /** + * @brief Sort a sequence just enough to find a particular position + * using a predicate for comparison. + * @param first An iterator. + * @param nth Another iterator. + * @param last Another iterator. + * @param comp A comparison functor. + * @return Nothing. + * + * Rearranges the elements in the range @p [first,last) so that @p *nth + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of @p *nth are + * not completely sorted, but for any iterator @i in the range + * @p [first,nth) and any iterator @j in the range @p [nth,last) it + * holds that @p comp(*j,*i) is false. + */ template<typename _RandomAccessIter, typename _Compare> void nth_element(_RandomAccessIter __first, @@ -2383,8 +2756,15 @@ __result, __binary_pred, _IterType()); } - // Binary search (lower_bound, upper_bound, equal_range, binary_search). - + /** + * @brief Finds the first position in which @a val could be inserted + * without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @return An iterator pointing to the first element "not less than" @a val. + * @ingroup binarysearch + */ template<typename _ForwardIter, typename _Tp> _ForwardIter lower_bound(_ForwardIter __first, _ForwardIter __last, const _Tp& __val) @@ -2420,6 +2800,19 @@ __result, __binary_pred, _IterType()); return __first; } + /** + * @brief Finds the first position in which @a val could be inserted + * without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @param comp A functor to use for comparisons. + * @return An iterator pointing to the first element "not less than" @a val. + * @ingroup binarysearch + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ template<typename _ForwardIter, typename _Tp, typename _Compare> _ForwardIter lower_bound(_ForwardIter __first, _ForwardIter __last, @@ -2451,6 +2844,15 @@ __result, __binary_pred, _IterType()); return __first; } + /** + * @brief Finds the last position in which @a val could be inserted + * without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @return An iterator pointing to the first element greater than @a val. + * @ingroup binarysearch + */ template<typename _ForwardIter, typename _Tp> _ForwardIter upper_bound(_ForwardIter __first, _ForwardIter __last, const _Tp& __val) @@ -2483,6 +2885,19 @@ __result, __binary_pred, _IterType()); return __first; } + /** + * @brief Finds the last position in which @a val could be inserted + * without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @param comp A functor to use for comparisons. + * @return An iterator pointing to the first element greater than @a val. + * @ingroup binarysearch + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ template<typename _ForwardIter, typename _Tp, typename _Compare> _ForwardIter upper_bound(_ForwardIter __first, _ForwardIter __last, @@ -2514,6 +2929,22 @@ __result, __binary_pred, _IterType()); return __first; } + /** + * @brief Finds the largest subrange in which @a val could be inserted + * at any place in it without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @return An pair of iterators defining the subrange. + * @ingroup binarysearch + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(first, last, val), + * upper_bound(first, last, val)) + * @endcode + * but does not actually call those functions. + */ template<typename _ForwardIter, typename _Tp> pair<_ForwardIter, _ForwardIter> equal_range(_ForwardIter __first, _ForwardIter __last, const _Tp& __val) @@ -2552,6 +2983,23 @@ __result, __binary_pred, _IterType()); return pair<_ForwardIter, _ForwardIter>(__first, __first); } + /** + * @brief Finds the largest subrange in which @a val could be inserted + * at any place in it without changing the ordering. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @param comp A functor to use for comparisons. + * @return An pair of iterators defining the subrange. + * @ingroup binarysearch + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(first, last, val, comp), + * upper_bound(first, last, val, comp)) + * @endcode + * but does not actually call those functions. + */ template<typename _ForwardIter, typename _Tp, typename _Compare> pair<_ForwardIter, _ForwardIter> equal_range(_ForwardIter __first, _ForwardIter __last, const _Tp& __val, @@ -2590,6 +3038,17 @@ __result, __binary_pred, _IterType()); return pair<_ForwardIter, _ForwardIter>(__first, __first); } + /** + * @brief Determines whether an element exists in a range. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @return True if @a val (or its equivelent) is in [@a first,@a last ]. + * @ingroup binarysearch + * + * Note that this does not actually return an iterator to @a val. For + * that, use std::find or a container's specialized find member functions. + */ template<typename _ForwardIter, typename _Tp> bool binary_search(_ForwardIter __first, _ForwardIter __last, @@ -2606,6 +3065,21 @@ __result, __binary_pred, _IterType()); return __i != __last && !(__val < *__i); } + /** + * @brief Determines whether an element exists in a range. + * @param first An iterator. + * @param last Another iterator. + * @param val The search term. + * @param comp A functor to use for comparisons. + * @return True if @a val (or its equivelent) is in [@a first,@a last ]. + * @ingroup binarysearch + * + * Note that this does not actually return an iterator to @a val. For + * that, use std::find or a container's specialized find member functions. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ template<typename _ForwardIter, typename _Tp, typename _Compare> bool binary_search(_ForwardIter __first, _ForwardIter __last, @@ -2622,8 +3096,22 @@ __result, __binary_pred, _IterType()); return __i != __last && !__comp(__val, *__i); } - // merge, with and without an explicitly supplied comparison function. - + /** + * @brief Merges two sorted ranges. + * @param first1 An iterator. + * @param first2 Another iterator. + * @param last1 Another iterator. + * @param last2 Another iterator. + * @param result An iterator pointing to the end of the merged range. + * @return An iterator pointing to the first element "not less than" @a val. + * + * Merges the ranges [first1,last1) and [first2,last2) into the sorted range + * [result, result + (last1-first1) + (last2-first2)). Both input ranges + * must be sorted, and the output range must not overlap with either of + * the input ranges. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + */ template<typename _InputIter1, typename _InputIter2, typename _OutputIter> _OutputIter merge(_InputIter1 __first1, _InputIter1 __last1, @@ -2655,6 +3143,26 @@ __result, __binary_pred, _IterType()); return copy(__first2, __last2, copy(__first1, __last1, __result)); } + /** + * @brief Merges two sorted ranges. + * @param first1 An iterator. + * @param first2 Another iterator. + * @param last1 Another iterator. + * @param last2 Another iterator. + * @param result An iterator pointing to the end of the merged range. + * @param comp A functor to use for comparisons. + * @return An iterator pointing to the first element "not less than" @a val. + * + * Merges the ranges [first1,last1) and [first2,last2) into the sorted range + * [result, result + (last1-first1) + (last2-first2)). Both input ranges + * must be sorted, and the output range must not overlap with either of + * the input ranges. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ template<typename _InputIter1, typename _InputIter2, typename _OutputIter, typename _Compare> _OutputIter @@ -2688,8 +3196,11 @@ __result, __binary_pred, _IterType()); return copy(__first2, __last2, copy(__first1, __last1, __result)); } - // inplace_merge and its auxiliary functions. - + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter, typename _Distance> void __merge_without_buffer(_BidirectionalIter __first, @@ -2729,6 +3240,11 @@ __result, __binary_pred, _IterType()); __len1 - __len11, __len2 - __len22); } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter, typename _Distance, typename _Compare> void __merge_without_buffer(_BidirectionalIter __first, @@ -2769,6 +3285,11 @@ __result, __binary_pred, _IterType()); __len1 - __len11, __len2 - __len22, __comp); } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter1, typename _BidirectionalIter2, typename _Distance> _BidirectionalIter1 @@ -2797,6 +3318,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter1, typename _BidirectionalIter2, typename _BidirectionalIter3> _BidirectionalIter3 @@ -2826,6 +3352,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter1, typename _BidirectionalIter2, typename _BidirectionalIter3, typename _Compare> _BidirectionalIter3 @@ -2856,6 +3387,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter, typename _Distance, typename _Pointer> void __merge_adaptive(_BidirectionalIter __first, @@ -2900,6 +3436,11 @@ __result, __binary_pred, _IterType()); } } + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ template<typename _BidirectionalIter, typename _Distance, typename _Pointer, typename _Compare> void @@ -2947,6 +3488,23 @@ __result, __binary_pred, _IterType()); } } + /** + * @brief Merges two sorted ranges in place. + * @param first An iterator. + * @param middle Another iterator. + * @param last Another iterator. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [first,middle) and + * [middle,last), and puts the result in [first,last). The output will + * be sorted. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * If enough additional memory is available, this takes (last-first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(first,last). + */ template<typename _BidirectionalIter> void inplace_merge(_BidirectionalIter __first, @@ -2977,6 +3535,27 @@ __result, __binary_pred, _IterType()); __buf.begin(), _DistanceType(__buf.size())); } + /** + * @brief Merges two sorted ranges in place. + * @param first An iterator. + * @param middle Another iterator. + * @param last Another iterator. + * @param comp A functor to use for comparisons. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [first,middle) and + * [middle,last), and puts the result in [first,last). The output will + * be sorted. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * If enough additional memory is available, this takes (last-first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(first,last). + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ template<typename _BidirectionalIter, typename _Compare> void inplace_merge(_BidirectionalIter __first, diff --git a/libstdc++-v3/include/bits/stl_alloc.h b/libstdc++-v3/include/bits/stl_alloc.h index 7a4d9e9e4a6..238986d7eeb 100644 --- a/libstdc++-v3/include/bits/stl_alloc.h +++ b/libstdc++-v3/include/bits/stl_alloc.h @@ -50,7 +50,7 @@ /** * @defgroup Allocators Memory Allocators - * @maint + * @if maint * stl_alloc.h implements some node allocators. These are NOT the same as * allocators in the C++ standard, nor in the original H-P STL. They do not * encapsulate different pointer types; we assume that there is only one @@ -72,7 +72,11 @@ * * "SGI" allocators may be wrapped in __allocator to convert the interface * into a "standard" one. - * @endmaint + * @endif + * + * @note The @c reallocate member functions have been deprecated for 3.2 + * and will be removed in 3.4. You must define @c _GLIBCPP_DEPRECATED + * to make this visible in 3.2; see c++config.h. * * The canonical description of these classes is in docs/html/ext/howto.html * or online at http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3 @@ -85,157 +89,172 @@ #include <bits/functexcept.h> // For __throw_bad_alloc #include <bits/stl_threads.h> +#include <bits/atomicity.h> + namespace std { /** - * @maint + * @if maint * A new-based allocator, as required by the standard. Allocation and * deallocation forward to global new and delete. "SGI" style, minus * reallocate(). - * @endmaint + * @endif * (See @link Allocators allocators info @endlink for more.) - */ - class __new_alloc + */ + class __new_alloc { public: - static void* + static void* allocate(size_t __n) { return ::operator new(__n); } - - static void + + static void deallocate(void* __p, size_t) { ::operator delete(__p); } }; - + /** - * @maint + * @if maint * A malloc-based allocator. Typically slower than the * __default_alloc_template (below). Typically thread-safe and more * storage efficient. The template argument is unused and is only present * to permit multiple instantiations (but see __default_alloc_template * for caveats). "SGI" style, plus __set_malloc_handler for OOM conditions. - * @endmaint + * @endif * (See @link Allocators allocators info @endlink for more.) - */ - template <int __inst> - class __malloc_alloc_template + */ + template<int __inst> + class __malloc_alloc_template { private: static void* _S_oom_malloc(size_t); + + // _GLIBCPP_DEPRECATED static void* _S_oom_realloc(void*, size_t); + static void (* __malloc_alloc_oom_handler)(); - + public: - static void* + static void* allocate(size_t __n) { - void* __result = malloc(__n); - if (0 == __result) __result = _S_oom_malloc(__n); - return __result; + void* __result = malloc(__n); + if (__builtin_expect(__result == 0, 0)) + __result = _S_oom_malloc(__n); + return __result; } - static void + static void deallocate(void* __p, size_t /* __n */) { free(__p); } - static void* + // _GLIBCPP_DEPRECATED + static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz) { - void* __result = realloc(__p, __new_sz); - if (0 == __result) __result = _S_oom_realloc(__p, __new_sz); - return __result; + void* __result = realloc(__p, __new_sz); + if (__builtin_expect(__result == 0, 0)) + __result = _S_oom_realloc(__p, __new_sz); + return __result; } - + static void (* __set_malloc_handler(void (*__f)()))() { - void (* __old)() = __malloc_alloc_oom_handler; - __malloc_alloc_oom_handler = __f; - return(__old); + void (* __old)() = __malloc_alloc_oom_handler; + __malloc_alloc_oom_handler = __f; + return __old; } }; // malloc_alloc out-of-memory handling - template <int __inst> + template<int __inst> void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0; - template <int __inst> + template<int __inst> void* - __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n) + __malloc_alloc_template<__inst>:: + _S_oom_malloc(size_t __n) { void (* __my_malloc_handler)(); void* __result; - - for (;;) - { - __my_malloc_handler = __malloc_alloc_oom_handler; - if (0 == __my_malloc_handler) - std::__throw_bad_alloc(); - (*__my_malloc_handler)(); - __result = malloc(__n); - if (__result) - return(__result); - } + + for (;;) + { + __my_malloc_handler = __malloc_alloc_oom_handler; + if (__builtin_expect(__my_malloc_handler == 0, 0)) + __throw_bad_alloc(); + (*__my_malloc_handler)(); + __result = malloc(__n); + if (__result) + return __result; + } } - - template <int __inst> - void* - __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n) - { + + // _GLIBCPP_DEPRECATED + template<int __inst> + void* + __malloc_alloc_template<__inst>:: + _S_oom_realloc(void* __p, size_t __n) + { void (* __my_malloc_handler)(); void* __result; - - for (;;) - { - __my_malloc_handler = __malloc_alloc_oom_handler; - if (0 == __my_malloc_handler) - std::__throw_bad_alloc(); - (*__my_malloc_handler)(); - __result = realloc(__p, __n); - if (__result) - return(__result); - } - } + for (;;) + { + __my_malloc_handler = __malloc_alloc_oom_handler; + if (__builtin_expect(__my_malloc_handler == 0, 0)) + __throw_bad_alloc(); + (*__my_malloc_handler)(); + __result = realloc(__p, __n); + if (__result) + return __result; + } + } -// Determines the underlying allocator choice for the node allocator. -#ifdef __USE_MALLOC - typedef __malloc_alloc_template<0> __mem_interface; -#else + // Should not be referenced within the library anymore. typedef __new_alloc __mem_interface; -#endif - /** - * @maint + * @if maint * This is used primarily (only?) in _Alloc_traits and other places to - * help provide the _Alloc_type typedef. + * help provide the _Alloc_type typedef. All it does is forward the + * requests after some minimal checking. * * This is neither "standard"-conforming nor "SGI". The _Alloc parameter * must be "SGI" style. - * @endmaint + * @endif * (See @link Allocators allocators info @endlink for more.) - */ - template<class _Tp, class _Alloc> - class __simple_alloc - { - public: - static _Tp* allocate(size_t __n) - { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); } - - static _Tp* allocate() - { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); } - - static void deallocate(_Tp* __p, size_t __n) - { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); } - - static void deallocate(_Tp* __p) - { _Alloc::deallocate(__p, sizeof (_Tp)); } - }; + */ + template<typename _Tp, typename _Alloc> + class __simple_alloc + { + public: + static _Tp* + allocate(size_t __n) + { + _Tp* __ret = 0; + if (__n) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + return __ret; + } + + static _Tp* + allocate() + { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); } + + static void + deallocate(_Tp* __p, size_t __n) + { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); } + + static void + deallocate(_Tp* __p) + { _Alloc::deallocate(__p, sizeof (_Tp)); } + }; /** - * @maint + * @if maint * An adaptor for an underlying allocator (_Alloc) to check the size * arguments for debugging. Errors are reported using assert; these * checks can be disabled via NDEBUG, but the space penalty is still @@ -245,275 +264,292 @@ namespace std * "There is some evidence that this can confuse Purify." - SGI comment * * This adaptor is "SGI" style. The _Alloc parameter must also be "SGI". - * @endmaint + * @endif * (See @link Allocators allocators info @endlink for more.) - */ - template <class _Alloc> - class __debug_alloc - { - private: - enum {_S_extra = 8}; // Size of space used to store size. Note that this - // must be large enough to preserve alignment. - - public: - - static void* allocate(size_t __n) + */ + template<typename _Alloc> + class __debug_alloc { - char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra); - *(size_t*)__result = __n; - return __result + (int) _S_extra; - } - - static void deallocate(void* __p, size_t __n) - { - char* __real_p = (char*)__p - (int) _S_extra; - assert(*(size_t*)__real_p == __n); - _Alloc::deallocate(__real_p, __n + (int) _S_extra); - } - - static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz) + private: + // Size of space used to store size. Note that this must be + // large enough to preserve alignment. + enum {_S_extra = 8}; + + public: + static void* + allocate(size_t __n) + { + char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra); + *(size_t*)__result = __n; + return __result + (int) _S_extra; + } + + static void + deallocate(void* __p, size_t __n) + { + char* __real_p = (char*)__p - (int) _S_extra; + assert(*(size_t*)__real_p == __n); + _Alloc::deallocate(__real_p, __n + (int) _S_extra); + } + + // _GLIBCPP_DEPRECATED + static void* + reallocate(void* __p, size_t __old_sz, size_t __new_sz) + { + char* __real_p = (char*)__p - (int) _S_extra; + assert(*(size_t*)__real_p == __old_sz); + char* __result = (char*) _Alloc::reallocate(__real_p, + __old_sz + (int) _S_extra, + __new_sz + (int) _S_extra); + *(size_t*)__result = __new_sz; + return __result + (int) _S_extra; + } + }; + + + /** + * @if maint + * Default node allocator. "SGI" style. Uses various allocators to + * fulfill underlying requests (and makes as few requests as possible + * when in default high-speed pool mode). + * + * Important implementation properties: + * 0. If globally mandated, then allocate objects from __new_alloc + * 1. If the clients request an object of size > _MAX_BYTES, the resulting + * object will be obtained directly from __new_alloc + * 2. In all other cases, we allocate an object of size exactly + * _S_round_up(requested_size). Thus the client has enough size + * information that we can return the object to the proper free list + * without permanently losing part of the object. + * + * The first template parameter specifies whether more than one thread may + * use this allocator. It is safe to allocate an object from one instance + * of a default_alloc and deallocate it with another one. This effectively + * transfers its ownership to the second one. This may have undesirable + * effects on reference locality. + * + * The second parameter is unused and serves only to allow the creation of + * multiple default_alloc instances. Note that containers built on different + * allocator instances have different types, limiting the utility of this + * approach. If you do not wish to share the free lists with the main + * default_alloc instance, instantiate this with a non-zero __inst. + * + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template<bool __threads, int __inst> + class __default_alloc_template { - char* __real_p = (char*)__p - (int) _S_extra; - assert(*(size_t*)__real_p == __old_sz); - char* __result = (char*) - _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra, - __new_sz + (int) _S_extra); - *(size_t*)__result = __new_sz; - return __result + (int) _S_extra; - } - }; + private: + enum {_ALIGN = 8}; + enum {_MAX_BYTES = 128}; + enum {_NFREELISTS = _MAX_BYTES / _ALIGN}; + union _Obj + { + union _Obj* _M_free_list_link; + char _M_client_data[1]; // The client sees this. + }; -#ifdef __USE_MALLOC + static _Obj* volatile _S_free_list[_NFREELISTS]; -typedef __mem_interface __alloc; -typedef __mem_interface __single_client_alloc; + // Chunk allocation state. + static char* _S_start_free; + static char* _S_end_free; + static size_t _S_heap_size; -#else + static _STL_mutex_lock _S_node_allocator_lock; + static size_t + _S_round_up(size_t __bytes) + { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); } -/** - * @maint - * Default node allocator. "SGI" style. Uses __mem_interface for its - * underlying requests (and makes as few requests as possible). - * **** Currently __mem_interface is always __new_alloc, never __malloc*. - * - * Important implementation properties: - * 1. If the clients request an object of size > _MAX_BYTES, the resulting - * object will be obtained directly from the underlying __mem_interface. - * 2. In all other cases, we allocate an object of size exactly - * _S_round_up(requested_size). Thus the client has enough size - * information that we can return the object to the proper free list - * without permanently losing part of the object. - * - * The first template parameter specifies whether more than one thread may - * use this allocator. It is safe to allocate an object from one instance - * of a default_alloc and deallocate it with another one. This effectively - * transfers its ownership to the second one. This may have undesirable - * effects on reference locality. - * - * The second parameter is unused and serves only to allow the creation of - * multiple default_alloc instances. Note that containers built on different - * allocator instances have different types, limiting the utility of this - * approach. If you do not wish to share the free lists with the main - * default_alloc instance, instantiate this with a non-zero __inst. - * - * @endmaint - * (See @link Allocators allocators info @endlink for more.) -*/ -template<bool __threads, int __inst> - class __default_alloc_template - { - private: - enum {_ALIGN = 8}; - enum {_MAX_BYTES = 128}; - enum {_NFREELISTS = _MAX_BYTES / _ALIGN}; - - union _Obj - { - union _Obj* _M_free_list_link; - char _M_client_data[1]; // The client sees this. - }; + static size_t + _S_freelist_index(size_t __bytes) + { return (((__bytes) + (size_t)_ALIGN - 1)/(size_t)_ALIGN - 1); } + + // Returns an object of size __n, and optionally adds to size __n + // free list. + static void* + _S_refill(size_t __n); + + // Allocates a chunk for nobjs of size size. nobjs may be reduced + // if it is inconvenient to allocate the requested number. + static char* + _S_chunk_alloc(size_t __size, int& __nobjs); + + // It would be nice to use _STL_auto_lock here. But we need a + // test whether threads are in use. + struct _Lock + { + _Lock() { if (__threads) _S_node_allocator_lock._M_acquire_lock(); } + ~_Lock() { if (__threads) _S_node_allocator_lock._M_release_lock(); } + } __attribute__ ((__unused__)); + friend struct _Lock; + + static _Atomic_word _S_force_new; - static _Obj* volatile _S_free_list[_NFREELISTS]; - - // Chunk allocation state. - static char* _S_start_free; - static char* _S_end_free; - static size_t _S_heap_size; - - static _STL_mutex_lock _S_node_allocator_lock; - - static size_t - _S_round_up(size_t __bytes) - { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); } - - static size_t - _S_freelist_index(size_t __bytes) - { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); } - - // Returns an object of size __n, and optionally adds to size __n - // free list. - static void* - _S_refill(size_t __n); - - // Allocates a chunk for nobjs of size size. nobjs may be reduced - // if it is inconvenient to allocate the requested number. - static char* - _S_chunk_alloc(size_t __size, int& __nobjs); - - // It would be nice to use _STL_auto_lock here. But we need a - // test whether threads are in use. - class _Lock - { public: - _Lock() { if (__threads) _S_node_allocator_lock._M_acquire_lock(); } - ~_Lock() { if (__threads) _S_node_allocator_lock._M_release_lock(); } - } __attribute__ ((__unused__)); - friend class _Lock; - - public: - // __n must be > 0 - static void* - allocate(size_t __n) - { - void* __ret = 0; - - if (__n > (size_t) _MAX_BYTES) - __ret = __mem_interface::allocate(__n); - else - { - _Obj* volatile* __my_free_list = _S_free_list - + _S_freelist_index(__n); - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; - _Obj* __restrict__ __result = *__my_free_list; - if (__result == 0) - __ret = _S_refill(_S_round_up(__n)); - else - { - *__my_free_list = __result -> _M_free_list_link; - __ret = __result; - } - } - return __ret; - }; + // __n must be > 0 + static void* + allocate(size_t __n) + { + void* __ret = 0; + + // If there is a race through here, assume answer from getenv + // will resolve in same direction. Inspired by techniques + // to efficiently support threading found in basic_string.h. + if (_S_force_new == 0) + { + if (getenv("GLIBCPP_FORCE_NEW")) + __atomic_add(&_S_force_new, 1); + else + __atomic_add(&_S_force_new, -1); + // Trust but verify... + assert(_S_force_new != 0); + } + + if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0)) + __ret = __new_alloc::allocate(__n); + else + { + _Obj* volatile* __my_free_list = _S_free_list + + _S_freelist_index(__n); + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + _Obj* __restrict__ __result = *__my_free_list; + if (__builtin_expect(__result == 0, 0)) + __ret = _S_refill(_S_round_up(__n)); + else + { + *__my_free_list = __result -> _M_free_list_link; + __ret = __result; + } + if (__builtin_expect(__ret == 0, 0)) + __throw_bad_alloc(); + } + return __ret; + } - // __p may not be 0 - static void - deallocate(void* __p, size_t __n) - { - if (__n > (size_t) _MAX_BYTES) - __mem_interface::deallocate(__p, __n); - else - { - _Obj* volatile* __my_free_list - = _S_free_list + _S_freelist_index(__n); - _Obj* __q = (_Obj*)__p; - - // Acquire the lock here with a constructor call. This ensures that - // it is released in exit or during stack unwinding. - _Lock __lock_instance; - __q -> _M_free_list_link = *__my_free_list; - *__my_free_list = __q; - } - } - - static void* - reallocate(void* __p, size_t __old_sz, size_t __new_sz); - }; + // __p may not be 0 + static void + deallocate(void* __p, size_t __n) + { + if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0)) + __new_alloc::deallocate(__p, __n); + else + { + _Obj* volatile* __my_free_list = _S_free_list + + _S_freelist_index(__n); + _Obj* __q = (_Obj*)__p; + + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + __q -> _M_free_list_link = *__my_free_list; + *__my_free_list = __q; + } + } + + // _GLIBCPP_DEPRECATED + static void* + reallocate(void* __p, size_t __old_sz, size_t __new_sz); + }; + template<bool __threads, int __inst> _Atomic_word + __default_alloc_template<__threads, __inst>::_S_force_new = 0; template<bool __threads, int __inst> - inline bool - operator==(const __default_alloc_template<__threads, __inst>&, - const __default_alloc_template<__threads, __inst>&) + inline bool + operator==(const __default_alloc_template<__threads,__inst>&, + const __default_alloc_template<__threads,__inst>&) { return true; } template<bool __threads, int __inst> - inline bool - operator!=(const __default_alloc_template<__threads, __inst>&, - const __default_alloc_template<__threads, __inst>&) + inline bool + operator!=(const __default_alloc_template<__threads,__inst>&, + const __default_alloc_template<__threads,__inst>&) { return false; } // We allocate memory in large chunks in order to avoid fragmenting the - // malloc heap (or whatever __mem_interface is using) too much. We assume - // that __size is properly aligned. We hold the allocation lock. + // heap too much. We assume that __size is properly aligned. We hold + // the allocation lock. template<bool __threads, int __inst> char* - __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, - int& __nobjs) + __default_alloc_template<__threads, __inst>:: + _S_chunk_alloc(size_t __size, int& __nobjs) { char* __result; size_t __total_bytes = __size * __nobjs; size_t __bytes_left = _S_end_free - _S_start_free; - - if (__bytes_left >= __total_bytes) - { - __result = _S_start_free; - _S_start_free += __total_bytes; - return(__result); - } - else if (__bytes_left >= __size) - { - __nobjs = (int)(__bytes_left/__size); - __total_bytes = __size * __nobjs; - __result = _S_start_free; - _S_start_free += __total_bytes; - return(__result); - } - else - { - size_t __bytes_to_get = - 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); - // Try to make use of the left-over piece. - if (__bytes_left > 0) - { - _Obj* volatile* __my_free_list = - _S_free_list + _S_freelist_index(__bytes_left); - - ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list; - *__my_free_list = (_Obj*)_S_start_free; - } - _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get); - if (0 == _S_start_free) - { - size_t __i; - _Obj* volatile* __my_free_list; - _Obj* __p; - // Try to make do with what we have. That can't hurt. We - // do not try smaller requests, since that tends to result - // in disaster on multi-process machines. - __i = __size; - for (; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN) - { - __my_free_list = _S_free_list + _S_freelist_index(__i); - __p = *__my_free_list; - if (0 != __p) - { - *__my_free_list = __p -> _M_free_list_link; - _S_start_free = (char*)__p; - _S_end_free = _S_start_free + __i; - return(_S_chunk_alloc(__size, __nobjs)); - // Any leftover piece will eventually make it to the - // right free list. - } - } - _S_end_free = 0; // In case of exception. - _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get); - // This should either throw an exception or remedy the situation. - // Thus we assume it succeeded. - } - _S_heap_size += __bytes_to_get; - _S_end_free = _S_start_free + __bytes_to_get; - return(_S_chunk_alloc(__size, __nobjs)); - } + + if (__bytes_left >= __total_bytes) + { + __result = _S_start_free; + _S_start_free += __total_bytes; + return __result ; + } + else if (__bytes_left >= __size) + { + __nobjs = (int)(__bytes_left/__size); + __total_bytes = __size * __nobjs; + __result = _S_start_free; + _S_start_free += __total_bytes; + return __result; + } + else + { + size_t __bytes_to_get = + 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); + // Try to make use of the left-over piece. + if (__bytes_left > 0) + { + _Obj* volatile* __my_free_list = + _S_free_list + _S_freelist_index(__bytes_left); + + ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list; + *__my_free_list = (_Obj*)_S_start_free; + } + _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); + if (_S_start_free == 0) + { + size_t __i; + _Obj* volatile* __my_free_list; + _Obj* __p; + // Try to make do with what we have. That can't hurt. We + // do not try smaller requests, since that tends to result + // in disaster on multi-process machines. + __i = __size; + for (; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN) + { + __my_free_list = _S_free_list + _S_freelist_index(__i); + __p = *__my_free_list; + if (__p != 0) + { + *__my_free_list = __p -> _M_free_list_link; + _S_start_free = (char*)__p; + _S_end_free = _S_start_free + __i; + return _S_chunk_alloc(__size, __nobjs); + // Any leftover piece will eventually make it to the + // right free list. + } + } + _S_end_free = 0; // In case of exception. + _S_start_free = (char*)__new_alloc::allocate(__bytes_to_get); + // This should either throw an exception or remedy the situation. + // Thus we assume it succeeded. + } + _S_heap_size += __bytes_to_get; + _S_end_free = _S_start_free + __bytes_to_get; + return _S_chunk_alloc(__size, __nobjs); + } } - - + + // Returns an object of size __n, and optionally adds to "size // __n"'s free list. We assume that __n is properly aligned. We // hold the allocation lock. @@ -528,404 +564,421 @@ template<bool __threads, int __inst> _Obj* __current_obj; _Obj* __next_obj; int __i; - - if (1 == __nobjs) return(__chunk); + + if (1 == __nobjs) + return __chunk; __my_free_list = _S_free_list + _S_freelist_index(__n); - - /* Build free list in chunk */ + + // Build free list in chunk. __result = (_Obj*)__chunk; *__my_free_list = __next_obj = (_Obj*)(__chunk + __n); - for (__i = 1; ; __i++) { - __current_obj = __next_obj; - __next_obj = (_Obj*)((char*)__next_obj + __n); - if (__nobjs - 1 == __i) { - __current_obj -> _M_free_list_link = 0; - break; - } else { - __current_obj -> _M_free_list_link = __next_obj; - } - } - return(__result); + for (__i = 1; ; __i++) + { + __current_obj = __next_obj; + __next_obj = (_Obj*)((char*)__next_obj + __n); + if (__nobjs - 1 == __i) + { + __current_obj -> _M_free_list_link = 0; + break; + } + else + __current_obj -> _M_free_list_link = __next_obj; + } + return __result; } + // _GLIBCPP_DEPRECATED template<bool threads, int inst> void* - __default_alloc_template<threads, inst>::reallocate(void* __p, - size_t __old_sz, - size_t __new_sz) + __default_alloc_template<threads, inst>:: + reallocate(void* __p, size_t __old_sz, size_t __new_sz) { void* __result; size_t __copy_sz; - - if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) { + + if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) return(realloc(__p, __new_sz)); - } - if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p); + if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) + return(__p); __result = allocate(__new_sz); __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz; memcpy(__result, __p, __copy_sz); deallocate(__p, __old_sz); - return(__result); + return __result; } - + template<bool __threads, int __inst> - _STL_mutex_lock - __default_alloc_template<__threads, __inst>::_S_node_allocator_lock - __STL_MUTEX_INITIALIZER; - + _STL_mutex_lock + __default_alloc_template<__threads,__inst>::_S_node_allocator_lock + __STL_MUTEX_INITIALIZER; + template<bool __threads, int __inst> - char* __default_alloc_template<__threads, __inst>::_S_start_free = 0; - + char* __default_alloc_template<__threads,__inst>::_S_start_free = 0; + template<bool __threads, int __inst> - char* __default_alloc_template<__threads, __inst>::_S_end_free = 0; - + char* __default_alloc_template<__threads,__inst>::_S_end_free = 0; + template<bool __threads, int __inst> - size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0; - + size_t __default_alloc_template<__threads,__inst>::_S_heap_size = 0; + template<bool __threads, int __inst> - typename __default_alloc_template<__threads, __inst>::_Obj* volatile - __default_alloc_template<__threads, __inst>::_S_free_list[_NFREELISTS]; - - typedef __default_alloc_template<true, 0> __alloc; - typedef __default_alloc_template<false, 0> __single_client_alloc; + typename __default_alloc_template<__threads,__inst>::_Obj* volatile + __default_alloc_template<__threads,__inst>::_S_free_list[_NFREELISTS]; + typedef __default_alloc_template<true,0> __alloc; + typedef __default_alloc_template<false,0> __single_client_alloc; -#endif /* ! __USE_MALLOC */ + /** + * @brief The "standard" allocator, as per [20.4]. + * + * The private _Alloc is "SGI" style. (See comments at the top + * of stl_alloc.h.) + * + * The underlying allocator behaves as follows. + * - __default_alloc_template is used via two typedefs + * - "__single_client_alloc" typedef does no locking for threads + * - "__alloc" typedef is threadsafe via the locks + * - __new_alloc is used for memory requests + * + * (See @link Allocators allocators info @endlink for more.) + */ + template<typename _Tp> + class allocator + { + typedef __alloc _Alloc; // The underlying allocator. + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + + allocator() throw() {} + allocator(const allocator&) throw() {} + template<typename _Tp1> + allocator(const allocator<_Tp1>&) throw() {} + ~allocator() throw() {} + + pointer + address(reference __x) const { return &__x; } + + const_pointer + address(const_reference __x) const { return &__x; } + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _Tp* + allocate(size_type __n, const void* = 0) + { + _Tp* __ret = 0; + if (__n) + { + if (__n <= this->max_size()) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + else + __throw_bad_alloc(); + } + return __ret; + } -/** - * This is a "standard" allocator, as per [20.4]. The private _Alloc is - * "SGI" style. (See comments at the top of stl_alloc.h.) - * - * The underlying allocator behaves as follows. - * - if __USE_MALLOC then - * - thread safety depends on malloc and is entirely out of our hands - * - __malloc_alloc_template is used for memory requests - * - else (the default) - * - __default_alloc_template is used via two typedefs - * - "__single_client_alloc" typedef does no locking for threads - * - "__alloc" typedef is threadsafe via the locks - * - __new_alloc is used for memory requests - * - * (See @link Allocators allocators info @endlink for more.) -*/ -template <class _Tp> -class allocator -{ - typedef __alloc _Alloc; // The underlying allocator. -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - typedef _Tp value_type; - - template <class _Tp1> struct rebind { - typedef allocator<_Tp1> other; - }; + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { _Alloc::deallocate(__p, __n * sizeof(_Tp)); } - allocator() throw() {} - allocator(const allocator&) throw() {} - template <class _Tp1> allocator(const allocator<_Tp1>&) throw() {} - ~allocator() throw() {} - - pointer address(reference __x) const { return &__x; } - const_pointer address(const_reference __x) const { return &__x; } - - // __n is permitted to be 0. The C++ standard says nothing about what - // the return value is when __n == 0. - _Tp* allocate(size_type __n, const void* = 0) { - return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))) - : 0; - } - - // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type __n) - { _Alloc::deallocate(__p, __n * sizeof(_Tp)); } - - size_type max_size() const throw() - { return size_t(-1) / sizeof(_Tp); } - - void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } - void destroy(pointer __p) { __p->~_Tp(); } -}; - -template<> -class allocator<void> { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template <class _Tp1> struct rebind { - typedef allocator<_Tp1> other; - }; -}; + size_type + max_size() const throw() { return size_t(-1) / sizeof(_Tp); } + void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } + void destroy(pointer __p) { __p->~_Tp(); } + }; -template <class _T1, class _T2> -inline bool operator==(const allocator<_T1>&, const allocator<_T2>&) -{ - return true; -} + template<> + class allocator<void> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + }; -template <class _T1, class _T2> -inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&) -{ - return false; -} + template<typename _T1, typename _T2> + inline bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + { return true; } -/** - * @maint - * Allocator adaptor to turn an "SGI" style allocator (e.g., __alloc, - * __malloc_alloc_template) into a "standard" conforming allocator. Note - * that this adaptor does *not* assume that all objects of the underlying - * alloc class are identical, nor does it assume that all of the underlying - * alloc's member functions are static member functions. Note, also, that - * __allocator<_Tp, __alloc> is essentially the same thing as allocator<_Tp>. - * @endmaint - * (See @link Allocators allocators info @endlink for more.) -*/ -template <class _Tp, class _Alloc> -struct __allocator -{ - _Alloc __underlying_alloc; - - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - typedef _Tp value_type; - - template <class _Tp1> struct rebind { - typedef __allocator<_Tp1, _Alloc> other; - }; + template<typename _T1, typename _T2> + inline bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + { return false; } - __allocator() throw() {} - __allocator(const __allocator& __a) throw() - : __underlying_alloc(__a.__underlying_alloc) {} - template <class _Tp1> - __allocator(const __allocator<_Tp1, _Alloc>& __a) throw() - : __underlying_alloc(__a.__underlying_alloc) {} - ~__allocator() throw() {} - - pointer address(reference __x) const { return &__x; } - const_pointer address(const_reference __x) const { return &__x; } - - // __n is permitted to be 0. - _Tp* allocate(size_type __n, const void* = 0) { - return __n != 0 - ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp))) - : 0; - } - - // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type __n) - { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); } - - size_type max_size() const throw() - { return size_t(-1) / sizeof(_Tp); } - - void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } - void destroy(pointer __p) { __p->~_Tp(); } -}; - -template <class _Alloc> -class __allocator<void, _Alloc> { - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template <class _Tp1> struct rebind { - typedef __allocator<_Tp1, _Alloc> other; - }; -}; -template <class _Tp, class _Alloc> -inline bool operator==(const __allocator<_Tp, _Alloc>& __a1, - const __allocator<_Tp, _Alloc>& __a2) -{ - return __a1.__underlying_alloc == __a2.__underlying_alloc; -} + /** + * @if maint + * Allocator adaptor to turn an "SGI" style allocator (e.g., + * __alloc, __malloc_alloc_template) into a "standard" conforming + * allocator. Note that this adaptor does *not* assume that all + * objects of the underlying alloc class are identical, nor does it + * assume that all of the underlying alloc's member functions are + * static member functions. Note, also, that __allocator<_Tp, + * __alloc> is essentially the same thing as allocator<_Tp>. + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template<typename _Tp, typename _Alloc> + struct __allocator + { + _Alloc __underlying_alloc; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + + template<typename _Tp1> + struct rebind + { typedef __allocator<_Tp1, _Alloc> other; }; + + __allocator() throw() {} + __allocator(const __allocator& __a) throw() + : __underlying_alloc(__a.__underlying_alloc) {} + + template<typename _Tp1> + __allocator(const __allocator<_Tp1, _Alloc>& __a) throw() + : __underlying_alloc(__a.__underlying_alloc) {} + + ~__allocator() throw() {} + + pointer + address(reference __x) const { return &__x; } + + const_pointer + address(const_reference __x) const { return &__x; } + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _Tp* + allocate(size_type __n, const void* = 0) + { + _Tp* __ret = 0; + if (__n) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + return __ret; + } -template <class _Tp, class _Alloc> -inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1, - const __allocator<_Tp, _Alloc>& __a2) -{ - return __a1.__underlying_alloc != __a2.__underlying_alloc; -} + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); } + + size_type + max_size() const throw() { return size_t(-1) / sizeof(_Tp); } + + void + construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } + }; + template<typename _Alloc> + struct __allocator<void, _Alloc> + { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template<typename _Tp1> + struct rebind + { typedef __allocator<_Tp1, _Alloc> other; }; + }; -//@{ -/** Comparison operators for all of the predifined SGI-style allocators. - * This ensures that __allocator<malloc_alloc> (for example) will work - * correctly. As required, all allocators compare equal. -*/ -template <int inst> -inline bool operator==(const __malloc_alloc_template<inst>&, - const __malloc_alloc_template<inst>&) -{ - return true; -} + template<typename _Tp, typename _Alloc> + inline bool + operator==(const __allocator<_Tp,_Alloc>& __a1, + const __allocator<_Tp,_Alloc>& __a2) + { return __a1.__underlying_alloc == __a2.__underlying_alloc; } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const __allocator<_Tp, _Alloc>& __a1, + const __allocator<_Tp, _Alloc>& __a2) + { return __a1.__underlying_alloc != __a2.__underlying_alloc; } + + + //@{ + /** Comparison operators for all of the predifined SGI-style allocators. + * This ensures that __allocator<malloc_alloc> (for example) will work + * correctly. As required, all allocators compare equal. + */ + template<int inst> + inline bool + operator==(const __malloc_alloc_template<inst>&, + const __malloc_alloc_template<inst>&) + { return true; } -template <int __inst> -inline bool operator!=(const __malloc_alloc_template<__inst>&, - const __malloc_alloc_template<__inst>&) -{ - return false; -} + template<int __inst> + inline bool + operator!=(const __malloc_alloc_template<__inst>&, + const __malloc_alloc_template<__inst>&) + { return false; } -template <class _Alloc> -inline bool operator==(const __debug_alloc<_Alloc>&, - const __debug_alloc<_Alloc>&) { - return true; -} + template<typename _Alloc> + inline bool + operator==(const __debug_alloc<_Alloc>&, const __debug_alloc<_Alloc>&) + { return true; } -template <class _Alloc> -inline bool operator!=(const __debug_alloc<_Alloc>&, - const __debug_alloc<_Alloc>&) { - return false; -} -//@} + template<typename _Alloc> + inline bool + operator!=(const __debug_alloc<_Alloc>&, const __debug_alloc<_Alloc>&) + { return false; } + //@} -/** - * @maint - * Another allocator adaptor: _Alloc_traits. This serves two purposes. - * First, make it possible to write containers that can use either "SGI" - * style allocators or "standard" allocators. Second, provide a mechanism - * so that containers can query whether or not the allocator has distinct - * instances. If not, the container can avoid wasting a word of memory to - * store an empty object. For examples of use, see stl_vector.h, etc, or - * any of the other classes derived from this one. - * - * This adaptor uses partial specialization. The general case of - * _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a - * standard-conforming allocator, possibly with non-equal instances and - * non-static members. (It still behaves correctly even if _Alloc has - * static member and if all instances are equal. Refinements affect - * performance, not correctness.) - * - * There are always two members: allocator_type, which is a standard- - * conforming allocator type for allocating objects of type _Tp, and - * _S_instanceless, a static const member of type bool. If - * _S_instanceless is true, this means that there is no difference - * between any two instances of type allocator_type. Furthermore, if - * _S_instanceless is true, then _Alloc_traits has one additional - * member: _Alloc_type. This type encapsulates allocation and - * deallocation of objects of type _Tp through a static interface; it - * has two member functions, whose signatures are - * - * - static _Tp* allocate(size_t) - * - static void deallocate(_Tp*, size_t) - * - * The size_t parameters are "standard" style (see top of stl_alloc.h) in - * that they take counts, not sizes. - * - * @endmaint - * (See @link Allocators allocators info @endlink for more.) -*/ -//@{ -// The fully general version. -template <class _Tp, class _Allocator> -struct _Alloc_traits -{ - static const bool _S_instanceless = false; - typedef typename _Allocator::template rebind<_Tp>::other allocator_type; -}; + /** + * @if maint + * Another allocator adaptor: _Alloc_traits. This serves two purposes. + * First, make it possible to write containers that can use either "SGI" + * style allocators or "standard" allocators. Second, provide a mechanism + * so that containers can query whether or not the allocator has distinct + * instances. If not, the container can avoid wasting a word of memory to + * store an empty object. For examples of use, see stl_vector.h, etc, or + * any of the other classes derived from this one. + * + * This adaptor uses partial specialization. The general case of + * _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a + * standard-conforming allocator, possibly with non-equal instances and + * non-static members. (It still behaves correctly even if _Alloc has + * static member and if all instances are equal. Refinements affect + * performance, not correctness.) + * + * There are always two members: allocator_type, which is a standard- + * conforming allocator type for allocating objects of type _Tp, and + * _S_instanceless, a static const member of type bool. If + * _S_instanceless is true, this means that there is no difference + * between any two instances of type allocator_type. Furthermore, if + * _S_instanceless is true, then _Alloc_traits has one additional + * member: _Alloc_type. This type encapsulates allocation and + * deallocation of objects of type _Tp through a static interface; it + * has two member functions, whose signatures are + * + * - static _Tp* allocate(size_t) + * - static void deallocate(_Tp*, size_t) + * + * The size_t parameters are "standard" style (see top of stl_alloc.h) in + * that they take counts, not sizes. + * + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + //@{ + // The fully general version. + template<typename _Tp, typename _Allocator> + struct _Alloc_traits + { + static const bool _S_instanceless = false; + typedef typename _Allocator::template rebind<_Tp>::other allocator_type; + }; -template <class _Tp, class _Allocator> -const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; + template<typename _Tp, typename _Allocator> + const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; -/// The version for the default allocator. -template <class _Tp, class _Tp1> -struct _Alloc_traits<_Tp, allocator<_Tp1> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __alloc> _Alloc_type; - typedef allocator<_Tp> allocator_type; -}; -//@} - -//@{ -/// Versions for the predefined "SGI" style allocators. -template <class _Tp, int __inst> -struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; -}; - -#ifndef __USE_MALLOC -template <class _Tp, bool __threads, int __inst> -struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > - _Alloc_type; - typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > - allocator_type; -}; -#endif + /// The version for the default allocator. + template<typename _Tp, typename _Tp1> + struct _Alloc_traits<_Tp, allocator<_Tp1> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __alloc> _Alloc_type; + typedef allocator<_Tp> allocator_type; + }; + //@} -template <class _Tp, class _Alloc> -struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; - typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type; -}; -//@} - -//@{ -/// Versions for the __allocator adaptor used with the predefined "SGI" style allocators. -template <class _Tp, class _Tp1, int __inst> -struct _Alloc_traits<_Tp, - __allocator<_Tp1, __malloc_alloc_template<__inst> > > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; -}; - -#ifndef __USE_MALLOC -template <class _Tp, class _Tp1, bool __thr, int __inst> -struct _Alloc_traits<_Tp, - __allocator<_Tp1, - __default_alloc_template<__thr, __inst> > > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > - _Alloc_type; - typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > - allocator_type; -}; -#endif + //@{ + /// Versions for the predefined "SGI" style allocators. + template<typename _Tp, int __inst> + struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; + typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; + }; -template <class _Tp, class _Tp1, class _Alloc> -struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; - typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type; -}; -//@} + template<typename _Tp, bool __threads, int __inst> + struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > + _Alloc_type; + typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > + allocator_type; + }; -} // namespace std + template<typename _Tp, typename _Alloc> + struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; + typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type; + }; + //@} + + //@{ + /// Versions for the __allocator adaptor used with the predefined + /// "SGI" style allocators. + template<typename _Tp, typename _Tp1, int __inst> + struct _Alloc_traits<_Tp, + __allocator<_Tp1, __malloc_alloc_template<__inst> > > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; + typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; + }; -#endif /* __GLIBCPP_INTERNAL_ALLOC_H */ + template<typename _Tp, typename _Tp1, bool __thr, int __inst> + struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > + _Alloc_type; + typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > + allocator_type; + }; -// Local Variables: -// mode:C++ -// End: + template<typename _Tp, typename _Tp1, typename _Alloc> + struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; + typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type; + }; + //@} + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class allocator<char>; + extern template class allocator<wchar_t>; + extern template class __default_alloc_template<true,0>; +} // namespace std + +#endif diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 66c7e2de594..ce6df71b67f 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -63,17 +63,19 @@ namespace std { - extern const int __WORD_BIT; + typedef unsigned long _Bit_type; + enum { _M_word_bit = int(CHAR_BIT * sizeof(_Bit_type)) }; struct _Bit_reference { - unsigned int* _M_p; - unsigned int _M_mask; - _Bit_reference(unsigned int* __x, unsigned int __y) + + _Bit_type * _M_p; + _Bit_type _M_mask; + _Bit_reference(_Bit_type * __x, _Bit_type __y) : _M_p(__x), _M_mask(__y) {} public: _Bit_reference() : _M_p(0), _M_mask(0) {} - operator bool() const { return !(!(*_M_p & _M_mask)); } + operator bool() const { return !!(*_M_p & _M_mask); } _Bit_reference& operator=(bool __x) { if (__x) *_M_p |= _M_mask; @@ -84,9 +86,8 @@ public: { return *this = bool(__x); } bool operator==(const _Bit_reference& __x) const { return bool(*this) == bool(__x); } - bool operator<(const _Bit_reference& __x) const { - return !bool(*this) && bool(__x); - } + bool operator<(const _Bit_reference& __x) const + { return !bool(*this) && bool(__x); } void flip() { *_M_p ^= _M_mask; } }; @@ -99,31 +100,31 @@ inline void swap(_Bit_reference __x, _Bit_reference __y) struct _Bit_iterator_base : public iterator<random_access_iterator_tag, bool> { - unsigned int* _M_p; + _Bit_type * _M_p; unsigned int _M_offset; - _Bit_iterator_base(unsigned int* __x, unsigned int __y) + _Bit_iterator_base(_Bit_type * __x, unsigned int __y) : _M_p(__x), _M_offset(__y) {} void _M_bump_up() { - if (_M_offset++ == __WORD_BIT - 1) { + if (_M_offset++ == _M_word_bit - 1) { _M_offset = 0; ++_M_p; } } void _M_bump_down() { if (_M_offset-- == 0) { - _M_offset = __WORD_BIT - 1; + _M_offset = _M_word_bit - 1; --_M_p; } } void _M_incr(ptrdiff_t __i) { difference_type __n = __i + _M_offset; - _M_p += __n / __WORD_BIT; - __n = __n % __WORD_BIT; + _M_p += __n / _M_word_bit; + __n = __n % _M_word_bit; if (__n < 0) { - _M_offset = (unsigned int) __n + __WORD_BIT; + _M_offset = (unsigned int) __n + _M_word_bit; --_M_p; } else _M_offset = (unsigned int) __n; @@ -151,7 +152,7 @@ struct _Bit_iterator_base : public iterator<random_access_iterator_tag, bool> inline ptrdiff_t operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) { - return __WORD_BIT * (__x._M_p - __y._M_p) + __x._M_offset - __y._M_offset; + return _M_word_bit * (__x._M_p - __y._M_p) + __x._M_offset - __y._M_offset; } @@ -162,10 +163,10 @@ struct _Bit_iterator : public _Bit_iterator_base typedef _Bit_iterator iterator; _Bit_iterator() : _Bit_iterator_base(0, 0) {} - _Bit_iterator(unsigned int* __x, unsigned int __y) + _Bit_iterator(_Bit_type * __x, unsigned int __y) : _Bit_iterator_base(__x, __y) {} - reference operator*() const { return reference(_M_p, 1U << _M_offset); } + reference operator*() const { return reference(_M_p, 1UL << _M_offset); } iterator& operator++() { _M_bump_up(); return *this; @@ -216,13 +217,13 @@ struct _Bit_const_iterator : public _Bit_iterator_base typedef _Bit_const_iterator const_iterator; _Bit_const_iterator() : _Bit_iterator_base(0, 0) {} - _Bit_const_iterator(unsigned int* __x, unsigned int __y) + _Bit_const_iterator(_Bit_type * __x, unsigned int __y) : _Bit_iterator_base(__x, __y) {} _Bit_const_iterator(const _Bit_iterator& __x) : _Bit_iterator_base(__x._M_p, __x._M_offset) {} const_reference operator*() const { - return _Bit_reference(_M_p, 1U << _M_offset); + return _Bit_reference(_M_p, 1UL << _M_offset); } const_iterator& operator++() { _M_bump_up(); @@ -282,19 +283,19 @@ public: : _M_data_allocator(__a), _M_start(), _M_finish(), _M_end_of_storage(0) {} protected: - unsigned int* _M_bit_alloc(size_t __n) - { return _M_data_allocator.allocate((__n + __WORD_BIT - 1)/__WORD_BIT); } + _Bit_type * _M_bit_alloc(size_t __n) + { return _M_data_allocator.allocate((__n + _M_word_bit - 1)/_M_word_bit); } void _M_deallocate() { if (_M_start._M_p) _M_data_allocator.deallocate(_M_start._M_p, _M_end_of_storage - _M_start._M_p); } - typename _Alloc_traits<unsigned int, _Allocator>::allocator_type + typename _Alloc_traits<_Bit_type, _Allocator>::allocator_type _M_data_allocator; _Bit_iterator _M_start; _Bit_iterator _M_finish; - unsigned int* _M_end_of_storage; + _Bit_type * _M_end_of_storage; }; // Specialization for instanceless allocators. @@ -309,11 +310,11 @@ public: : _M_start(), _M_finish(), _M_end_of_storage(0) {} protected: - typedef typename _Alloc_traits<unsigned int, _Allocator>::_Alloc_type + typedef typename _Alloc_traits<_Bit_type, _Allocator>::_Alloc_type _Alloc_type; - unsigned int* _M_bit_alloc(size_t __n) - { return _Alloc_type::allocate((__n + __WORD_BIT - 1)/__WORD_BIT); } + _Bit_type * _M_bit_alloc(size_t __n) + { return _Alloc_type::allocate((__n + _M_word_bit - 1)/_M_word_bit); } void _M_deallocate() { if (_M_start._M_p) _Alloc_type::deallocate(_M_start._M_p, @@ -322,7 +323,7 @@ protected: _Bit_iterator _M_start; _Bit_iterator _M_finish; - unsigned int* _M_end_of_storage; + _Bit_type * _M_end_of_storage; }; template <class _Alloc> @@ -379,8 +380,8 @@ template <typename _Alloc> protected: void _M_initialize(size_type __n) { - unsigned int* __q = _M_bit_alloc(__n); - _M_end_of_storage = __q + (__n + __WORD_BIT - 1)/__WORD_BIT; + _Bit_type * __q = _M_bit_alloc(__n); + _M_end_of_storage = __q + (__n + _M_word_bit - 1)/_M_word_bit; _M_start = iterator(__q, 0); _M_finish = _M_start + difference_type(__n); } @@ -391,13 +392,14 @@ template <typename _Alloc> ++_M_finish; } else { - size_type __len = size() ? 2 * size() : __WORD_BIT; - unsigned int* __q = _M_bit_alloc(__len); + size_type __len = size() + ? 2 * size() : static_cast<size_type>(_M_word_bit); + _Bit_type * __q = _M_bit_alloc(__len); iterator __i = copy(begin(), __position, iterator(__q, 0)); *__i++ = __x; _M_finish = copy(__position, end(), __i); _M_deallocate(); - _M_end_of_storage = __q + (__len + __WORD_BIT - 1)/__WORD_BIT; + _M_end_of_storage = __q + (__len + _M_word_bit - 1)/_M_word_bit; _M_start = iterator(__q, 0); } } @@ -443,12 +445,12 @@ template <typename _Alloc> } else { size_type __len = size() + max(size(), __n); - unsigned int* __q = _M_bit_alloc(__len); + _Bit_type * __q = _M_bit_alloc(__len); iterator __i = copy(begin(), __position, iterator(__q, 0)); __i = copy(__first, __last, __i); _M_finish = copy(__position, end(), __i); _M_deallocate(); - _M_end_of_storage = __q + (__len + __WORD_BIT - 1)/__WORD_BIT; + _M_end_of_storage = __q + (__len + _M_word_bit - 1)/_M_word_bit; _M_start = iterator(__q, 0); } } @@ -609,12 +611,14 @@ template <typename _Alloc> } void reserve(size_type __n) { - if (capacity() < __n) { - unsigned int* __q = _M_bit_alloc(__n); + if (__n > this->max_size()) + __throw_length_error("vector::reserve"); + if (this->capacity() < __n) { + _Bit_type * __q = _M_bit_alloc(__n); _M_finish = copy(begin(), end(), iterator(__q, 0)); _M_deallocate(); _M_start = iterator(__q, 0); - _M_end_of_storage = __q + (__n + __WORD_BIT - 1)/__WORD_BIT; + _M_end_of_storage = __q + (__n + _M_word_bit - 1)/_M_word_bit; } } @@ -673,12 +677,12 @@ template <typename _Alloc> } else { size_type __len = size() + max(size(), __n); - unsigned int* __q = _M_bit_alloc(__len); + _Bit_type * __q = _M_bit_alloc(__len); iterator __i = copy(begin(), __position, iterator(__q, 0)); fill_n(__i, __n, __x); _M_finish = copy(__position, end(), __i + difference_type(__n)); _M_deallocate(); - _M_end_of_storage = __q + (__len + __WORD_BIT - 1)/__WORD_BIT; + _M_end_of_storage = __q + (__len + _M_word_bit - 1)/_M_word_bit; _M_start = iterator(__q, 0); } } @@ -705,7 +709,7 @@ template <typename _Alloc> insert(end(), __new_size - size(), __x); } void flip() { - for (unsigned int* __p = _M_start._M_p; __p != _M_end_of_storage; ++__p) + for (_Bit_type * __p = _M_start._M_p; __p != _M_end_of_storage; ++__p) *__p = ~*__p; } diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 51bd8a013e7..685913888c8 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -1,6 +1,6 @@ // nonstandard construct and destroy functions -*- C++ -*- -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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 @@ -67,10 +67,10 @@ namespace std { /** - * @maint + * @if maint * Constructs an object in existing memory by invoking an allocated * object's constructor with an initializer. - * @endmaint + * @endif */ template <class _T1, class _T2> inline void @@ -78,10 +78,10 @@ namespace std { new (static_cast<void*>(__p)) _T1(__value); } /** - * @maint + * @if maint * Constructs an object in existing memory by invoking an allocated * object's default constructor (no initializers). - * @endmaint + * @endif */ template <class _T1> inline void @@ -89,11 +89,11 @@ namespace std { new (static_cast<void*>(__p)) _T1(); } /** - * @maint + * @if maint * Destroy a range of objects with nontrivial destructors. * * This is a helper function used only by _Destroy(). - * @endmaint + * @endif */ template <class _ForwardIterator> inline void @@ -101,13 +101,13 @@ namespace std { for ( ; __first != __last; ++__first) _Destroy(&*__first); } /** - * @maint + * @if maint * Destroy a range of objects with trivial destructors. Since the destructors * are trivial, there's nothing to do and hopefully this function will be * entirely optimized away. * * This is a helper function used only by _Destroy(). - * @endmaint + * @endif */ template <class _ForwardIterator> inline void @@ -115,9 +115,9 @@ namespace std { } /** - * @maint + * @if maint * Destroy the object pointed to by a pointer type. - * @endmaint + * @endif */ template <class _Tp> inline void @@ -125,11 +125,11 @@ namespace std { __pointer->~_Tp(); } /** - * @maint + * @if maint * Destroy a range of objects. If the value_type of the object has * a trivial destructor, the compiler should optimize all of this * away, otherwise the objects' destructors must be invoked. - * @endmaint + * @endif */ template <class _ForwardIterator> inline void @@ -146,6 +146,3 @@ namespace std #endif /* _CPP_BITS_STL_CONSTRUCT_H */ -// Local Variables: -// mode:C++ -// End: diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index b2d58d8f0a6..cbe87796770 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -1,6 +1,6 @@ // deque implementation -*- C++ -*- -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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 @@ -73,14 +73,14 @@ namespace std { /** - * @maint + * @if maint * @brief This function controls the size of memory nodes. * @param size The size of an element. * @return The number (not bytesize) of elements per node. * * This function started off as a compiler kludge from SGI, but seems to * be a useful wrapper around a repeated constant expression. - * @endmaint + * @endif */ inline size_t __deque_buf_size(size_t __size) @@ -94,9 +94,9 @@ __deque_buf_size(size_t __size) * marking its valid range. Access to elements is done as offsets of either * of those two, relying on operator overloading in this class. * - * @maint + * @if maint * All the functions are op overloads except for _M_set_node. - * @endmaint + * @endif */ template <class _Tp, class _Ref, class _Ptr> struct _Deque_iterator @@ -130,11 +130,6 @@ struct _Deque_iterator reference operator*() const { return *_M_cur; } pointer operator->() const { return _M_cur; } - difference_type operator-(const _Self& __x) const { - return difference_type(_S_buffer_size()) * (_M_node - __x._M_node - 1) + - (_M_cur - _M_first) + (__x._M_last - __x._M_cur); - } - _Self& operator++() { ++_M_cur; if (_M_cur == _M_last) { @@ -194,21 +189,11 @@ struct _Deque_iterator reference operator[](difference_type __n) const { return *(*this + __n); } - bool operator==(const _Self& __x) const { return _M_cur == __x._M_cur; } - bool operator!=(const _Self& __x) const { return !(*this == __x); } - bool operator<(const _Self& __x) const { - return (_M_node == __x._M_node) ? - (_M_cur < __x._M_cur) : (_M_node < __x._M_node); - } - bool operator>(const _Self& __x) const { return __x < *this; } - bool operator<=(const _Self& __x) const { return !(__x < *this); } - bool operator>=(const _Self& __x) const { return !(*this < __x); } - - /** @maint + /** @if maint * Prepares to traverse new_node. Sets everything except _M_cur, which * should therefore be set by the caller immediately afterwards, based on * _M_first and _M_last. - * @endmaint + * @endif */ void _M_set_node(_Map_pointer __new_node) { _M_node = __new_node; @@ -217,6 +202,123 @@ struct _Deque_iterator } }; +// Note: we also provide overloads whose operands are of the same type in +// order to avoid ambiguos overload resolution when std::rel_ops operators +// are in scope (for additional details, see libstdc++/3628) +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return __x._M_cur == __y._M_cur; +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return __x._M_cur == __y._M_cur; +} + +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return !(__x == __y); +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return !(__x == __y); +} + +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return (__x._M_node == __y._M_node) ? + (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return (__x._M_node == __y._M_node) ? + (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); +} + +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return __y < __x; +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return __y < __x; +} + +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return !(__y < __x); +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return !(__y < __x); +} + +template <class _Tp, class _Ref, class _Ptr> +inline bool +operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) +{ + return !(__x < __y); +} + +template <class _Tp, class _RefL, class _PtrL, class _RefR, class _PtrR> +inline bool +operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return !(__x < __y); +} + +// _GLIBCPP_RESOLVE_LIB_DEFECTS +// According to the resolution of DR179 not only the various comparison +// operators but also operator- must accept mixed iterator/const_iterator +// parameters. +template <typename _Tp, typename _RefL, typename _PtrL, + typename _RefR, typename _PtrR> +inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type +operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) +{ + return _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type + (_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size()) * + (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); +} + template <class _Tp, class _Ref, class _Ptr> inline _Deque_iterator<_Tp, _Ref, _Ptr> operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) @@ -225,16 +327,16 @@ operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) } -/// @maint Primary default version. @endmaint +/// @if maint Primary default version. @endif /** - * @maint + * @if maint * Deque base class. It has two purposes. First, its constructor * and destructor allocate (but don't initialize) storage. This makes * exception safety easier. Second, the base class encapsulates all of * the differences between SGI-style allocators and standard-conforming * allocators. There are two versions: this ordinary one, and the * space-saving specialization for instanceless allocators. - * @endmaint + * @endif */ template <class _Tp, class _Alloc, bool __is_static> class _Deque_alloc_base @@ -270,7 +372,7 @@ protected: size_t _M_map_size; }; -/// Specialization for instanceless allocators. +/// @if maint Specialization for instanceless allocators. @endif template <class _Tp, class _Alloc> class _Deque_alloc_base<_Tp, _Alloc, true> { @@ -301,14 +403,14 @@ protected: /** - * @maint + * @if maint * Deque base class. Using _Alloc_traits in the instantiation of the parent * class provides the compile-time dispatching mentioned in the parent's docs. * This class provides the unified face for deque's allocation. * * Nothing in this class ever constructs or destroys an actual Tp element. * (Deque handles that itself.) Only/All memory management is performed here. - * @endmaint + * @endif */ template <class _Tp, class _Alloc> class _Deque_base @@ -352,13 +454,13 @@ _Deque_base<_Tp,_Alloc>::~_Deque_base() } /** - * @maint + * @if maint * @brief Layout storage. * @param num_elements The count of T's for which to allocate space at first. * @return Nothing. * * The initial underlying memory layout is a bit complicated... - * @endmaint + * @endif */ template <class _Tp, class _Alloc> void @@ -415,6 +517,14 @@ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) /** + * @ingroup Containers + * @ingroup Sequences + * + * Meets the requirements of a <a href="tables.html#65">container</a>, a + * <a href="tables.html#66">reversible container</a>, and a + * <a href="tables.html#67">sequence</a>, including the + * <a href="tables.html#68">optional sequence requirements</a>. + * * Placeholder: see http://www.sgi.com/tech/stl/Deque.html for now. * * In previous HP/SGI versions of deque, there was an extra template parameter @@ -422,14 +532,15 @@ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) * the C++ standard (it can be detected using template template parameters), * and it was removed. * - * @maint + * @if maint * Here's how a deque<Tp> manages memory. Each deque has 4 members: * * - Tp** _M_map * - size_t _M_map_size * - iterator _M_start, _M_finish * - * map_size is at least 8. map is an array of map_size pointers-to-"nodes". + * map_size is at least 8. %map is an array of map_size pointers-to-"nodes". + * (The name has nothing to do with the std::map class.) * * A "node" has no specific type name as such, but it is referred to as * "node" in this file. It is a simple array-of-Tp. If Tp is very large, @@ -443,18 +554,18 @@ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) * memory pool. There are 20 hours left in the year; perhaps I can fix * this before 2002. * - * Not every pointer in the map array will point to a node. If the initial - * number of elements in the deque is small, the /middle/ map pointers will + * Not every pointer in the %map array will point to a node. If the initial + * number of elements in the deque is small, the /middle/ %map pointers will * be valid, and the ones at the edges will be unused. This same situation - * will arise as the map grows: available map pointers, if any, will be on - * the ends. As new nodes are created, only a subset of the map's pointers + * will arise as the %map grows: available %map pointers, if any, will be on + * the ends. As new nodes are created, only a subset of the %map's pointers * need to be copied "outward". * * Class invariants: * - For any nonsingular iterator i: - * - i.node points to a member of the map array. (Yes, you read that + * - i.node points to a member of the %map array. (Yes, you read that * correctly: i.node does not actually point to a node.) The member of - * the map array is what actually points to the node. + * the %map array is what actually points to the node. * - i.first == *(i.node) (This points to the node (first Tp element).) * - i.last == i.first + node_size * - i.cur is a pointer in the range [i.first, i.last). NOTE: @@ -470,10 +581,10 @@ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) * that range are uninitialized storage. Otherwise, [start.cur, start.last) * and [finish.first, finish.cur) are initialized objects, and [start.first, * start.cur) and [finish.cur, finish.last) are uninitialized storage. - * - [map, map + map_size) is a valid, non-empty range. + * - [%map, %map + map_size) is a valid, non-empty range. * - [start.node, finish.node] is a valid range contained within - * [map, map + map_size). - * - A pointer in the range [map, map + map_size) points to an allocated node + * [%map, %map + map_size). + * - A pointer in the range [%map, %map + map_size) points to an allocated node * if and only if the pointer is in the range [start.node, finish.node]. * * Here's the magic: nothing in deque is "aware" of the discontiguous storage! @@ -483,8 +594,7 @@ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) * the implementation routines for deque itself work only through the start * and finish iterators. This keeps the routines simple and sane, and we can * use other standard algorithms as well. - * - * @endmaint + * @endif */ template <class _Tp, class _Alloc = allocator<_Tp> > class deque : protected _Deque_base<_Tp, _Alloc> @@ -524,11 +634,11 @@ protected: using _Base::_M_allocate_map; using _Base::_M_deallocate_map; - /** @maint + /** @if maint * A total of four data members accumulated down the heirarchy. If the * _Alloc type requires separate instances, then two of them will also be * included in each deque. - * @endmaint + * @endif */ using _Base::_M_map; using _Base::_M_map_size; @@ -555,7 +665,7 @@ public: // Basic accessors void _M_range_check(size_type __n) const { if (__n >= this->size()) - __throw_range_error("deque"); + __throw_out_of_range("deque"); } reference at(size_type __n) @@ -1035,7 +1145,7 @@ void deque<_Tp,_Alloc>::clear() } /** - * @maint + * @if maint * @brief Fills the deque with copies of value. * @param value Initial value. * @return Nothing. @@ -1044,7 +1154,7 @@ void deque<_Tp,_Alloc>::clear() * * This function is called only when the user provides an explicit size (with * or without an explicit exemplar value). - * @endmaint + * @endif */ template <class _Tp, class _Alloc> void deque<_Tp,_Alloc>::_M_fill_initialize(const value_type& __value) @@ -1063,7 +1173,7 @@ void deque<_Tp,_Alloc>::_M_fill_initialize(const value_type& __value) } /** @{ - * @maint + * @if maint * @brief Fills the deque with whatever is in [first,last). * @param first An input iterator. * @param last An input iterator. @@ -1072,7 +1182,7 @@ void deque<_Tp,_Alloc>::_M_fill_initialize(const value_type& __value) * If the iterators are actually forward iterators (or better), then the * memory layout can be done all at once. Else we move forward using * push_back on each value from the iterator. - * @endmaint + * @endif */ template <class _Tp, class _Alloc> template <class _InputIterator> void deque<_Tp,_Alloc>::_M_range_initialize(_InputIterator __first, @@ -1570,6 +1680,3 @@ inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) { #endif /* __GLIBCPP_INTERNAL_DEQUE_H */ -// Local Variables: -// mode:C++ -// End: diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index b42181f5ba2..6fb0d81339f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -548,7 +548,10 @@ namespace std return insert_iterator<_Container>(__x, typename _Container::iterator(__i)); } - +} // namespace std + +namespace __gnu_cxx +{ // This iterator adapter is 'normal' in the sense that it does not // change the semantics of any of the operators of its iterator // parameter. Its primary purpose is to convert an iterator that is @@ -556,6 +559,8 @@ namespace std // The _Container parameter exists solely so that different containers // using this template can instantiate different types, even if the // _Iterator parameter is the same. + using std::iterator_traits; + using std::iterator; template<typename _Iterator, typename _Container> class __normal_iterator : public iterator<typename iterator_traits<_Iterator>::iterator_category, @@ -624,14 +629,18 @@ namespace std operator-(const difference_type& __n) const { return __normal_iterator(_M_current - __n); } - difference_type - operator-(const __normal_iterator& __i) const - { return _M_current - __i._M_current; } - const _Iterator& base() const { return _M_current; } }; + // Note: In what follows, the left- and right-hand-side iterators are + // allowed to vary in types (conceptually in cv-qualification) so that + // comparaison between cv-qualified and non-cv-qualified iterators be + // valid. However, the greedy and unfriendly operators in std::rel_ops + // will make overload resolution ambiguous (when in scope) if we don't + // provide overloads whose operands are of the same type. Can someone + // remind me what generic programming is about? -- Gaby + // Forward iterator requirements template<typename _IteratorL, typename _IteratorR, typename _Container> inline bool @@ -639,11 +648,23 @@ namespace std const __normal_iterator<_IteratorR, _Container>& __rhs) { return __lhs.base() == __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() == __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> inline bool operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) - { return !(__lhs == __rhs); } + { return __lhs.base() != __rhs.base(); } + + template<typename _Iterator, typename _Container> + inline bool + operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() != __rhs.base(); } // Random access iterator requirements template<typename _IteratorL, typename _IteratorR, typename _Container> @@ -652,30 +673,64 @@ namespace std const __normal_iterator<_IteratorR, _Container>& __rhs) { return __lhs.base() < __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() < __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> inline bool operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) - { return __rhs < __lhs; } + { return __lhs.base() > __rhs.base(); } + + template<typename _Iterator, typename _Container> + inline bool + operator>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() > __rhs.base(); } template<typename _IteratorL, typename _IteratorR, typename _Container> inline bool operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) - { return !(__rhs < __lhs); } + { return __lhs.base() <= __rhs.base(); } + + template<typename _Iterator, typename _Container> + inline bool + operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() <= __rhs.base(); } template<typename _IteratorL, typename _IteratorR, typename _Container> inline bool operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) - { return !(__lhs < __rhs); } + { return __lhs.base() >= __rhs.base(); } + + template<typename _Iterator, typename _Container> + inline bool + operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() >= __rhs.base(); } + + // _GLIBCPP_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline typename __normal_iterator<_IteratorL, _Container>::difference_type + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() - __rhs.base(); } template<typename _Iterator, typename _Container> inline __normal_iterator<_Iterator, _Container> operator+(typename __normal_iterator<_Iterator, _Container>::difference_type __n, const __normal_iterator<_Iterator, _Container>& __i) { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } -} // namespace std +} // namespace __gnu_cxx #endif diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index e5b3fa461b4..5dff8fc3f44 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -146,10 +146,10 @@ namespace std }; /** - * @maint + * @if maint * This function is not a part of the C++ standard but is syntactic * sugar for internal library use only. - * @endmaint + * @endif */ template<typename _Iter> inline typename iterator_traits<_Iter>::iterator_category @@ -160,7 +160,3 @@ namespace std #endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_TYPES_H */ - -// Local Variables: -// mode:C++ -// End: diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 99205791387..3d470b1f25f 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -1,6 +1,6 @@ // List implementation -*- C++ -*- -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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 @@ -273,7 +273,19 @@ namespace std void clear(); }; - + /** + * @ingroup Containers + * @ingroup Sequences + * + * Meets the requirements of a <a href="tables.html#65">container</a>, a + * <a href="tables.html#66">reversible container</a>, and a + * <a href="tables.html#67">sequence</a>, including the + * <a href="tables.html#68">optional sequence requirements</a> with the + * %exception of @c at and @c operator[]. + * + * @doctodo + * + */ template<typename _Tp, typename _Alloc = allocator<_Tp> > class list : protected _List_base<_Tp, _Alloc> { diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index d689ccc8d27..b0411b2becc 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -95,7 +95,7 @@ inline bool operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) return __x.first == __y.first && __x.second == __y.second; } -/// http://gcc.gnu.org/onlinedocs/libstdc++/20_util/howto.html#pairlt +/// <http://gcc.gnu.org/onlinedocs/libstdc++/20_util/howto.html#pairlt> template <class _T1, class _T2> inline bool operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { diff --git a/libstdc++-v3/include/bits/stl_relops.h b/libstdc++-v3/include/bits/stl_relops.h index cc1ef782647..ce3dc0b9b39 100644 --- a/libstdc++-v3/include/bits/stl_relops.h +++ b/libstdc++-v3/include/bits/stl_relops.h @@ -57,7 +57,7 @@ * This is an internal header file, included by other library headers. * You should not attempt to use it directly. * - * @maint + * @if maint * Inclusion of this file has been removed from * all of the other STL headers for safety reasons, except std_utility.h. * For more information, see the thread of about twenty messages starting @@ -65,7 +65,7 @@ * FAQ at http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4 . * * Short summary: the rel_ops operators should be avoided for the present. - * @endmaint + * @endif */ #ifndef _CPP_BITS_STL_RELOPS_H diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h index 088807fb82d..7b88f9333ec 100644 --- a/libstdc++-v3/include/bits/stl_tempbuf.h +++ b/libstdc++-v3/include/bits/stl_tempbuf.h @@ -65,11 +65,11 @@ namespace std { /** - * @maint + * @if maint * This class is used in two places: stl_algo.h and ext/memory, where it * is wrapped as the temporary_buffer class. See temporary_buffer docs for * more notes. - * @endmaint + * @endif */ template <class _ForwardIterator, class _Tp> class _Temporary_buffer diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index ef50c9ee38a..d2ae142e926 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -90,1207 +90,1373 @@ iterators invalidated are those referring to the deleted node. namespace std { - typedef bool _Rb_tree_Color_type; - extern const _Rb_tree_Color_type _S_rb_tree_red; // false - extern const _Rb_tree_Color_type _S_rb_tree_black; // true + enum _Rb_tree_color { _M_red = false, _M_black = true }; -struct _Rb_tree_node_base -{ - typedef _Rb_tree_Color_type _Color_type; - typedef _Rb_tree_node_base* _Base_ptr; + struct _Rb_tree_node_base + { + typedef _Rb_tree_node_base* _Base_ptr; + + _Rb_tree_color _M_color; + _Base_ptr _M_parent; + _Base_ptr _M_left; + _Base_ptr _M_right; + + static _Base_ptr + _S_minimum(_Base_ptr __x) + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } - _Color_type _M_color; - _Base_ptr _M_parent; - _Base_ptr _M_left; - _Base_ptr _M_right; + static _Base_ptr + _S_maximum(_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + }; - static _Base_ptr _S_minimum(_Base_ptr __x) + template<typename _Val> + struct _Rb_tree_node : public _Rb_tree_node_base + { + typedef _Rb_tree_node<_Val>* _Link_type; + _Val _M_value_field; + }; + + struct _Rb_tree_base_iterator { - while (__x->_M_left != 0) __x = __x->_M_left; - return __x; - } + typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + _Base_ptr _M_node; + + void + _M_increment() + { + if (_M_node->_M_right != 0) + { + _M_node = _M_node->_M_right; + while (_M_node->_M_left != 0) + _M_node = _M_node->_M_left; + } + else + { + _Base_ptr __y = _M_node->_M_parent; + while (_M_node == __y->_M_right) + { + _M_node = __y; + __y = __y->_M_parent; + } + if (_M_node->_M_right != __y) + _M_node = __y; + } + } + + void + _M_decrement() + { + if (_M_node->_M_color == _M_red + && _M_node->_M_parent->_M_parent == _M_node) + _M_node = _M_node->_M_right; + else if (_M_node->_M_left != 0) + { + _Base_ptr __y = _M_node->_M_left; + while (__y->_M_right != 0) + __y = __y->_M_right; + _M_node = __y; + } + else + { + _Base_ptr __y = _M_node->_M_parent; + while (_M_node == __y->_M_left) + { + _M_node = __y; + __y = __y->_M_parent; + } + _M_node = __y; + } + } + }; + + template<typename _Val, typename _Ref, typename _Ptr> + struct _Rb_tree_iterator : public _Rb_tree_base_iterator + { + typedef _Val value_type; + typedef _Ref reference; + typedef _Ptr pointer; + typedef _Rb_tree_iterator<_Val, _Val&, _Val*> iterator; + typedef _Rb_tree_iterator<_Val, const _Val&, const _Val*> + const_iterator; + typedef _Rb_tree_iterator<_Val, _Ref, _Ptr> _Self; + typedef _Rb_tree_node<_Val>* _Link_type; + + _Rb_tree_iterator() {} + _Rb_tree_iterator(_Link_type __x) { _M_node = __x; } + _Rb_tree_iterator(const iterator& __it) { _M_node = __it._M_node; } + + reference + operator*() const { return _Link_type(_M_node)->_M_value_field; } + + pointer + operator->() const { return &(operator*()); } + + _Self& + operator++() + { + _M_increment(); + return *this; + } - static _Base_ptr _S_maximum(_Base_ptr __x) + _Self + operator++(int) + { + _Self __tmp = *this; + _M_increment(); + return __tmp; + } + + _Self& + operator--() { _M_decrement(); return *this; } + + _Self + operator--(int) + { + _Self __tmp = *this; + _M_decrement(); + return __tmp; + } + }; + + template<typename _Val, typename _Ref, typename _Ptr> + inline bool + operator==(const _Rb_tree_iterator<_Val, _Ref, _Ptr>& __x, + const _Rb_tree_iterator<_Val, _Ref, _Ptr>& __y) + { return __x._M_node == __y._M_node; } + + template<typename _Val> + inline bool + operator==(const _Rb_tree_iterator<_Val, const _Val&, const _Val*>& __x, + const _Rb_tree_iterator<_Val, _Val&, _Val*>& __y) + { return __x._M_node == __y._M_node; } + + template<typename _Val> + inline bool + operator==(const _Rb_tree_iterator<_Val, _Val&, _Val*>& __x, + const _Rb_tree_iterator<_Val, const _Val&, const _Val*>& __y) + { return __x._M_node == __y._M_node; } + + template<typename _Val, typename _Ref, typename _Ptr> + inline bool + operator!=(const _Rb_tree_iterator<_Val, _Ref, _Ptr>& __x, + const _Rb_tree_iterator<_Val, _Ref, _Ptr>& __y) + { return __x._M_node != __y._M_node; } + + template<typename _Val> + inline bool + operator!=(const _Rb_tree_iterator<_Val, const _Val&, const _Val*>& __x, + const _Rb_tree_iterator<_Val, _Val&, _Val*>& __y) + { return __x._M_node != __y._M_node; } + + template<typename _Val> + inline bool + operator!=(const _Rb_tree_iterator<_Val, _Val&, _Val*>& __x, + const _Rb_tree_iterator<_Val, const _Val&, const _Val*>& __y) + { return __x._M_node != __y._M_node; } + + inline void + _Rb_tree_rotate_left(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) { - while (__x->_M_right != 0) __x = __x->_M_right; - return __x; + _Rb_tree_node_base* __y = __x->_M_right; + __x->_M_right = __y->_M_left; + if (__y->_M_left !=0) + __y->_M_left->_M_parent = __x; + __y->_M_parent = __x->_M_parent; + + if (__x == __root) + __root = __y; + else if (__x == __x->_M_parent->_M_left) + __x->_M_parent->_M_left = __y; + else + __x->_M_parent->_M_right = __y; + __y->_M_left = __x; + __x->_M_parent = __y; } -}; - -template <class _Value> -struct _Rb_tree_node : public _Rb_tree_node_base -{ - typedef _Rb_tree_node<_Value>* _Link_type; - _Value _M_value_field; -}; + inline void + _Rb_tree_rotate_right(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) + { + _Rb_tree_node_base* __y = __x->_M_left; + __x->_M_left = __y->_M_right; + if (__y->_M_right != 0) + __y->_M_right->_M_parent = __x; + __y->_M_parent = __x->_M_parent; -struct _Rb_tree_base_iterator -{ - typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; - typedef bidirectional_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; - _Base_ptr _M_node; + if (__x == __root) + __root = __y; + else if (__x == __x->_M_parent->_M_right) + __x->_M_parent->_M_right = __y; + else + __x->_M_parent->_M_left = __y; + __y->_M_right = __x; + __x->_M_parent = __y; + } - void _M_increment() + inline void + _Rb_tree_rebalance(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) { - if (_M_node->_M_right != 0) { - _M_node = _M_node->_M_right; - while (_M_node->_M_left != 0) - _M_node = _M_node->_M_left; - } - else { - _Base_ptr __y = _M_node->_M_parent; - while (_M_node == __y->_M_right) { - _M_node = __y; - __y = __y->_M_parent; + __x->_M_color = _M_red; + while (__x != __root + && __x->_M_parent->_M_color == _M_red) + { + if (__x->_M_parent == __x->_M_parent->_M_parent->_M_left) + { + _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_right; + if (__y && __y->_M_color == _M_red) + { + __x->_M_parent->_M_color = _M_black; + __y->_M_color = _M_black; + __x->_M_parent->_M_parent->_M_color = _M_red; + __x = __x->_M_parent->_M_parent; + } + else + { + if (__x == __x->_M_parent->_M_right) + { + __x = __x->_M_parent; + _Rb_tree_rotate_left(__x, __root); + } + __x->_M_parent->_M_color = _M_black; + __x->_M_parent->_M_parent->_M_color = _M_red; + _Rb_tree_rotate_right(__x->_M_parent->_M_parent, __root); + } + } + else + { + _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_left; + if (__y && __y->_M_color == _M_red) + { + __x->_M_parent->_M_color = _M_black; + __y->_M_color = _M_black; + __x->_M_parent->_M_parent->_M_color = _M_red; + __x = __x->_M_parent->_M_parent; + } + else + { + if (__x == __x->_M_parent->_M_left) + { + __x = __x->_M_parent; + _Rb_tree_rotate_right(__x, __root); + } + __x->_M_parent->_M_color = _M_black; + __x->_M_parent->_M_parent->_M_color = _M_red; + _Rb_tree_rotate_left(__x->_M_parent->_M_parent, __root); + } + } } - if (_M_node->_M_right != __y) - _M_node = __y; - } + __root->_M_color = _M_black; } - void _M_decrement() + inline _Rb_tree_node_base* + _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* __z, + _Rb_tree_node_base*& __root, + _Rb_tree_node_base*& __leftmost, + _Rb_tree_node_base*& __rightmost) { - if (_M_node->_M_color == _S_rb_tree_red && - _M_node->_M_parent->_M_parent == _M_node) - _M_node = _M_node->_M_right; - else if (_M_node->_M_left != 0) { - _Base_ptr __y = _M_node->_M_left; - while (__y->_M_right != 0) - __y = __y->_M_right; - _M_node = __y; - } - else { - _Base_ptr __y = _M_node->_M_parent; - while (_M_node == __y->_M_left) { - _M_node = __y; - __y = __y->_M_parent; + _Rb_tree_node_base* __y = __z; + _Rb_tree_node_base* __x = 0; + _Rb_tree_node_base* __x_parent = 0; + if (__y->_M_left == 0) // __z has at most one non-null child. y == z. + __x = __y->_M_right; // __x might be null. + else + if (__y->_M_right == 0) // __z has exactly one non-null child. y == z. + __x = __y->_M_left; // __x is not null. + else + { + // __z has two non-null children. Set __y to + __y = __y->_M_right; // __z's successor. __x might be null. + while (__y->_M_left != 0) + __y = __y->_M_left; + __x = __y->_M_right; + } + if (__y != __z) + { + // relink y in place of z. y is z's successor + __z->_M_left->_M_parent = __y; + __y->_M_left = __z->_M_left; + if (__y != __z->_M_right) + { + __x_parent = __y->_M_parent; + if (__x) __x->_M_parent = __y->_M_parent; + __y->_M_parent->_M_left = __x; // __y must be a child of _M_left + __y->_M_right = __z->_M_right; + __z->_M_right->_M_parent = __y; + } + else + __x_parent = __y; + if (__root == __z) + __root = __y; + else if (__z->_M_parent->_M_left == __z) + __z->_M_parent->_M_left = __y; + else + __z->_M_parent->_M_right = __y; + __y->_M_parent = __z->_M_parent; + std::swap(__y->_M_color, __z->_M_color); + __y = __z; + // __y now points to node to be actually deleted } - _M_node = __y; - } - } -}; - -template <class _Value, class _Ref, class _Ptr> -struct _Rb_tree_iterator : public _Rb_tree_base_iterator -{ - typedef _Value value_type; - typedef _Ref reference; - typedef _Ptr pointer; - typedef _Rb_tree_iterator<_Value, _Value&, _Value*> - iterator; - typedef _Rb_tree_iterator<_Value, const _Value&, const _Value*> - const_iterator; - typedef _Rb_tree_iterator<_Value, _Ref, _Ptr> - _Self; - typedef _Rb_tree_node<_Value>* _Link_type; - - _Rb_tree_iterator() {} - _Rb_tree_iterator(_Link_type __x) { _M_node = __x; } - _Rb_tree_iterator(const iterator& __it) { _M_node = __it._M_node; } - - reference operator*() const { return _Link_type(_M_node)->_M_value_field; } - pointer operator->() const { return &(operator*()); } - - _Self& operator++() { _M_increment(); return *this; } - _Self operator++(int) { - _Self __tmp = *this; - _M_increment(); - return __tmp; - } - - _Self& operator--() { _M_decrement(); return *this; } - _Self operator--(int) { - _Self __tmp = *this; - _M_decrement(); - return __tmp; + else + { // __y == __z + __x_parent = __y->_M_parent; + if (__x) + __x->_M_parent = __y->_M_parent; + if (__root == __z) + __root = __x; + else + if (__z->_M_parent->_M_left == __z) + __z->_M_parent->_M_left = __x; + else + __z->_M_parent->_M_right = __x; + if (__leftmost == __z) + if (__z->_M_right == 0) // __z->_M_left must be null also + __leftmost = __z->_M_parent; + // makes __leftmost == _M_header if __z == __root + else + __leftmost = _Rb_tree_node_base::_S_minimum(__x); + if (__rightmost == __z) + if (__z->_M_left == 0) // __z->_M_right must be null also + __rightmost = __z->_M_parent; + // makes __rightmost == _M_header if __z == __root + else // __x == __z->_M_left + __rightmost = _Rb_tree_node_base::_S_maximum(__x); + } + if (__y->_M_color != _M_red) + { + while (__x != __root && (__x == 0 || __x->_M_color == _M_black)) + if (__x == __x_parent->_M_left) + { + _Rb_tree_node_base* __w = __x_parent->_M_right; + if (__w->_M_color == _M_red) + { + __w->_M_color = _M_black; + __x_parent->_M_color = _M_red; + _Rb_tree_rotate_left(__x_parent, __root); + __w = __x_parent->_M_right; + } + if ((__w->_M_left == 0 || + __w->_M_left->_M_color == _M_black) && + (__w->_M_right == 0 || + __w->_M_right->_M_color == _M_black)) + { + __w->_M_color = _M_red; + __x = __x_parent; + __x_parent = __x_parent->_M_parent; + } + else + { + if (__w->_M_right == 0 + || __w->_M_right->_M_color == _M_black) + { + if (__w->_M_left) __w->_M_left->_M_color = _M_black; + __w->_M_color = _M_red; + _Rb_tree_rotate_right(__w, __root); + __w = __x_parent->_M_right; + } + __w->_M_color = __x_parent->_M_color; + __x_parent->_M_color = _M_black; + if (__w->_M_right) + __w->_M_right->_M_color = _M_black; + _Rb_tree_rotate_left(__x_parent, __root); + break; + } + } + else + { + // same as above, with _M_right <-> _M_left. + _Rb_tree_node_base* __w = __x_parent->_M_left; + if (__w->_M_color == _M_red) + { + __w->_M_color = _M_black; + __x_parent->_M_color = _M_red; + _Rb_tree_rotate_right(__x_parent, __root); + __w = __x_parent->_M_left; + } + if ((__w->_M_right == 0 || + __w->_M_right->_M_color == _M_black) && + (__w->_M_left == 0 || + __w->_M_left->_M_color == _M_black)) + { + __w->_M_color = _M_red; + __x = __x_parent; + __x_parent = __x_parent->_M_parent; + } + else + { + if (__w->_M_left == 0 || __w->_M_left->_M_color == _M_black) + { + if (__w->_M_right) __w->_M_right->_M_color = _M_black; + __w->_M_color = _M_red; + _Rb_tree_rotate_left(__w, __root); + __w = __x_parent->_M_left; + } + __w->_M_color = __x_parent->_M_color; + __x_parent->_M_color = _M_black; + if (__w->_M_left) + __w->_M_left->_M_color = _M_black; + _Rb_tree_rotate_right(__x_parent, __root); + break; + } + } + if (__x) __x->_M_color = _M_black; + } + return __y; } -}; - -template <class _Value, class _Ref, class _Ptr> -inline bool operator==(const _Rb_tree_iterator<_Value, _Ref, _Ptr>& __x, - const _Rb_tree_iterator<_Value, _Ref, _Ptr>& __y) { - return __x._M_node == __y._M_node; -} - -template <class _Value> -inline bool operator==(const _Rb_tree_iterator<_Value, const _Value&, const _Value*>& __x, - const _Rb_tree_iterator<_Value, _Value&, _Value*>& __y) { - return __x._M_node == __y._M_node; -} - -template <class _Value> -inline bool operator==(const _Rb_tree_iterator<_Value, _Value&, _Value*>& __x, - const _Rb_tree_iterator<_Value, const _Value&, const _Value*>& __y) { - return __x._M_node == __y._M_node; -} - -template <class _Value, class _Ref, class _Ptr> -inline bool operator!=(const _Rb_tree_iterator<_Value, _Ref, _Ptr>& __x, - const _Rb_tree_iterator<_Value, _Ref, _Ptr>& __y) { - return __x._M_node != __y._M_node; -} - -template <class _Value> -inline bool operator!=(const _Rb_tree_iterator<_Value, const _Value&, const _Value*>& __x, - const _Rb_tree_iterator<_Value, _Value&, _Value*>& __y) { - return __x._M_node != __y._M_node; -} - -template <class _Value> -inline bool operator!=(const _Rb_tree_iterator<_Value, _Value&, _Value*>& __x, - const _Rb_tree_iterator<_Value, const _Value&, const _Value*>& __y) { - return __x._M_node != __y._M_node; -} - -inline void -_Rb_tree_rotate_left(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) -{ - _Rb_tree_node_base* __y = __x->_M_right; - __x->_M_right = __y->_M_left; - if (__y->_M_left !=0) - __y->_M_left->_M_parent = __x; - __y->_M_parent = __x->_M_parent; - - if (__x == __root) - __root = __y; - else if (__x == __x->_M_parent->_M_left) - __x->_M_parent->_M_left = __y; - else - __x->_M_parent->_M_right = __y; - __y->_M_left = __x; - __x->_M_parent = __y; -} - -inline void -_Rb_tree_rotate_right(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) -{ - _Rb_tree_node_base* __y = __x->_M_left; - __x->_M_left = __y->_M_right; - if (__y->_M_right != 0) - __y->_M_right->_M_parent = __x; - __y->_M_parent = __x->_M_parent; - - if (__x == __root) - __root = __y; - else if (__x == __x->_M_parent->_M_right) - __x->_M_parent->_M_right = __y; - else - __x->_M_parent->_M_left = __y; - __y->_M_right = __x; - __x->_M_parent = __y; -} - -inline void -_Rb_tree_rebalance(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root) -{ - __x->_M_color = _S_rb_tree_red; - while (__x != __root && __x->_M_parent->_M_color == _S_rb_tree_red) { - if (__x->_M_parent == __x->_M_parent->_M_parent->_M_left) { - _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_right; - if (__y && __y->_M_color == _S_rb_tree_red) { - __x->_M_parent->_M_color = _S_rb_tree_black; - __y->_M_color = _S_rb_tree_black; - __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red; - __x = __x->_M_parent->_M_parent; + + // Base class to encapsulate the differences between old SGI-style + // allocators and standard-conforming allocators. In order to avoid + // having an empty base class, we arbitrarily move one of rb_tree's + // data members into the base class. + + // _Base for general standard-conforming allocators. + template<typename _Tp, typename _Alloc, bool _S_instanceless> + class _Rb_tree_alloc_base + { + public: + typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; + + allocator_type + get_allocator() const { return _M_node_allocator; } + + _Rb_tree_alloc_base(const allocator_type& __a) + : _M_node_allocator(__a), _M_header(0) {} + + protected: + typename _Alloc_traits<_Rb_tree_node<_Tp>, _Alloc>::allocator_type + _M_node_allocator; + + _Rb_tree_node<_Tp>* _M_header; + + _Rb_tree_node<_Tp>* + _M_get_node() { return _M_node_allocator.allocate(1); } + + void + _M_put_node(_Rb_tree_node<_Tp>* __p) + { _M_node_allocator.deallocate(__p, 1); } + }; + + // Specialization for instanceless allocators. + template<typename _Tp, typename _Alloc> + class _Rb_tree_alloc_base<_Tp, _Alloc, true> + { + public: + typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { return allocator_type(); } + + _Rb_tree_alloc_base(const allocator_type&) : _M_header(0) {} + + protected: + _Rb_tree_node<_Tp>* _M_header; + + typedef typename _Alloc_traits<_Rb_tree_node<_Tp>, _Alloc>::_Alloc_type + _Alloc_type; + + _Rb_tree_node<_Tp>* + _M_get_node() { return _Alloc_type::allocate(1); } + + void + _M_put_node(_Rb_tree_node<_Tp>* __p) { _Alloc_type::deallocate(__p, 1); } + }; + + template<typename _Tp, typename _Alloc> + struct _Rb_tree_base : public _Rb_tree_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + { + typedef _Rb_tree_alloc_base<_Tp, + _Alloc, _Alloc_traits<_Tp, _Alloc>::_S_instanceless> _Base; + typedef typename _Base::allocator_type allocator_type; + + _Rb_tree_base(const allocator_type& __a) + : _Base(__a) { _M_header = _M_get_node(); } + ~_Rb_tree_base() { _M_put_node(_M_header); } + }; + + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc = allocator<_Val> > + class _Rb_tree : protected _Rb_tree_base<_Val, _Alloc> + { + typedef _Rb_tree_base<_Val, _Alloc> _Base; + + protected: + typedef _Rb_tree_node_base* _Base_ptr; + typedef _Rb_tree_node<_Val> _Rb_tree_node; + + public: + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef _Rb_tree_node* _Link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename _Base::allocator_type allocator_type; + allocator_type get_allocator() const { return _Base::get_allocator(); } + + protected: + using _Base::_M_get_node; + using _Base::_M_put_node; + using _Base::_M_header; + + _Link_type + _M_create_node(const value_type& __x) + { + _Link_type __tmp = _M_get_node(); + try + { _Construct(&__tmp->_M_value_field, __x); } + catch(...) + { + _M_put_node(__tmp); + __throw_exception_again; + } + return __tmp; } - else { - if (__x == __x->_M_parent->_M_right) { - __x = __x->_M_parent; - _Rb_tree_rotate_left(__x, __root); - } - __x->_M_parent->_M_color = _S_rb_tree_black; - __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_right(__x->_M_parent->_M_parent, __root); + + _Link_type + _M_clone_node(_Link_type __x) + { + _Link_type __tmp = _M_create_node(__x->_M_value_field); + __tmp->_M_color = __x->_M_color; + __tmp->_M_left = 0; + __tmp->_M_right = 0; + return __tmp; } - } - else { - _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_left; - if (__y && __y->_M_color == _S_rb_tree_red) { - __x->_M_parent->_M_color = _S_rb_tree_black; - __y->_M_color = _S_rb_tree_black; - __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red; - __x = __x->_M_parent->_M_parent; + + void + destroy_node(_Link_type __p) + { + _Destroy(&__p->_M_value_field); + _M_put_node(__p); + } + + size_type _M_node_count; // keeps track of size of tree + _Compare _M_key_compare; + + _Link_type& + _M_root() const { return (_Link_type&) _M_header->_M_parent; } + + _Link_type& + _M_leftmost() const { return (_Link_type&) _M_header->_M_left; } + + _Link_type& + _M_rightmost() const { return (_Link_type&) _M_header->_M_right; } + + static _Link_type& + _S_left(_Link_type __x) { return (_Link_type&)(__x->_M_left); } + + static _Link_type& + _S_right(_Link_type __x) { return (_Link_type&)(__x->_M_right); } + + static _Link_type& + _S_parent(_Link_type __x) { return (_Link_type&)(__x->_M_parent); } + + static reference + _S_value(_Link_type __x) { return __x->_M_value_field; } + + static const _Key& + _S_key(_Link_type __x) { return _KeyOfValue()(_S_value(__x)); } + + static _Rb_tree_color& + _S_color(_Link_type __x) { return __x->_M_color; } + + static _Link_type& + _S_left(_Base_ptr __x) { return (_Link_type&)(__x->_M_left); } + + static _Link_type& + _S_right(_Base_ptr __x) { return (_Link_type&)(__x->_M_right); } + + static _Link_type& + _S_parent(_Base_ptr __x) { return (_Link_type&)(__x->_M_parent); } + + static reference + _S_value(_Base_ptr __x) { return ((_Link_type)__x)->_M_value_field; } + + static const _Key& + _S_key(_Base_ptr __x) { return _KeyOfValue()(_S_value(_Link_type(__x)));} + + static _Rb_tree_color& + _S_color(_Base_ptr __x) { return (_Link_type(__x)->_M_color); } + + static _Link_type + _S_minimum(_Link_type __x) + { return (_Link_type) _Rb_tree_node_base::_S_minimum(__x); } + + static _Link_type + _S_maximum(_Link_type __x) + { return (_Link_type) _Rb_tree_node_base::_S_maximum(__x); } + + public: + typedef _Rb_tree_iterator<value_type, reference, pointer> iterator; + typedef _Rb_tree_iterator<value_type, const_reference, const_pointer> + const_iterator; + + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; + + private: + iterator + _M_insert(_Base_ptr __x, _Base_ptr __y, const value_type& __v); + + _Link_type + _M_copy(_Link_type __x, _Link_type __p); + + void + _M_erase(_Link_type __x); + + public: + // allocation/deallocation + _Rb_tree() + : _Base(allocator_type()), _M_node_count(0), _M_key_compare() + { _M_empty_initialize(); } + + _Rb_tree(const _Compare& __comp) + : _Base(allocator_type()), _M_node_count(0), _M_key_compare(__comp) + { _M_empty_initialize(); } + + _Rb_tree(const _Compare& __comp, const allocator_type& __a) + : _Base(__a), _M_node_count(0), _M_key_compare(__comp) + { _M_empty_initialize(); } + + _Rb_tree(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x) + : _Base(__x.get_allocator()), _M_node_count(0), + _M_key_compare(__x._M_key_compare) + { + if (__x._M_root() == 0) + _M_empty_initialize(); + else + { + _S_color(_M_header) = _M_red; + _M_root() = _M_copy(__x._M_root(), _M_header); + _M_leftmost() = _S_minimum(_M_root()); + _M_rightmost() = _S_maximum(_M_root()); + } + _M_node_count = __x._M_node_count; } - else { - if (__x == __x->_M_parent->_M_left) { - __x = __x->_M_parent; - _Rb_tree_rotate_right(__x, __root); - } - __x->_M_parent->_M_color = _S_rb_tree_black; - __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_left(__x->_M_parent->_M_parent, __root); + + ~_Rb_tree() { clear(); } + + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& + operator=(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x); + + private: + void _M_empty_initialize() + { + _S_color(_M_header) = _M_red; // used to distinguish header from + // __root, in iterator.operator++ + _M_root() = 0; + _M_leftmost() = _M_header; + _M_rightmost() = _M_header; + } + + public: + // Accessors. + _Compare + key_comp() const { return _M_key_compare; } + + iterator + begin() { return _M_leftmost(); } + + const_iterator + begin() const { return _M_leftmost(); } + + iterator + end() { return _M_header; } + + const_iterator + end() const { return _M_header; } + + reverse_iterator + rbegin() { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const { return const_reverse_iterator(end()); } + + reverse_iterator + rend() { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const { return const_reverse_iterator(begin()); } + + bool + empty() const { return _M_node_count == 0; } + + size_type + size() const { return _M_node_count; } + + size_type + max_size() const { return size_type(-1); } + + void + swap(_Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __t) + { + std::swap(_M_header, __t._M_header); + std::swap(_M_node_count, __t._M_node_count); + std::swap(_M_key_compare, __t._M_key_compare); } + + // Insert/erase. + pair<iterator,bool> + insert_unique(const value_type& __x); + + iterator + insert_equal(const value_type& __x); + + iterator + insert_unique(iterator __position, const value_type& __x); + + iterator + insert_equal(iterator __position, const value_type& __x); + + template<typename _InputIterator> + void + insert_unique(_InputIterator __first, _InputIterator __last); + + template<typename _InputIterator> + void + insert_equal(_InputIterator __first, _InputIterator __last); + + void + erase(iterator __position); + + size_type + erase(const key_type& __x); + + void + erase(iterator __first, iterator __last); + + void + erase(const key_type* __first, const key_type* __last); + + void + clear() + { + if (_M_node_count != 0) + { + _M_erase(_M_root()); + _M_leftmost() = _M_header; + _M_root() = 0; + _M_rightmost() = _M_header; + _M_node_count = 0; + } + } + + // Set operations. + iterator + find(const key_type& __x); + + const_iterator + find(const key_type& __x) const; + + size_type + count(const key_type& __x) const; + + iterator + lower_bound(const key_type& __x); + + const_iterator + lower_bound(const key_type& __x) const; + + iterator + upper_bound(const key_type& __x); + + const_iterator + upper_bound(const key_type& __x) const; + + pair<iterator,iterator> + equal_range(const key_type& __x); + + pair<const_iterator, const_iterator> + equal_range(const key_type& __x) const; + + // Debugging. + bool + __rb_verify() const; + }; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator==(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { + return __x.size() == __y.size() && + equal(__x.begin(), __x.end(), __y.begin()); } - } - __root->_M_color = _S_rb_tree_black; -} - -inline _Rb_tree_node_base* -_Rb_tree_rebalance_for_erase(_Rb_tree_node_base* __z, - _Rb_tree_node_base*& __root, - _Rb_tree_node_base*& __leftmost, - _Rb_tree_node_base*& __rightmost) -{ - _Rb_tree_node_base* __y = __z; - _Rb_tree_node_base* __x = 0; - _Rb_tree_node_base* __x_parent = 0; - if (__y->_M_left == 0) // __z has at most one non-null child. y == z. - __x = __y->_M_right; // __x might be null. - else - if (__y->_M_right == 0) // __z has exactly one non-null child. y == z. - __x = __y->_M_left; // __x is not null. - else { // __z has two non-null children. Set __y to - __y = __y->_M_right; // __z's successor. __x might be null. - while (__y->_M_left != 0) - __y = __y->_M_left; - __x = __y->_M_right; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator<(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { + return lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } - if (__y != __z) { // relink y in place of z. y is z's successor - __z->_M_left->_M_parent = __y; - __y->_M_left = __z->_M_left; - if (__y != __z->_M_right) { - __x_parent = __y->_M_parent; - if (__x) __x->_M_parent = __y->_M_parent; - __y->_M_parent->_M_left = __x; // __y must be a child of _M_left - __y->_M_right = __z->_M_right; - __z->_M_right->_M_parent = __y; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator!=(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { return !(__x == __y); } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator>(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { return __y < __x; } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator<=(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { return !(__y < __x); } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline bool + operator>=(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { return !(__x < __y); } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline void + swap(_Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x, + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __y) + { __x.swap(__y); } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + operator=(const _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>& __x) + { + if (this != &__x) + { + // Note that _Key may be a constant type. + clear(); + _M_node_count = 0; + _M_key_compare = __x._M_key_compare; + if (__x._M_root() == 0) + { + _M_root() = 0; + _M_leftmost() = _M_header; + _M_rightmost() = _M_header; + } + else + { + _M_root() = _M_copy(__x._M_root(), _M_header); + _M_leftmost() = _S_minimum(_M_root()); + _M_rightmost() = _S_maximum(_M_root()); + _M_node_count = __x._M_node_count; + } + } + return *this; } - else - __x_parent = __y; - if (__root == __z) - __root = __y; - else if (__z->_M_parent->_M_left == __z) - __z->_M_parent->_M_left = __y; - else - __z->_M_parent->_M_right = __y; - __y->_M_parent = __z->_M_parent; - std::swap(__y->_M_color, __z->_M_color); - __y = __z; - // __y now points to node to be actually deleted - } - else { // __y == __z - __x_parent = __y->_M_parent; - if (__x) __x->_M_parent = __y->_M_parent; - if (__root == __z) - __root = __x; - else - if (__z->_M_parent->_M_left == __z) - __z->_M_parent->_M_left = __x; - else - __z->_M_parent->_M_right = __x; - if (__leftmost == __z) - if (__z->_M_right == 0) // __z->_M_left must be null also - __leftmost = __z->_M_parent; - // makes __leftmost == _M_header if __z == __root - else - __leftmost = _Rb_tree_node_base::_S_minimum(__x); - if (__rightmost == __z) - if (__z->_M_left == 0) // __z->_M_right must be null also - __rightmost = __z->_M_parent; - // makes __rightmost == _M_header if __z == __root - else // __x == __z->_M_left - __rightmost = _Rb_tree_node_base::_S_maximum(__x); - } - if (__y->_M_color != _S_rb_tree_red) { - while (__x != __root && (__x == 0 || __x->_M_color == _S_rb_tree_black)) - if (__x == __x_parent->_M_left) { - _Rb_tree_node_base* __w = __x_parent->_M_right; - if (__w->_M_color == _S_rb_tree_red) { - __w->_M_color = _S_rb_tree_black; - __x_parent->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_left(__x_parent, __root); - __w = __x_parent->_M_right; - } - if ((__w->_M_left == 0 || - __w->_M_left->_M_color == _S_rb_tree_black) && - (__w->_M_right == 0 || - __w->_M_right->_M_color == _S_rb_tree_black)) { - __w->_M_color = _S_rb_tree_red; - __x = __x_parent; - __x_parent = __x_parent->_M_parent; - } else { - if (__w->_M_right == 0 || - __w->_M_right->_M_color == _S_rb_tree_black) { - if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black; - __w->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_right(__w, __root); - __w = __x_parent->_M_right; - } - __w->_M_color = __x_parent->_M_color; - __x_parent->_M_color = _S_rb_tree_black; - if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black; - _Rb_tree_rotate_left(__x_parent, __root); - break; - } - } else { // same as above, with _M_right <-> _M_left. - _Rb_tree_node_base* __w = __x_parent->_M_left; - if (__w->_M_color == _S_rb_tree_red) { - __w->_M_color = _S_rb_tree_black; - __x_parent->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_right(__x_parent, __root); - __w = __x_parent->_M_left; - } - if ((__w->_M_right == 0 || - __w->_M_right->_M_color == _S_rb_tree_black) && - (__w->_M_left == 0 || - __w->_M_left->_M_color == _S_rb_tree_black)) { - __w->_M_color = _S_rb_tree_red; - __x = __x_parent; - __x_parent = __x_parent->_M_parent; - } else { - if (__w->_M_left == 0 || - __w->_M_left->_M_color == _S_rb_tree_black) { - if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black; - __w->_M_color = _S_rb_tree_red; - _Rb_tree_rotate_left(__w, __root); - __w = __x_parent->_M_left; - } - __w->_M_color = __x_parent->_M_color; - __x_parent->_M_color = _S_rb_tree_black; - if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black; - _Rb_tree_rotate_right(__x_parent, __root); - break; - } - } - if (__x) __x->_M_color = _S_rb_tree_black; - } - return __y; -} - -// Base class to encapsulate the differences between old SGI-style -// allocators and standard-conforming allocators. In order to avoid -// having an empty base class, we arbitrarily move one of rb_tree's -// data members into the base class. - -// _Base for general standard-conforming allocators. -template <class _Tp, class _Alloc, bool _S_instanceless> -class _Rb_tree_alloc_base { -public: - typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return _M_node_allocator; } - - _Rb_tree_alloc_base(const allocator_type& __a) - : _M_node_allocator(__a), _M_header(0) {} - -protected: - typename _Alloc_traits<_Rb_tree_node<_Tp>, _Alloc>::allocator_type - _M_node_allocator; - _Rb_tree_node<_Tp>* _M_header; - - _Rb_tree_node<_Tp>* _M_get_node() - { return _M_node_allocator.allocate(1); } - void _M_put_node(_Rb_tree_node<_Tp>* __p) - { _M_node_allocator.deallocate(__p, 1); } -}; - -// Specialization for instanceless allocators. -template <class _Tp, class _Alloc> -class _Rb_tree_alloc_base<_Tp, _Alloc, true> { -public: - typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return allocator_type(); } - - _Rb_tree_alloc_base(const allocator_type&) : _M_header(0) {} - -protected: - _Rb_tree_node<_Tp>* _M_header; - - typedef typename _Alloc_traits<_Rb_tree_node<_Tp>, _Alloc>::_Alloc_type - _Alloc_type; - - _Rb_tree_node<_Tp>* _M_get_node() - { return _Alloc_type::allocate(1); } - void _M_put_node(_Rb_tree_node<_Tp>* __p) - { _Alloc_type::deallocate(__p, 1); } -}; - -template <class _Tp, class _Alloc> -struct _Rb_tree_base - : public _Rb_tree_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> -{ - typedef _Rb_tree_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - _Base; - typedef typename _Base::allocator_type allocator_type; - - _Rb_tree_base(const allocator_type& __a) - : _Base(__a) { _M_header = _M_get_node(); } - ~_Rb_tree_base() { _M_put_node(_M_header); } - -}; - - -template <class _Key, class _Value, class _KeyOfValue, class _Compare, - class _Alloc = allocator<_Value> > -class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc> { - typedef _Rb_tree_base<_Value, _Alloc> _Base; -protected: - typedef _Rb_tree_node_base* _Base_ptr; - typedef _Rb_tree_node<_Value> _Rb_tree_node; - typedef _Rb_tree_Color_type _Color_type; -public: - typedef _Key key_type; - typedef _Value value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef _Rb_tree_node* _Link_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - - typedef typename _Base::allocator_type allocator_type; - allocator_type get_allocator() const { return _Base::get_allocator(); } - -protected: - using _Base::_M_get_node; - using _Base::_M_put_node; - using _Base::_M_header; - -protected: - - _Link_type - _M_create_node(const value_type& __x) - { - _Link_type __tmp = _M_get_node(); - try { - _Construct(&__tmp->_M_value_field, __x); + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + _M_insert(_Base_ptr __x_, _Base_ptr __y_, const _Val& __v) + { + _Link_type __x = (_Link_type) __x_; + _Link_type __y = (_Link_type) __y_; + _Link_type __z; + + if (__y == _M_header || __x != 0 || + _M_key_compare(_KeyOfValue()(__v), _S_key(__y))) + { + __z = _M_create_node(__v); + _S_left(__y) = __z; // also makes _M_leftmost() = __z + // when __y == _M_header + if (__y == _M_header) + { + _M_root() = __z; + _M_rightmost() = __z; + } + else if (__y == _M_leftmost()) + _M_leftmost() = __z; // maintain _M_leftmost() pointing to min node + } + else + { + __z = _M_create_node(__v); + _S_right(__y) = __z; + // Maintain _M_rightmost() pointing to max node. + if (__y == _M_rightmost()) + _M_rightmost() = __z; + } + _S_parent(__z) = __y; + _S_left(__z) = 0; + _S_right(__z) = 0; + _Rb_tree_rebalance(__z, _M_header->_M_parent); + ++_M_node_count; + return iterator(__z); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + insert_equal(const _Val& __v) + { + _Link_type __y = _M_header; + _Link_type __x = _M_root(); + while (__x != 0) + { + __y = __x; + __x = _M_key_compare(_KeyOfValue()(__v), _S_key(__x)) ? + _S_left(__x) : _S_right(__x); + } + return _M_insert(__x, __y, __v); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + pair<typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator, + bool> + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + insert_unique(const _Val& __v) + { + _Link_type __y = _M_header; + _Link_type __x = _M_root(); + bool __comp = true; + while (__x != 0) + { + __y = __x; + __comp = _M_key_compare(_KeyOfValue()(__v), _S_key(__x)); + __x = __comp ? _S_left(__x) : _S_right(__x); + } + iterator __j = iterator(__y); + if (__comp) + if (__j == begin()) + return pair<iterator,bool>(_M_insert(__x, __y, __v), true); + else + --__j; + if (_M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v))) + return pair<iterator,bool>(_M_insert(__x, __y, __v), true); + return pair<iterator,bool>(__j, false); + } + + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + insert_unique(iterator __position, const _Val& __v) + { + if (__position._M_node == _M_header->_M_left) + { + // begin() + if (size() > 0 && + _M_key_compare(_KeyOfValue()(__v), _S_key(__position._M_node))) + return _M_insert(__position._M_node, __position._M_node, __v); + // first argument just needs to be non-null + else + return insert_unique(__v).first; + } + else if (__position._M_node == _M_header) + { + // end() + if (_M_key_compare(_S_key(_M_rightmost()), _KeyOfValue()(__v))) + return _M_insert(0, _M_rightmost(), __v); + else + return insert_unique(__v).first; + } + else + { + iterator __before = __position; + --__before; + if (_M_key_compare(_S_key(__before._M_node), _KeyOfValue()(__v)) + && _M_key_compare(_KeyOfValue()(__v),_S_key(__position._M_node))) + { + if (_S_right(__before._M_node) == 0) + return _M_insert(0, __before._M_node, __v); + else + return _M_insert(__position._M_node, __position._M_node, __v); + // first argument just needs to be non-null + } + else + return insert_unique(__v).first; + } } - catch(...) + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + insert_equal(iterator __position, const _Val& __v) + { + if (__position._M_node == _M_header->_M_left) + { + // begin() + if (size() > 0 && + !_M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v))) + return _M_insert(__position._M_node, __position._M_node, __v); + // first argument just needs to be non-null + else + return insert_equal(__v); + } + else if (__position._M_node == _M_header) + { + // end() + if (!_M_key_compare(_KeyOfValue()(__v), _S_key(_M_rightmost()))) + return _M_insert(0, _M_rightmost(), __v); + else + return insert_equal(__v); + } + else + { + iterator __before = __position; + --__before; + if (!_M_key_compare(_KeyOfValue()(__v), _S_key(__before._M_node)) + && !_M_key_compare(_S_key(__position._M_node), + _KeyOfValue()(__v))) + { + if (_S_right(__before._M_node) == 0) + return _M_insert(0, __before._M_node, __v); + else + return _M_insert(__position._M_node, __position._M_node, __v); + // first argument just needs to be non-null + } + else + return insert_equal(__v); + } + } + + template<typename _Key, typename _Val, typename _KoV, + typename _Cmp, typename _Alloc> + template<class _II> + void + _Rb_tree<_Key,_Val,_KoV,_Cmp,_Alloc>:: + insert_equal(_II __first, _II __last) { - _M_put_node(__tmp); - __throw_exception_again; + for ( ; __first != __last; ++__first) + insert_equal(*__first); } - return __tmp; - } - _Link_type _M_clone_node(_Link_type __x) - { - _Link_type __tmp = _M_create_node(__x->_M_value_field); - __tmp->_M_color = __x->_M_color; - __tmp->_M_left = 0; - __tmp->_M_right = 0; - return __tmp; - } + template<typename _Key, typename _Val, typename _KoV, + typename _Cmp, typename _Alloc> + template<class _II> + void + _Rb_tree<_Key,_Val,_KoV,_Cmp,_Alloc>:: + insert_unique(_II __first, _II __last) + { + for ( ; __first != __last; ++__first) + insert_unique(*__first); + } - void - destroy_node(_Link_type __p) - { - _Destroy(&__p->_M_value_field); - _M_put_node(__p); - } + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline void + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::erase(iterator __position) + { + _Link_type __y = + (_Link_type) _Rb_tree_rebalance_for_erase(__position._M_node, + _M_header->_M_parent, + _M_header->_M_left, + _M_header->_M_right); + destroy_node(__y); + --_M_node_count; + } -protected: - size_type _M_node_count; // keeps track of size of tree - _Compare _M_key_compare; - - _Link_type& _M_root() const - { return (_Link_type&) _M_header->_M_parent; } - _Link_type& _M_leftmost() const - { return (_Link_type&) _M_header->_M_left; } - _Link_type& _M_rightmost() const - { return (_Link_type&) _M_header->_M_right; } - - static _Link_type& _S_left(_Link_type __x) - { return (_Link_type&)(__x->_M_left); } - static _Link_type& _S_right(_Link_type __x) - { return (_Link_type&)(__x->_M_right); } - static _Link_type& _S_parent(_Link_type __x) - { return (_Link_type&)(__x->_M_parent); } - static reference _S_value(_Link_type __x) - { return __x->_M_value_field; } - static const _Key& _S_key(_Link_type __x) - { return _KeyOfValue()(_S_value(__x)); } - static _Color_type& _S_color(_Link_type __x) - { return (_Color_type&)(__x->_M_color); } - - static _Link_type& _S_left(_Base_ptr __x) - { return (_Link_type&)(__x->_M_left); } - static _Link_type& _S_right(_Base_ptr __x) - { return (_Link_type&)(__x->_M_right); } - static _Link_type& _S_parent(_Base_ptr __x) - { return (_Link_type&)(__x->_M_parent); } - static reference _S_value(_Base_ptr __x) - { return ((_Link_type)__x)->_M_value_field; } - static const _Key& _S_key(_Base_ptr __x) - { return _KeyOfValue()(_S_value(_Link_type(__x)));} - static _Color_type& _S_color(_Base_ptr __x) - { return (_Color_type&)(_Link_type(__x)->_M_color); } - - static _Link_type _S_minimum(_Link_type __x) - { return (_Link_type) _Rb_tree_node_base::_S_minimum(__x); } - - static _Link_type _S_maximum(_Link_type __x) - { return (_Link_type) _Rb_tree_node_base::_S_maximum(__x); } - -public: - typedef _Rb_tree_iterator<value_type, reference, pointer> iterator; - typedef _Rb_tree_iterator<value_type, const_reference, const_pointer> - const_iterator; - - typedef reverse_iterator<const_iterator> const_reverse_iterator; - typedef reverse_iterator<iterator> reverse_iterator; - -private: - iterator _M_insert(_Base_ptr __x, _Base_ptr __y, const value_type& __v); - _Link_type _M_copy(_Link_type __x, _Link_type __p); - void _M_erase(_Link_type __x); - -public: - // allocation/deallocation - _Rb_tree() - : _Base(allocator_type()), _M_node_count(0), _M_key_compare() - { _M_empty_initialize(); } - - _Rb_tree(const _Compare& __comp) - : _Base(allocator_type()), _M_node_count(0), _M_key_compare(__comp) - { _M_empty_initialize(); } - - _Rb_tree(const _Compare& __comp, const allocator_type& __a) - : _Base(__a), _M_node_count(0), _M_key_compare(__comp) - { _M_empty_initialize(); } - - _Rb_tree(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x) - : _Base(__x.get_allocator()), - _M_node_count(0), _M_key_compare(__x._M_key_compare) - { - if (__x._M_root() == 0) - _M_empty_initialize(); - else { - _S_color(_M_header) = _S_rb_tree_red; - _M_root() = _M_copy(__x._M_root(), _M_header); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::size_type + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::erase(const _Key& __x) + { + pair<iterator,iterator> __p = equal_range(__x); + size_type __n = distance(__p.first, __p.second); + erase(__p.first, __p.second); + return __n; } - _M_node_count = __x._M_node_count; - } - ~_Rb_tree() { clear(); } - _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& - operator=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x); - -private: - void _M_empty_initialize() { - _S_color(_M_header) = _S_rb_tree_red; // used to distinguish header from - // __root, in iterator.operator++ - _M_root() = 0; - _M_leftmost() = _M_header; - _M_rightmost() = _M_header; - } -public: - // accessors: - _Compare key_comp() const { return _M_key_compare; } - iterator begin() { return _M_leftmost(); } - const_iterator begin() const { return _M_leftmost(); } - iterator end() { return _M_header; } - const_iterator end() const { return _M_header; } - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - bool empty() const { return _M_node_count == 0; } - size_type size() const { return _M_node_count; } - size_type max_size() const { return size_type(-1); } - - void swap(_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __t) { - std::swap(_M_header, __t._M_header); - std::swap(_M_node_count, __t._M_node_count); - std::swap(_M_key_compare, __t._M_key_compare); - } - -public: - // insert/erase - pair<iterator,bool> insert_unique(const value_type& __x); - iterator insert_equal(const value_type& __x); - - iterator insert_unique(iterator __position, const value_type& __x); - iterator insert_equal(iterator __position, const value_type& __x); - - template <class _InputIterator> - void insert_unique(_InputIterator __first, _InputIterator __last); - template <class _InputIterator> - void insert_equal(_InputIterator __first, _InputIterator __last); - - void erase(iterator __position); - size_type erase(const key_type& __x); - void erase(iterator __first, iterator __last); - void erase(const key_type* __first, const key_type* __last); - void clear() { - if (_M_node_count != 0) { - _M_erase(_M_root()); - _M_leftmost() = _M_header; - _M_root() = 0; - _M_rightmost() = _M_header; - _M_node_count = 0; + template<typename _Key, typename _Val, typename _KoV, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type + _Rb_tree<_Key,_Val,_KoV,_Compare,_Alloc>:: + _M_copy(_Link_type __x, _Link_type __p) + { + // Structural copy. __x and __p must be non-null. + _Link_type __top = _M_clone_node(__x); + __top->_M_parent = __p; + + try + { + if (__x->_M_right) + __top->_M_right = _M_copy(_S_right(__x), __top); + __p = __top; + __x = _S_left(__x); + + while (__x != 0) + { + _Link_type __y = _M_clone_node(__x); + __p->_M_left = __y; + __y->_M_parent = __p; + if (__x->_M_right) + __y->_M_right = _M_copy(_S_right(__x), __y); + __p = __y; + __x = _S_left(__x); + } + } + catch(...) + { + _M_erase(__top); + __throw_exception_again; + } + return __top; } - } - -public: - // set operations: - iterator find(const key_type& __x); - const_iterator find(const key_type& __x) const; - size_type count(const key_type& __x) const; - iterator lower_bound(const key_type& __x); - const_iterator lower_bound(const key_type& __x) const; - iterator upper_bound(const key_type& __x); - const_iterator upper_bound(const key_type& __x) const; - pair<iterator,iterator> equal_range(const key_type& __x); - pair<const_iterator, const_iterator> equal_range(const key_type& __x) const; - -public: - // Debugging. - bool __rb_verify() const; -}; - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator==(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) -{ - return __x.size() == __y.size() && - equal(__x.begin(), __x.end(), __y.begin()); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator<(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) -{ - return lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator!=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) { - return !(__x == __y); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator>(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) { - return __y < __x; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator<=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) { - return !(__y < __x); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline bool -operator>=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) { - return !(__x < __y); -} - - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline void -swap(_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x, - _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __y) -{ - __x.swap(__y); -} - - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::operator=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x) -{ - if (this != &__x) { - // Note that _Key may be a constant type. - clear(); - _M_node_count = 0; - _M_key_compare = __x._M_key_compare; - if (__x._M_root() == 0) { - _M_root() = 0; - _M_leftmost() = _M_header; - _M_rightmost() = _M_header; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + void + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::_M_erase(_Link_type __x) + { + // Erase without rebalancing. + while (__x != 0) + { + _M_erase(_S_right(__x)); + _Link_type __y = _S_left(__x); + destroy_node(__x); + __x = __y; + } } - else { - _M_root() = _M_copy(__x._M_root(), _M_header); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_node_count = __x._M_node_count; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + void + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + erase(iterator __first, iterator __last) + { + if (__first == begin() && __last == end()) + clear(); + else + while (__first != __last) erase(__first++); } - } - return *this; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::_M_insert(_Base_ptr __x_, _Base_ptr __y_, const _Value& __v) -{ - _Link_type __x = (_Link_type) __x_; - _Link_type __y = (_Link_type) __y_; - _Link_type __z; - - if (__y == _M_header || __x != 0 || - _M_key_compare(_KeyOfValue()(__v), _S_key(__y))) { - __z = _M_create_node(__v); - _S_left(__y) = __z; // also makes _M_leftmost() = __z - // when __y == _M_header - if (__y == _M_header) { - _M_root() = __z; - _M_rightmost() = __z; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + void + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + erase(const _Key* __first, const _Key* __last) + { + while (__first != __last) + erase(*__first++); } - else if (__y == _M_leftmost()) - _M_leftmost() = __z; // maintain _M_leftmost() pointing to min node - } - else { - __z = _M_create_node(__v); - _S_right(__y) = __z; - if (__y == _M_rightmost()) - _M_rightmost() = __z; // maintain _M_rightmost() pointing to max node - } - _S_parent(__z) = __y; - _S_left(__z) = 0; - _S_right(__z) = 0; - _Rb_tree_rebalance(__z, _M_header->_M_parent); - ++_M_node_count; - return iterator(__z); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::insert_equal(const _Value& __v) -{ - _Link_type __y = _M_header; - _Link_type __x = _M_root(); - while (__x != 0) { - __y = __x; - __x = _M_key_compare(_KeyOfValue()(__v), _S_key(__x)) ? - _S_left(__x) : _S_right(__x); - } - return _M_insert(__x, __y, __v); -} - - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -pair<typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator, - bool> -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::insert_unique(const _Value& __v) -{ - _Link_type __y = _M_header; - _Link_type __x = _M_root(); - bool __comp = true; - while (__x != 0) { - __y = __x; - __comp = _M_key_compare(_KeyOfValue()(__v), _S_key(__x)); - __x = __comp ? _S_left(__x) : _S_right(__x); - } - iterator __j = iterator(__y); - if (__comp) - if (__j == begin()) - return pair<iterator,bool>(_M_insert(__x, __y, __v), true); - else - --__j; - if (_M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v))) - return pair<iterator,bool>(_M_insert(__x, __y, __v), true); - return pair<iterator,bool>(__j, false); -} - - -template <class _Key, class _Val, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator -_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc> - ::insert_unique(iterator __position, const _Val& __v) -{ - if (__position._M_node == _M_header->_M_left) { // begin() - if (size() > 0 && - _M_key_compare(_KeyOfValue()(__v), _S_key(__position._M_node))) - return _M_insert(__position._M_node, __position._M_node, __v); - // first argument just needs to be non-null - else - return insert_unique(__v).first; - } else if (__position._M_node == _M_header) { // end() - if (_M_key_compare(_S_key(_M_rightmost()), _KeyOfValue()(__v))) - return _M_insert(0, _M_rightmost(), __v); - else - return insert_unique(__v).first; - } else { - iterator __before = __position; - --__before; - if (_M_key_compare(_S_key(__before._M_node), _KeyOfValue()(__v)) - && _M_key_compare(_KeyOfValue()(__v), _S_key(__position._M_node))) { - if (_S_right(__before._M_node) == 0) - return _M_insert(0, __before._M_node, __v); - else - return _M_insert(__position._M_node, __position._M_node, __v); - // first argument just needs to be non-null - } else - return insert_unique(__v).first; - } -} - -template <class _Key, class _Val, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc> - ::insert_equal(iterator __position, const _Val& __v) -{ - if (__position._M_node == _M_header->_M_left) { // begin() - if (size() > 0 && - !_M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v))) - return _M_insert(__position._M_node, __position._M_node, __v); - // first argument just needs to be non-null - else - return insert_equal(__v); - } else if (__position._M_node == _M_header) {// end() - if (!_M_key_compare(_KeyOfValue()(__v), _S_key(_M_rightmost()))) - return _M_insert(0, _M_rightmost(), __v); - else - return insert_equal(__v); - } else { - iterator __before = __position; - --__before; - if (!_M_key_compare(_KeyOfValue()(__v), _S_key(__before._M_node)) - && !_M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v))) { - if (_S_right(__before._M_node) == 0) - return _M_insert(0, __before._M_node, __v); - else - return _M_insert(__position._M_node, __position._M_node, __v); - // first argument just needs to be non-null - } else - return insert_equal(__v); - } -} - -template <class _Key, class _Val, class _KoV, class _Cmp, class _Alloc> - template<class _II> -void _Rb_tree<_Key,_Val,_KoV,_Cmp,_Alloc> - ::insert_equal(_II __first, _II __last) -{ - for ( ; __first != __last; ++__first) - insert_equal(*__first); -} - -template <class _Key, class _Val, class _KoV, class _Cmp, class _Alloc> - template<class _II> -void _Rb_tree<_Key,_Val,_KoV,_Cmp,_Alloc> - ::insert_unique(_II __first, _II __last) { - for ( ; __first != __last; ++__first) - insert_unique(*__first); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline void _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::erase(iterator __position) -{ - _Link_type __y = - (_Link_type) _Rb_tree_rebalance_for_erase(__position._M_node, - _M_header->_M_parent, - _M_header->_M_left, - _M_header->_M_right); - destroy_node(__y); - --_M_node_count; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::size_type -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::erase(const _Key& __x) -{ - pair<iterator,iterator> __p = equal_range(__x); - size_type __n = distance(__p.first, __p.second); - erase(__p.first, __p.second); - return __n; -} - -template <class _Key, class _Val, class _KoV, class _Compare, class _Alloc> -typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type -_Rb_tree<_Key,_Val,_KoV,_Compare,_Alloc> - ::_M_copy(_Link_type __x, _Link_type __p) -{ - // structural copy. __x and __p must be non-null. - _Link_type __top = _M_clone_node(__x); - __top->_M_parent = __p; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::find(const _Key& __k) + { + _Link_type __y = _M_header; // Last node which is not less than __k. + _Link_type __x = _M_root(); // Current node. + + while (__x != 0) + if (!_M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + + iterator __j = iterator(__y); + return (__j == end() || _M_key_compare(__k, _S_key(__j._M_node))) ? + end() : __j; + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::const_iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + find(const _Key& __k) const + { + _Link_type __y = _M_header; // Last node which is not less than __k. + _Link_type __x = _M_root(); // Current node. - try { - if (__x->_M_right) - __top->_M_right = _M_copy(_S_right(__x), __top); - __p = __top; - __x = _S_left(__x); - - while (__x != 0) { - _Link_type __y = _M_clone_node(__x); - __p->_M_left = __y; - __y->_M_parent = __p; - if (__x->_M_right) - __y->_M_right = _M_copy(_S_right(__x), __y); - __p = __y; - __x = _S_left(__x); + while (__x != 0) + { + if (!_M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + } + const_iterator __j = const_iterator(__y); + return (__j == end() || _M_key_compare(__k, _S_key(__j._M_node))) ? + end() : __j; } - } - catch(...) + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::size_type + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + count(const _Key& __k) const { - _M_erase(__top); - __throw_exception_again; + pair<const_iterator, const_iterator> __p = equal_range(__k); + size_type __n = distance(__p.first, __p.second); + return __n; } - return __top; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -void _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::_M_erase(_Link_type __x) -{ - // erase without rebalancing - while (__x != 0) { - _M_erase(_S_right(__x)); - _Link_type __y = _S_left(__x); - destroy_node(__x); - __x = __y; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + lower_bound(const _Key& __k) + { + _Link_type __y = _M_header; /* Last node which is not less than __k. */ + _Link_type __x = _M_root(); /* Current node. */ + + while (__x != 0) + if (!_M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + + return iterator(__y); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::const_iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + lower_bound(const _Key& __k) const + { + _Link_type __y = _M_header; /* Last node which is not less than __k. */ + _Link_type __x = _M_root(); /* Current node. */ + + while (__x != 0) + if (!_M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + + return const_iterator(__y); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + upper_bound(const _Key& __k) + { + _Link_type __y = _M_header; /* Last node which is greater than __k. */ + _Link_type __x = _M_root(); /* Current node. */ + + while (__x != 0) + if (_M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + + return iterator(__y); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::const_iterator + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + upper_bound(const _Key& __k) const + { + _Link_type __y = _M_header; /* Last node which is greater than __k. */ + _Link_type __x = _M_root(); /* Current node. */ + + while (__x != 0) + if (_M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + + return const_iterator(__y); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline + pair<typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator, + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator> + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: + equal_range(const _Key& __k) + { return pair<iterator, iterator>(lower_bound(__k), upper_bound(__k)); } + + template<typename _Key, typename _Val, typename _KoV, + typename _Compare, typename _Alloc> + inline + pair<typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::const_iterator, + typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::const_iterator> + _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc> + ::equal_range(const _Key& __k) const + { + return pair<const_iterator,const_iterator>(lower_bound(__k), + upper_bound(__k)); } -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -void _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::erase(iterator __first, iterator __last) -{ - if (__first == begin() && __last == end()) - clear(); - else - while (__first != __last) erase(__first++); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -void _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::erase(const _Key* __first, const _Key* __last) -{ - while (__first != __last) erase(*__first++); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::find(const _Key& __k) -{ - _Link_type __y = _M_header; // Last node which is not less than __k. - _Link_type __x = _M_root(); // Current node. - - while (__x != 0) - if (!_M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - - iterator __j = iterator(__y); - return (__j == end() || _M_key_compare(__k, _S_key(__j._M_node))) ? - end() : __j; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::const_iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::find(const _Key& __k) const -{ - _Link_type __y = _M_header; /* Last node which is not less than __k. */ - _Link_type __x = _M_root(); /* Current node. */ - - while (__x != 0) { - if (!_M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); + + inline int + __black_count(_Rb_tree_node_base* __node, _Rb_tree_node_base* __root) + { + if (__node == 0) + return 0; + int __sum = 0; + do + { + if (__node->_M_color == _M_black) + ++__sum; + if (__node == __root) + break; + __node = __node->_M_parent; + } + while (1); + return __sum; } - const_iterator __j = const_iterator(__y); - return (__j == end() || _M_key_compare(__k, _S_key(__j._M_node))) ? - end() : __j; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::size_type -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::count(const _Key& __k) const -{ - pair<const_iterator, const_iterator> __p = equal_range(__k); - size_type __n = distance(__p.first, __p.second); - return __n; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::lower_bound(const _Key& __k) -{ - _Link_type __y = _M_header; /* Last node which is not less than __k. */ - _Link_type __x = _M_root(); /* Current node. */ - - while (__x != 0) - if (!_M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - - return iterator(__y); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::const_iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::lower_bound(const _Key& __k) const -{ - _Link_type __y = _M_header; /* Last node which is not less than __k. */ - _Link_type __x = _M_root(); /* Current node. */ - - while (__x != 0) - if (!_M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - - return const_iterator(__y); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::upper_bound(const _Key& __k) -{ - _Link_type __y = _M_header; /* Last node which is greater than __k. */ - _Link_type __x = _M_root(); /* Current node. */ - - while (__x != 0) - if (_M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - - return iterator(__y); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::const_iterator -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::upper_bound(const _Key& __k) const -{ - _Link_type __y = _M_header; /* Last node which is greater than __k. */ - _Link_type __x = _M_root(); /* Current node. */ - - while (__x != 0) - if (_M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - - return const_iterator(__y); -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -inline -pair<typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator, - typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator> -_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> - ::equal_range(const _Key& __k) -{ - return pair<iterator, iterator>(lower_bound(__k), upper_bound(__k)); -} - -template <class _Key, class _Value, class _KoV, class _Compare, class _Alloc> -inline -pair<typename _Rb_tree<_Key, _Value, _KoV, _Compare, _Alloc>::const_iterator, - typename _Rb_tree<_Key, _Value, _KoV, _Compare, _Alloc>::const_iterator> -_Rb_tree<_Key, _Value, _KoV, _Compare, _Alloc> - ::equal_range(const _Key& __k) const -{ - return pair<const_iterator,const_iterator>(lower_bound(__k), - upper_bound(__k)); -} - -inline int -__black_count(_Rb_tree_node_base* __node, _Rb_tree_node_base* __root) -{ - if (__node == 0) - return 0; - int __sum = 0; - do { - if (__node->_M_color == _S_rb_tree_black) - ++__sum; - if (__node == __root) - break; - __node = __node->_M_parent; - } while (1); - return __sum; -} - -template <class _Key, class _Value, class _KeyOfValue, - class _Compare, class _Alloc> -bool _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const -{ - if (_M_node_count == 0 || begin() == end()) - return _M_node_count == 0 && begin() == end() && - _M_header->_M_left == _M_header && _M_header->_M_right == _M_header; + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + bool + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const + { + if (_M_node_count == 0 || begin() == end()) + return _M_node_count == 0 && begin() == end() && + _M_header->_M_left == _M_header && _M_header->_M_right == _M_header; - int __len = __black_count(_M_leftmost(), _M_root()); - for (const_iterator __it = begin(); __it != end(); ++__it) { - _Link_type __x = (_Link_type) __it._M_node; - _Link_type __L = _S_left(__x); - _Link_type __R = _S_right(__x); - - if (__x->_M_color == _S_rb_tree_red) - if ((__L && __L->_M_color == _S_rb_tree_red) || - (__R && __R->_M_color == _S_rb_tree_red)) - return false; - - if (__L && _M_key_compare(_S_key(__x), _S_key(__L))) - return false; - if (__R && _M_key_compare(_S_key(__R), _S_key(__x))) + int __len = __black_count(_M_leftmost(), _M_root()); + for (const_iterator __it = begin(); __it != end(); ++__it) + { + _Link_type __x = (_Link_type) __it._M_node; + _Link_type __L = _S_left(__x); + _Link_type __R = _S_right(__x); + + if (__x->_M_color == _M_red) + if ((__L && __L->_M_color == _M_red) + || (__R && __R->_M_color == _M_red)) + return false; + + if (__L && _M_key_compare(_S_key(__x), _S_key(__L))) + return false; + if (__R && _M_key_compare(_S_key(__R), _S_key(__x))) + return false; + + if (!__L && !__R && __black_count(__x, _M_root()) != __len) + return false; + } + + if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) return false; - - if (!__L && !__R && __black_count(__x, _M_root()) != __len) + if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) return false; - } - - if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) - return false; - if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) - return false; - - return true; -} - + return true; + } } // namespace std -#endif /* __GLIBCPP_INTERNAL_TREE_H */ - -// Local Variables: -// mode:C++ -// End: +#endif diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 866b20bf37e..b5f7b8c40b6 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -107,7 +107,7 @@ namespace std inline _ForwardIter uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result) { - typedef typename iterator_traits<_InputIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; typedef typename __type_traits<_ValueType>::is_POD_type _Is_POD; return __uninitialized_copy_aux(__first, __last, __result, _Is_POD()); } diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 4d8e7513e9f..ef3b1c26e74 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1,6 +1,6 @@ // Vector implementation -*- C++ -*- -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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 @@ -148,6 +148,15 @@ struct _Vector_base * @brief A standard container which offers fixed time access to individual * elements in any order. * + * @ingroup Containers + * @ingroup Sequences + * + * Meets the requirements of a <a href="tables.html#65">container</a>, a + * <a href="tables.html#66">reversible container</a>, and a + * <a href="tables.html#67">sequence</a>, including the + * <a href="tables.html#68">optional sequence requirements</a> with the + * %exception of @c push_front and @c pop_front. + * * In some terminology a vector can be described as a dynamic C-style array, * it offers fast and efficient access to individual elements in any order * and saves the user from worrying about memory and size allocation. @@ -166,8 +175,9 @@ public: typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef __normal_iterator<pointer, vector_type> iterator; - typedef __normal_iterator<const_pointer, vector_type> const_iterator; + typedef __gnu_cxx::__normal_iterator<pointer, vector_type> iterator; + typedef __gnu_cxx::__normal_iterator<const_pointer, vector_type> + const_iterator; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; @@ -381,7 +391,9 @@ public: * reallocation of memory and copy of vector data. */ void reserve(size_type __n) { - if (capacity() < __n) { + if (__n > this->max_size()) + __throw_length_error("vector::reserve"); + if (this->capacity() < __n) { const size_type __old_size = size(); pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); _Destroy(_M_start, _M_finish); @@ -413,32 +425,34 @@ public: template<class _InputIterator> void - assign(_InputIterator __first, _InputIterator __last) - { + assign(_InputIterator __first, _InputIterator __last) + { typedef typename _Is_integer<_InputIterator>::_Integral _Integral; _M_assign_dispatch(__first, __last, _Integral()); } template<class _Integer> void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign((size_type) __n, (_Tp) __val); } + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign((size_type) __n, (_Tp) __val); } template<class _InputIter> void - _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) + _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) { - typedef typename iterator_traits<_InputIter>::iterator_category _IterCategory; - _M_assign_aux(__first, __last, _IterCategory()); - } + typedef typename iterator_traits<_InputIter>::iterator_category _IterCategory; + _M_assign_aux(__first, __last, _IterCategory()); + } template <class _InputIterator> - void _M_assign_aux(_InputIterator __first, _InputIterator __last, - input_iterator_tag); + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + input_iterator_tag); template <class _ForwardIterator> - void _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag); + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); /** * Returns a read/write reference to the data at the first element of the @@ -484,9 +498,13 @@ public: _M_insert_aux(end(), __x); } +#ifdef _GLIBCPP_DEPRECATED /** * Add an element to the end of the vector. The element is * default-constructed. + * + * @note You must define _GLIBCPP_DEPRECATED to make this visible; see + * c++config.h. */ void push_back() @@ -498,6 +516,7 @@ public: else _M_insert_aux(end()); } +#endif void swap(vector<_Tp, _Alloc>& __x) diff --git a/libstdc++-v3/include/bits/streambuf.tcc b/libstdc++-v3/include/bits/streambuf.tcc index dc7921527d9..5f57df583a7 100644 --- a/libstdc++-v3/include/bits/streambuf.tcc +++ b/libstdc++-v3/include/bits/streambuf.tcc @@ -40,6 +40,10 @@ namespace std { template<typename _CharT, typename _Traits> + const size_t + basic_streambuf<_CharT, _Traits>::_S_pback_size; + + template<typename _CharT, typename _Traits> typename basic_streambuf<_CharT, _Traits>::int_type basic_streambuf<_CharT, _Traits>:: sbumpc() @@ -47,7 +51,7 @@ namespace std int_type __ret; if (_M_in_cur && _M_in_cur < _M_in_end) { - char_type __c = *gptr(); + char_type __c = *(this->gptr()); _M_in_cur_move(1); __ret = traits_type::to_int_type(__c); } @@ -65,7 +69,7 @@ namespace std bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur; bool __testne = _M_in_cur && !traits_type::eq(__c, this->gptr()[-1]); if (!__testpos || __testne) - __ret = pbackfail(traits_type::to_int_type(__c)); + __ret = this->pbackfail(traits_type::to_int_type(__c)); else { _M_in_cur_move(-1); @@ -134,7 +138,7 @@ namespace std if (__ret < __n) { int_type __c = this->uflow(); - if (__c != traits_type::eof()) + if (!traits_type::eq_int_type(__c, traits_type::eof())) { traits_type::assign(*__s++, traits_type::to_char_type(__c)); ++__ret; @@ -173,7 +177,7 @@ namespace std if (__ret < __n) { int_type __c = this->overflow(traits_type::to_int_type(*__s)); - if (__c != traits_type::eof()) + if (!traits_type::eq_int_type(__c, traits_type::eof())) { ++__ret; ++__s; @@ -204,19 +208,32 @@ namespace std try { while (__testput && __bufsize != -1) - { - __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize); - __ret += __xtrct; - __sbin->_M_in_cur_move(__xtrct); - if (__xtrct == __bufsize) + { + if (__bufsize != 0 && __sbin->gptr() != NULL + && __sbin->gptr() + __bufsize <= __sbin->egptr()) { - if (__sbin->sgetc() == _Traits::eof()) + __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize); + __ret += __xtrct; + __sbin->_M_in_cur_move(__xtrct); + if (__xtrct != __bufsize) break; - __bufsize = __sbin->in_avail(); } - else - break; - } + else + { + size_t __size = + __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1; + _CharT* __buf = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __size)); + streamsize __charsread = __sbin->sgetn(__buf, __size); + __xtrct = __sbout->sputn(__buf, __charsread); + __ret += __xtrct; + if (__xtrct != __charsread) + break; + } + if (_Traits::eq_int_type(__sbin->sgetc(), _Traits::eof())) + break; + __bufsize = __sbin->in_avail(); + } } catch(exception& __fail) { @@ -236,11 +253,13 @@ namespace std __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*, basic_streambuf<char>*); +#ifdef _GLIBCPP_USE_WCHAR_T extern template class basic_streambuf<wchar_t>; extern template streamsize __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*, basic_streambuf<wchar_t>*); +#endif } // namespace std #endif diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 88ae25eab18..152df9c6e4b 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -1,6 +1,7 @@ // Streambuf iterators -// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// 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 @@ -41,60 +42,6 @@ namespace std { - template<typename _CharT, typename _Traits> - class ostreambuf_iterator - : public iterator<output_iterator_tag, void, void, void, void> - { - public: - // Types: - typedef _CharT char_type; - typedef _Traits traits_type; - typedef basic_streambuf<_CharT, _Traits> streambuf_type; - typedef basic_ostream<_CharT, _Traits> ostream_type; - - private: - streambuf_type* _M_sbuf; - bool _M_failed; - - public: - inline - ostreambuf_iterator(ostream_type& __s) throw () - : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } - - ostreambuf_iterator(streambuf_type* __s) throw () - : _M_sbuf(__s), _M_failed(!_M_sbuf) { } - - ostreambuf_iterator& - operator=(_CharT __c); - - ostreambuf_iterator& - operator*() throw() - { return *this; } - - ostreambuf_iterator& - operator++(int) throw() - { return *this; } - - ostreambuf_iterator& - operator++() throw() - { return *this; } - - bool - failed() const throw() - { return _M_failed; } - }; - - template<typename _CharT, typename _Traits> - inline ostreambuf_iterator<_CharT, _Traits>& - ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c) - { - if (!_M_failed && - _Traits::eq_int_type(_M_sbuf->sputc(__c),_Traits::eof())) - _M_failed = true; - return *this; - } - - // 24.5.3 Template class istreambuf_iterator template<typename _CharT, typename _Traits> class istreambuf_iterator @@ -117,76 +64,78 @@ namespace std // the "end of stream" iterator value. // NB: This implementation assumes the "end of stream" value // is EOF, or -1. - streambuf_type* _M_sbuf; + mutable streambuf_type* _M_sbuf; int_type _M_c; public: istreambuf_iterator() throw() - : _M_sbuf(NULL), _M_c(-2) { } + : _M_sbuf(0), _M_c(traits_type::eof()) { } istreambuf_iterator(istream_type& __s) throw() - : _M_sbuf(__s.rdbuf()), _M_c(-2) { } + : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { } istreambuf_iterator(streambuf_type* __s) throw() - : _M_sbuf(__s), _M_c(-2) { } + : _M_sbuf(__s), _M_c(traits_type::eof()) { } - // NB: This should really have an int_type return - // value, so "end of stream" postion can be checked without - // hacking. + // NB: The result of operator*() on an end of stream is undefined. char_type operator*() const - { - // The result of operator*() on an end of stream is undefined. - char_type __ret; - if (_M_sbuf && _M_c != static_cast<int_type>(-2)) - __ret = _M_c; - else if (_M_sbuf) - __ret = traits_type::to_char_type(_M_sbuf->sgetc()); - else - __ret = static_cast<char_type>(traits_type::eof()); - return __ret; - } + { return traits_type::to_char_type(_M_get()); } istreambuf_iterator& operator++() { - if (_M_sbuf) - _M_sbuf->sbumpc(); - _M_c = -2; + const int_type __eof = traits_type::eof(); + if (_M_sbuf && traits_type::eq_int_type(_M_sbuf->sbumpc(), __eof)) + _M_sbuf = 0; + else + _M_c = __eof; return *this; } istreambuf_iterator operator++(int) { + const int_type __eof = traits_type::eof(); istreambuf_iterator __old = *this; - if (_M_sbuf) - __old._M_c = _M_sbuf->sbumpc(); - _M_c = -2; + if (_M_sbuf + && traits_type::eq_int_type((__old._M_c = _M_sbuf->sbumpc()), + __eof)) + _M_sbuf = 0; + else + _M_c = __eof; return __old; } - bool - equal(const istreambuf_iterator& __b) - { - int_type __eof = traits_type::eof(); - bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; - bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof; - return (__thiseof && __beof || (!__thiseof && !__beof)); - } - #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 110 istreambuf_iterator::equal not const // NB: there is also number 111 (NAD, Future) pending on this function. bool equal(const istreambuf_iterator& __b) const { - int_type __eof = traits_type::eof(); - bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; - bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof; + const int_type __eof = traits_type::eof(); + bool __thiseof = traits_type::eq_int_type(_M_get(), __eof); + bool __beof = traits_type::eq_int_type(__b._M_get(), __eof); return (__thiseof && __beof || (!__thiseof && !__beof)); } #endif + + private: + int_type + _M_get() const + { + const int_type __eof = traits_type::eof(); + int_type __ret = __eof; + if (_M_sbuf) + { + if (!traits_type::eq_int_type(_M_c, __eof)) + __ret = _M_c; + else + if (traits_type::eq_int_type((__ret = _M_sbuf->sgetc()), __eof)) + _M_sbuf = 0; + } + return __ret; + } }; template<typename _CharT, typename _Traits> @@ -200,5 +149,58 @@ namespace std operator!=(const istreambuf_iterator<_CharT, _Traits>& __a, const istreambuf_iterator<_CharT, _Traits>& __b) { return !__a.equal(__b); } + + template<typename _CharT, typename _Traits> + class ostreambuf_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + public: + // Types: + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_streambuf<_CharT, _Traits> streambuf_type; + typedef basic_ostream<_CharT, _Traits> ostream_type; + + private: + streambuf_type* _M_sbuf; + bool _M_failed; + + public: + inline + ostreambuf_iterator(ostream_type& __s) throw () + : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } + + ostreambuf_iterator(streambuf_type* __s) throw () + : _M_sbuf(__s), _M_failed(!_M_sbuf) { } + + ostreambuf_iterator& + operator=(_CharT __c); + + ostreambuf_iterator& + operator*() throw() + { return *this; } + + ostreambuf_iterator& + operator++(int) throw() + { return *this; } + + ostreambuf_iterator& + operator++() throw() + { return *this; } + + bool + failed() const throw() + { return _M_failed; } + }; + + template<typename _CharT, typename _Traits> + inline ostreambuf_iterator<_CharT, _Traits>& + ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c) + { + if (!_M_failed && + _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof())) + _M_failed = true; + return *this; + } } // namespace std #endif diff --git a/libstdc++-v3/include/bits/stringfwd.h b/libstdc++-v3/include/bits/stringfwd.h index b7418a67a7e..db40befdab6 100644 --- a/libstdc++-v3/include/bits/stringfwd.h +++ b/libstdc++-v3/include/bits/stringfwd.h @@ -45,23 +45,25 @@ namespace std { - template<class _CharT> - struct char_traits; - - template<> struct char_traits<char>; -#ifdef _GLIBCPP_USE_WCHAR_T - template<> struct char_traits<wchar_t>; -#endif - template<typename _Alloc> class allocator; + template<class _CharT> + struct char_traits; + template<typename _CharT, typename _Traits = char_traits<_CharT>, typename _Alloc = allocator<_CharT> > class basic_string; + + template<> struct char_traits<char>; typedef basic_string<char> string; + +#ifdef _GLIBCPP_USE_WCHAR_T + template<> struct char_traits<wchar_t>; + typedef basic_string<wchar_t> wstring; +#endif } // namespace std #endif // _CPP_BITS_STRINGFWD_H diff --git a/libstdc++-v3/include/bits/type_traits.h b/libstdc++-v3/include/bits/type_traits.h index 89e50f39a3f..61bc4369275 100644 --- a/libstdc++-v3/include/bits/type_traits.h +++ b/libstdc++-v3/include/bits/type_traits.h @@ -322,13 +322,13 @@ template<typename _Tp> struct _Is_normal_iterator { }; // Forward declaration hack, should really include this from somewhere. -namespace std +namespace __gnu_cxx { template<typename _Iterator, typename _Container> class __normal_iterator; } template<typename _Iterator, typename _Container> -struct _Is_normal_iterator< std::__normal_iterator<_Iterator, _Container> > { +struct _Is_normal_iterator< __gnu_cxx::__normal_iterator<_Iterator, _Container> > { typedef __true_type _Normal; }; |