diff options
Diffstat (limited to 'contrib/libstdc++/include/bits')
64 files changed, 34590 insertions, 0 deletions
diff --git a/contrib/libstdc++/include/bits/basic_ios.h b/contrib/libstdc++/include/bits/basic_ios.h new file mode 100644 index 0000000000000..13ad0f82e9906 --- /dev/null +++ b/contrib/libstdc++/include/bits/basic_ios.h @@ -0,0 +1,210 @@ +// Iostreams base classes -*- C++ -*- + +// Copyright (C) 1997, 1998, 1999, 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file basic_ios.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_BASICIOS_H +#define _CPP_BITS_BASICIOS_H 1 + +#pragma GCC system_header + +#include <bits/streambuf_iterator.h> +#include <bits/locale_facets.h> + +namespace std +{ + // 27.4.5 Template class basic_ios + template<typename _CharT, typename _Traits> + class basic_ios : public ios_base + { + public: + // Types: + typedef _CharT char_type; + typedef typename _Traits::int_type int_type; + typedef typename _Traits::pos_type pos_type; + typedef typename _Traits::off_type off_type; + typedef _Traits traits_type; + + // Non-standard Types: + typedef ctype<_CharT> __ctype_type; + typedef ostreambuf_iterator<_CharT, _Traits> __ostreambuf_iter; + typedef num_put<_CharT, __ostreambuf_iter> __numput_type; + typedef istreambuf_iterator<_CharT, _Traits> __istreambuf_iter; + typedef num_get<_CharT, __istreambuf_iter> __numget_type; + + // Data members: + protected: + basic_ostream<_CharT, _Traits>* _M_tie; + mutable char_type _M_fill; + mutable bool _M_fill_init; + basic_streambuf<_CharT, _Traits>* _M_streambuf; + + // Cached use_facet<ctype>, which is based on the current locale info. + const __ctype_type* _M_fctype; + // From ostream. + const __numput_type* _M_fnumput; + // From istream. + const __numget_type* _M_fnumget; + + public: + operator void*() const + { return this->fail() ? 0 : const_cast<basic_ios*>(this); } + + bool + operator!() const + { return this->fail(); } + + iostate + rdstate() const + { return _M_streambuf_state; } + + void + clear(iostate __state = goodbit); + + void + setstate(iostate __state) + { this->clear(this->rdstate() | __state); } + + bool + good() const + { return this->rdstate() == 0; } + + bool + eof() const + { return (this->rdstate() & eofbit) != 0; } + + bool + fail() const + { return (this->rdstate() & (badbit | failbit)) != 0; } + + bool + bad() const + { return (this->rdstate() & badbit) != 0; } + + iostate + exceptions() const + { return _M_exception; } + + void + exceptions(iostate __except) + { + _M_exception = __except; + this->clear(_M_streambuf_state); + } + + // Constructor/destructor: + explicit + basic_ios(basic_streambuf<_CharT, _Traits>* __sb) : ios_base() + { this->init(__sb); } + + virtual + ~basic_ios() { } + + // Members: + basic_ostream<_CharT, _Traits>* + tie() const + { return _M_tie; } + + basic_ostream<_CharT, _Traits>* + tie(basic_ostream<_CharT, _Traits>* __tiestr) + { + basic_ostream<_CharT, _Traits>* __old = _M_tie; + _M_tie = __tiestr; + return __old; + } + + basic_streambuf<_CharT, _Traits>* + rdbuf() const + { return _M_streambuf; } + + basic_streambuf<_CharT, _Traits>* + rdbuf(basic_streambuf<_CharT, _Traits>* __sb); + + basic_ios& + copyfmt(const basic_ios& __rhs); + + char_type + fill() const + { + if (!_M_fill_init) + { + _M_fill = this->widen(' '); + _M_fill_init = true; + } + return _M_fill; + } + + char_type + fill(char_type __ch) + { + char_type __old = this->fill(); + _M_fill = __ch; + return __old; + } + + // Locales: + locale + imbue(const locale& __loc); + + char + narrow(char_type __c, char __dfault) const; + + char_type + widen(char __c) const; + + protected: + // 27.4.5.1 basic_ios constructors + basic_ios() : ios_base() + { } + + void + init(basic_streambuf<_CharT, _Traits>* __sb); + + bool + _M_check_facet(const locale::facet* __f) const + { + if (!__f) + __throw_bad_cast(); + return true; + } + + void + _M_cache_facets(const locale& __loc); + }; +} // namespace std + +#ifdef _GLIBCPP_NO_TEMPLATE_EXPORT +# define export +#include <bits/basic_ios.tcc> +#endif + +#endif /* _CPP_BITS_BASICIOS_H */ diff --git a/contrib/libstdc++/include/bits/basic_ios.tcc b/contrib/libstdc++/include/bits/basic_ios.tcc new file mode 100644 index 0000000000000..1e345dc211720 --- /dev/null +++ b/contrib/libstdc++/include/bits/basic_ios.tcc @@ -0,0 +1,193 @@ +// basic_ios locale and locale-related member functions -*- C++ -*- + +// Copyright (C) 1999, 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef _CPP_BITS_BASICIOS_TCC +#define _CPP_BITS_BASICIOS_TCC 1 + +#pragma GCC system_header + +namespace std +{ + template<typename _CharT, typename _Traits> + void + basic_ios<_CharT, _Traits>::clear(iostate __state) + { + if (this->rdbuf()) + _M_streambuf_state = __state; + else + _M_streambuf_state = __state | badbit; + if ((this->rdstate() & this->exceptions())) + __throw_ios_failure("basic_ios::clear(iostate) caused exception"); + } + + template<typename _CharT, typename _Traits> + basic_streambuf<_CharT, _Traits>* + basic_ios<_CharT, _Traits>::rdbuf(basic_streambuf<_CharT, _Traits>* __sb) + { + basic_streambuf<_CharT, _Traits>* __old = _M_streambuf; + _M_streambuf = __sb; + this->clear(); + return __old; + } + + template<typename _CharT, typename _Traits> + basic_ios<_CharT, _Traits>& + basic_ios<_CharT, _Traits>::copyfmt(const basic_ios& __rhs) + { + // Per 27.1.1.1, do not call imbue, yet must trash all caches + // associated with imbue() + + // Alloc any new word array first, so if it fails we have "rollback". + _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_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_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()); + this->precision(__rhs.precision()); + this->tie(__rhs.tie()); + this->fill(__rhs.fill()); + // The next is required to be the last assignment. + this->exceptions(__rhs.exceptions()); + + _M_call_callbacks(copyfmt_event); + return *this; + } + + template<typename _CharT, typename _Traits> + char + basic_ios<_CharT, _Traits>::narrow(char_type __c, char __dfault) const + { + char __ret = __dfault; + if (_M_check_facet(_M_fctype)) + __ret = _M_fctype->narrow(__c, __dfault); + return __ret; + } + + template<typename _CharT, typename _Traits> + _CharT + basic_ios<_CharT, _Traits>::widen(char __c) const + { + char_type __ret = char_type(); + if (_M_check_facet(_M_fctype)) + __ret = _M_fctype->widen(__c); + return __ret; + } + + // Locales: + template<typename _CharT, typename _Traits> + locale + basic_ios<_CharT, _Traits>::imbue(const locale& __loc) + { + locale __old(this->getloc()); + ios_base::imbue(__loc); + _M_cache_facets(__loc); + if (this->rdbuf() != 0) + this->rdbuf()->pubimbue(__loc); + return __old; + } + + template<typename _CharT, typename _Traits> + void + basic_ios<_CharT, _Traits>::init(basic_streambuf<_CharT, _Traits>* __sb) + { + // NB: This may be called more than once on the same object. + ios_base::_M_init(); + _M_cache_facets(_M_ios_locale); + _M_tie = 0; + + // 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 = 0; + _M_fill_init = false; + + _M_exception = goodbit; + _M_streambuf = __sb; + _M_streambuf_state = __sb ? goodbit : badbit; + } + + template<typename _CharT, typename _Traits> + void + basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc) + { + if (has_facet<__ctype_type>(__loc)) + _M_fctype = &use_facet<__ctype_type>(__loc); + else + _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); + else + _M_fnumput = 0; + if (has_facet<__numget_type>(__loc)) + _M_fnumget = &use_facet<__numget_type>(__loc); + else + _M_fnumget = 0; + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class basic_ios<char>; + extern template class basic_ios<wchar_t>; +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/basic_string.h b/contrib/libstdc++/include/bits/basic_string.h new file mode 100644 index 0000000000000..e05a1c6ef6143 --- /dev/null +++ b/contrib/libstdc++/include/bits/basic_string.h @@ -0,0 +1,1084 @@ +// Components for manipulating sequences of characters -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 21 Strings library +// + +/** @file basic_string.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STRING_H +#define _CPP_BITS_STRING_H 1 + +#pragma GCC system_header + +#include <bits/atomicity.h> + +namespace std +{ + // Documentation? What's that? + // Nathan Myers <ncm@cantrip.org>. + // + // A string looks like this: + // + // [_Rep] + // _M_length + // [basic_string<char_type>] _M_capacity + // _M_dataplus _M_state + // _M_p ----------------> unnamed array of char_type + + // Where the _M_p points to the first character in the string, and + // you cast it to a pointer-to-_Rep and subtract 1 to get a + // pointer to the header. + + // This approach has the enormous advantage that a string object + // requires only one allocation. All the ugliness is confined + // within a single pair of inline functions, which each compile to + // a single "add" instruction: _Rep::_M_data(), and + // string::_M_rep(); and the allocation function which gets a + // block of raw bytes and with room enough and constructs a _Rep + // object at the front. + + // The reason you want _M_data pointing to the character array and + // not the _Rep is so that the debugger can see the string + // contents. (Probably we should add a non-inline member to get + // the _Rep for the debugger to use, so users can check the actual + // string length.) + + // Note that the _Rep object is a POD so that you can have a + // static "empty string" _Rep object already "constructed" before + // static constructors have run. The reference-count encoding is + // chosen so that a 0 indicates one reference, so you never try to + // destroy the empty-string _Rep object. + + // All but the last paragraph is considered pretty conventional + // for a C++ string implementation. + + // 21.3 Template class basic_string + template<typename _CharT, typename _Traits, typename _Alloc> + class basic_string + { + // Types: + public: + typedef _Traits traits_type; + typedef typename _Traits::char_type value_type; + typedef _Alloc allocator_type; + typedef typename _Alloc::size_type size_type; + typedef typename _Alloc::difference_type difference_type; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef __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; + + private: + // _Rep: string representation + // Invariants: + // 1. String really contains _M_length + 1 characters; last is set + // to 0 only on call to c_str(). We avoid instantiating + // _CharT() where the interface does not require it. + // 2. _M_capacity >= _M_length + // Allocated memory is always _M_capacity + (1 * sizeof(_CharT)). + // 3. _M_references has three states: + // -1: leaked, one reference, no ref-copies allowed, non-const. + // 0: one reference, non-const. + // n>0: n + 1 references, operations require a lock, const. + // 4. All fields==0 is an empty string, given the extra storage + // beyond-the-end for a null terminator; thus, the shared + // empty string representation needs no constructor. + struct _Rep + { + // Types: + typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc; + + // (Public) Data members: + + // The maximum number of individual char_type elements of an + // individual string is determined by _S_max_size. This is the + // value that will be returned by max_size(). (Whereas npos + // is the maximum number of bytes the allocator can allocate.) + // If one was to divvy up the theoretical largest size string, + // with a terminating character and m _CharT elements, it'd + // look like this: + // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT) + // Solving for m: + // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1 + // In addition, this implementation quarters this ammount. + static const size_type _S_max_size; + static const _CharT _S_terminal; + + size_type _M_length; + size_type _M_capacity; + _Atomic_word _M_references; + + bool + _M_is_leaked() const + { return _M_references < 0; } + + bool + _M_is_shared() const + { return _M_references > 0; } + + void + _M_set_leaked() + { _M_references = -1; } + + void + _M_set_sharable() + { _M_references = 0; } + + _CharT* + _M_refdata() throw() + { return reinterpret_cast<_CharT*>(this + 1); } + + _CharT& + operator[](size_t __s) throw() + { return _M_refdata() [__s]; } + + _CharT* + _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2) + { + return (!_M_is_leaked() && __alloc1 == __alloc2) + ? _M_refcopy() : _M_clone(__alloc1); + } + + // Create & Destroy + static _Rep* + _S_create(size_t, const _Alloc&); + + void + _M_dispose(const _Alloc& __a) + { + if (__exchange_and_add(&_M_references, -1) <= 0) + _M_destroy(__a); + } // XXX MT + + void + _M_destroy(const _Alloc&) throw(); + + _CharT* + _M_refcopy() throw() + { + __atomic_add(&_M_references, 1); + return _M_refdata(); + } // XXX MT + + _CharT* + _M_clone(const _Alloc&, size_type __res = 0); + }; + + // Use empty-base optimization: http://www.cantrip.org/emptyopt.html + struct _Alloc_hider : _Alloc + { + _Alloc_hider(_CharT* __dat, const _Alloc& __a) + : _Alloc(__a), _M_p(__dat) { } + + _CharT* _M_p; // The actual data. + }; + + public: + // Data Members (public): + // NB: This is an unsigned type, and thus represents the maximum + // size that the allocator can hold. + static const size_type npos = static_cast<size_type>(-1); + + private: + // Data Members (private): + mutable _Alloc_hider _M_dataplus; + + // The following storage is init'd to 0 by the linker, resulting + // (carefully) in an empty string with one reference. + static size_type _S_empty_rep_storage[(sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)]; + + _CharT* + _M_data() const + { return _M_dataplus._M_p; } + + _CharT* + _M_data(_CharT* __p) + { return (_M_dataplus._M_p = __p); } + + _Rep* + _M_rep() const + { return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); } + + // For the internal use we have functions similar to `begin'/`end' + // but they do not call _M_leak. + iterator + _M_ibegin() const { return iterator(_M_data()); } + + iterator + _M_iend() const { return iterator(_M_data() + this->size()); } + + void + _M_leak() // for use in begin() & non-const op[] + { + if (!_M_rep()->_M_is_leaked()) + _M_leak_hard(); + } + + iterator + _M_check(size_type __pos) const + { + if (__pos > this->size()) + __throw_out_of_range("basic_string::_M_check"); + return _M_ibegin() + __pos; + } + + // NB: _M_fold doesn't check for a bad __pos1 value. + iterator + _M_fold(size_type __pos, size_type __off) const + { + bool __testoff = __off < this->size() - __pos; + size_type __newoff = __testoff ? __off : this->size() - __pos; + return (_M_ibegin() + __pos + __newoff); + } + + // _S_copy_chars is a separate template to permit specialization + // to optimize for the common case of pointers as iterators. + template<class _Iterator> + static void + _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) + { + for (; __k1 != __k2; ++__k1, ++__p) + traits_type::assign(*__p, *__k1); // These types are off. + } + + static void + _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) + { _S_copy_chars(__p, __k1.base(), __k2.base()); } + + static void + _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2) + { _S_copy_chars(__p, __k1.base(), __k2.base()); } + + static void + _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) + { traits_type::copy(__p, __k1, __k2 - __k1); } + + static void + _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2) + { traits_type::copy(__p, __k1, __k2 - __k1); } + + void + _M_mutate(size_type __pos, size_type __len1, size_type __len2); + + void + _M_leak_hard(); + + static _Rep& + _S_empty_rep() + { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); } + + public: + // Construct/copy/destroy: + // NB: We overload ctors in some cases instead of using default + // arguments, per 17.4.4.4 para. 2 item 2. + + inline + basic_string(); + + explicit + basic_string(const _Alloc& __a); + + // NB: per LWG issue 42, semantics different from IS: + basic_string(const basic_string& __str); + basic_string(const basic_string& __str, size_type __pos, + size_type __n = npos); + basic_string(const basic_string& __str, size_type __pos, + size_type __n, const _Alloc& __a); + + basic_string(const _CharT* __s, size_type __n, + const _Alloc& __a = _Alloc()); + basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()); + basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()); + + template<class _InputIterator> + basic_string(_InputIterator __beg, _InputIterator __end, + const _Alloc& __a = _Alloc()); + + ~basic_string() + { _M_rep()->_M_dispose(this->get_allocator()); } + + basic_string& + operator=(const basic_string& __str) { return this->assign(__str); } + + basic_string& + operator=(const _CharT* __s) { return this->assign(__s); } + + basic_string& + operator=(_CharT __c) { return this->assign(1, __c); } + + // Iterators: + iterator + begin() + { + _M_leak(); + return iterator(_M_data()); + } + + const_iterator + begin() const + { return const_iterator(_M_data()); } + + iterator + end() + { + _M_leak(); + return iterator(_M_data() + this->size()); + } + + const_iterator + end() const + { return const_iterator(_M_data() + this->size()); } + + reverse_iterator + rbegin() + { return reverse_iterator(this->end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(this->end()); } + + reverse_iterator + rend() + { return reverse_iterator(this->begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(this->begin()); } + + public: + // Capacity: + size_type + size() const { return _M_rep()->_M_length; } + + size_type + length() const { return _M_rep()->_M_length; } + + size_type + max_size() const { return _Rep::_S_max_size; } + + void + resize(size_type __n, _CharT __c); + + void + resize(size_type __n) { this->resize(__n, _CharT()); } + + size_type + capacity() const { return _M_rep()->_M_capacity; } + + void + reserve(size_type __res_arg = 0); + + void + clear() { _M_mutate(0, this->size(), 0); } + + bool + empty() const { return this->size() == 0; } + + // Element access: + const_reference + operator[] (size_type __pos) const + { return _M_data()[__pos]; } + + reference + operator[](size_type __pos) + { + _M_leak(); + return _M_data()[__pos]; + } + + const_reference + at(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range("basic_string::at"); + return _M_data()[__n]; + } + + reference + at(size_type __n) + { + if (__n >= size()) + __throw_out_of_range("basic_string::at"); + _M_leak(); + return _M_data()[__n]; + } + + // Modifiers: + basic_string& + operator+=(const basic_string& __str) { return this->append(__str); } + + basic_string& + operator+=(const _CharT* __s) { return this->append(__s); } + + basic_string& + operator+=(_CharT __c) { return this->append(size_type(1), __c); } + + basic_string& + append(const basic_string& __str); + + basic_string& + append(const basic_string& __str, size_type __pos, size_type __n); + + basic_string& + append(const _CharT* __s, size_type __n); + + basic_string& + append(const _CharT* __s) + { return this->append(__s, traits_type::length(__s)); } + + basic_string& + append(size_type __n, _CharT __c); + + template<class _InputIterator> + basic_string& + append(_InputIterator __first, _InputIterator __last) + { return this->replace(_M_iend(), _M_iend(), __first, __last); } + + void + push_back(_CharT __c) + { this->replace(_M_iend(), _M_iend(), 1, __c); } + + basic_string& + assign(const basic_string& __str); + + basic_string& + assign(const basic_string& __str, size_type __pos, size_type __n) + { + const size_type __strsize = __str.size(); + if (__pos > __strsize) + __throw_out_of_range("basic_string::assign"); + const bool __testn = __n < __strsize - __pos; + const size_type __newsize = __testn ? __n : __strsize - __pos; + return this->assign(__str._M_data() + __pos, __newsize); + } + + basic_string& + assign(const _CharT* __s, size_type __n) + { + if (__n > this->max_size()) + __throw_length_error("basic_string::assign"); + if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data()) + || less<const _CharT*>()(_M_data() + this->size(), __s)) + return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n); + else + { + // Work in-place + const size_type __pos = __s - _M_data(); + if (__pos >= __n) + traits_type::copy(_M_data(), __s, __n); + else if (__pos) + traits_type::move(_M_data(), __s, __n); + _M_rep()->_M_length = __n; + _M_data()[__n] = _Rep::_S_terminal; + return *this; + } + } + + basic_string& + assign(const _CharT* __s) + { return this->assign(__s, traits_type::length(__s)); } + + basic_string& + assign(size_type __n, _CharT __c) + { return this->replace(_M_ibegin(), _M_iend(), __n, __c); } + + template<class _InputIterator> + basic_string& + assign(_InputIterator __first, _InputIterator __last) + { return this->replace(_M_ibegin(), _M_iend(), __first, __last); } + + void + insert(iterator __p, size_type __n, _CharT __c) + { this->replace(__p, __p, __n, __c); } + + template<class _InputIterator> + void insert(iterator __p, _InputIterator __beg, _InputIterator __end) + { this->replace(__p, __p, __beg, __end); } + + basic_string& + insert(size_type __pos1, const basic_string& __str) + { return this->insert(__pos1, __str, 0, __str.size()); } + + basic_string& + insert(size_type __pos1, const basic_string& __str, + size_type __pos2, size_type __n) + { + const size_type __strsize = __str.size(); + if (__pos2 > __strsize) + __throw_out_of_range("basic_string::insert"); + const bool __testn = __n < __strsize - __pos2; + const size_type __newsize = __testn ? __n : __strsize - __pos2; + return this->insert(__pos1, __str._M_data() + __pos2, __newsize); + } + + basic_string& + insert(size_type __pos, const _CharT* __s, size_type __n) + { + const size_type __size = this->size(); + if (__pos > __size) + __throw_out_of_range("basic_string::insert"); + if (__size > this->max_size() - __n) + __throw_length_error("basic_string::insert"); + 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, + __s, __s + __n); + else + { + // Work in-place. If _M_mutate reallocates the string, __s + // does not point anymore to valid data, therefore we save its + // offset, then we restore it. + const size_type __off = __s - _M_data(); + _M_mutate(__pos, 0, __n); + __s = _M_data() + __off; + _CharT* __p = _M_data() + __pos; + if (__s + __n <= __p) + traits_type::copy(__p, __s, __n); + else if (__s >= __p) + traits_type::copy(__p, __s + __n, __n); + else + { + traits_type::copy(__p, __s, __p - __s); + traits_type::copy(__p + (__p - __s), __p + __n, __n - (__p - __s)); + } + return *this; + } + } + + basic_string& + insert(size_type __pos, const _CharT* __s) + { return this->insert(__pos, __s, traits_type::length(__s)); } + + basic_string& + insert(size_type __pos, size_type __n, _CharT __c) + { + this->insert(_M_check(__pos), __n, __c); + return *this; + } + + iterator + insert(iterator __p, _CharT __c = _CharT()) + { + size_type __pos = __p - _M_ibegin(); + this->insert(_M_check(__pos), size_type(1), __c); + _M_rep()->_M_set_leaked(); + return this->_M_ibegin() + __pos; + } + + basic_string& + erase(size_type __pos = 0, size_type __n = npos) + { + return this->replace(_M_check(__pos), _M_fold(__pos, __n), + _M_data(), _M_data()); + } + + iterator + erase(iterator __position) + { + size_type __i = __position - _M_ibegin(); + this->replace(__position, __position + 1, _M_data(), _M_data()); + _M_rep()->_M_set_leaked(); + return _M_ibegin() + __i; + } + + iterator + erase(iterator __first, iterator __last) + { + size_type __i = __first - _M_ibegin(); + this->replace(__first, __last, _M_data(), _M_data()); + _M_rep()->_M_set_leaked(); + return _M_ibegin() + __i; + } + + basic_string& + replace(size_type __pos, size_type __n, const basic_string& __str) + { return this->replace(__pos, __n, __str._M_data(), __str.size()); } + + basic_string& + replace(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2); + + basic_string& + replace(size_type __pos, size_type __n1, const _CharT* __s, + size_type __n2) + { + const size_type __size = this->size(); + if (__pos > __size) + __throw_out_of_range("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); + } + + basic_string& + replace(size_type __pos, size_type __n1, const _CharT* __s) + { return this->replace(__pos, __n1, __s, traits_type::length(__s)); } + + basic_string& + replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) + { return this->replace(_M_check(__pos), _M_fold(__pos, __n1), __n2, __c); } + + basic_string& + replace(iterator __i1, iterator __i2, const basic_string& __str) + { return this->replace(__i1, __i2, __str._M_data(), __str.size()); } + + basic_string& + replace(iterator __i1, iterator __i2, + const _CharT* __s, size_type __n) + { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n); } + + basic_string& + replace(iterator __i1, iterator __i2, const _CharT* __s) + { return this->replace(__i1, __i2, __s, traits_type::length(__s)); } + + basic_string& + replace(iterator __i1, iterator __i2, size_type __n, _CharT __c); + + template<class _InputIterator> + basic_string& + replace(iterator __i1, iterator __i2, + _InputIterator __k1, _InputIterator __k2) + { return _M_replace(__i1, __i2, __k1, __k2, + typename iterator_traits<_InputIterator>::iterator_category()); } + + private: + template<class _InputIterator> + basic_string& + _M_replace(iterator __i1, iterator __i2, _InputIterator __k1, + _InputIterator __k2, input_iterator_tag); + + template<class _ForwardIterator> + basic_string& + _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1, + _ForwardIterator __k2); + + // _S_construct_aux is used to implement the 21.3.1 para 15 which + // requires special behaviour if _InIter is an integral type + template<class _InIter> + static _CharT* + _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a, + __false_type) + { + typedef typename iterator_traits<_InIter>::iterator_category _Tag; + return _S_construct(__beg, __end, __a, _Tag()); + } + + template<class _InIter> + static _CharT* + _S_construct_aux(_InIter __beg, _InIter __end, const _Alloc& __a, + __true_type) + { + return _S_construct(static_cast<size_type>(__beg), + static_cast<value_type>(__end), __a); + } + + template<class _InIter> + static _CharT* + _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a) + { + typedef typename _Is_integer<_InIter>::_Integral _Integral; + return _S_construct_aux(__beg, __end, __a, _Integral()); + } + + // For Input Iterators, used in istreambuf_iterators, etc. + template<class _InIter> + static _CharT* + _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, + input_iterator_tag); + + // For forward_iterators up to random_access_iterators, used for + // string::iterator, _CharT*, etc. + template<class _FwdIter> + static _CharT* + _S_construct(_FwdIter __beg, _FwdIter __end, const _Alloc& __a, + forward_iterator_tag); + + static _CharT* + _S_construct(size_type __req, _CharT __c, const _Alloc& __a); + + public: + + size_type + copy(_CharT* __s, size_type __n, size_type __pos = 0) const; + + void + swap(basic_string<_CharT, _Traits, _Alloc>& __s); + + // String operations: + const _CharT* + c_str() const + { + // MT: This assumes concurrent writes are OK. + size_type __n = this->size(); + traits_type::assign(_M_data()[__n], _Rep::_S_terminal); + return _M_data(); + } + + const _CharT* + data() const { return _M_data(); } + + allocator_type + get_allocator() const { return _M_dataplus; } + + size_type + find(const _CharT* __s, size_type __pos, size_type __n) const; + + size_type + find(const basic_string& __str, size_type __pos = 0) const + { return this->find(__str.data(), __pos, __str.size()); } + + size_type + find(const _CharT* __s, size_type __pos = 0) const + { return this->find(__s, __pos, traits_type::length(__s)); } + + size_type + find(_CharT __c, size_type __pos = 0) const; + + size_type + rfind(const basic_string& __str, size_type __pos = npos) const + { return this->rfind(__str.data(), __pos, __str.size()); } + + size_type + rfind(const _CharT* __s, size_type __pos, size_type __n) const; + + size_type + rfind(const _CharT* __s, size_type __pos = npos) const + { return this->rfind(__s, __pos, traits_type::length(__s)); } + + size_type + rfind(_CharT __c, size_type __pos = npos) const; + + size_type + find_first_of(const basic_string& __str, size_type __pos = 0) const + { return this->find_first_of(__str.data(), __pos, __str.size()); } + + size_type + find_first_of(const _CharT* __s, size_type __pos, size_type __n) const; + + size_type + find_first_of(const _CharT* __s, size_type __pos = 0) const + { return this->find_first_of(__s, __pos, traits_type::length(__s)); } + + size_type + find_first_of(_CharT __c, size_type __pos = 0) const + { return this->find(__c, __pos); } + + size_type + find_last_of(const basic_string& __str, size_type __pos = npos) const + { return this->find_last_of(__str.data(), __pos, __str.size()); } + + size_type + find_last_of(const _CharT* __s, size_type __pos, size_type __n) const; + + size_type + find_last_of(const _CharT* __s, size_type __pos = npos) const + { return this->find_last_of(__s, __pos, traits_type::length(__s)); } + + size_type + find_last_of(_CharT __c, size_type __pos = npos) const + { return this->rfind(__c, __pos); } + + size_type + find_first_not_of(const basic_string& __str, size_type __pos = 0) const + { return this->find_first_not_of(__str.data(), __pos, __str.size()); } + + size_type + find_first_not_of(const _CharT* __s, size_type __pos, + size_type __n) const; + + size_type + find_first_not_of(const _CharT* __s, size_type __pos = 0) const + { return this->find_first_not_of(__s, __pos, traits_type::length(__s)); } + + size_type + find_first_not_of(_CharT __c, size_type __pos = 0) const; + + size_type + find_last_not_of(const basic_string& __str, size_type __pos = npos) const + { return this->find_last_not_of(__str.data(), __pos, __str.size()); } + + size_type + find_last_not_of(const _CharT* __s, size_type __pos, + size_type __n) const; + size_type + find_last_not_of(const _CharT* __s, size_type __pos = npos) const + { return this->find_last_not_of(__s, __pos, traits_type::length(__s)); } + + size_type + find_last_not_of(_CharT __c, size_type __pos = npos) const; + + basic_string + substr(size_type __pos = 0, size_type __n = npos) const + { + if (__pos > this->size()) + __throw_out_of_range("basic_string::substr"); + return basic_string(*this, __pos, __n); + } + + int + compare(const basic_string& __str) const + { + size_type __size = this->size(); + size_type __osize = __str.size(); + size_type __len = min(__size, __osize); + + int __r = traits_type::compare(_M_data(), __str.data(), __len); + if (!__r) + __r = __size - __osize; + return __r; + } + + int + compare(size_type __pos, size_type __n, const basic_string& __str) const; + + int + compare(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2) const; + + int + compare(const _CharT* __s) const; + + // _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; + }; + + + template<typename _CharT, typename _Traits, typename _Alloc> + inline basic_string<_CharT, _Traits, _Alloc>:: + basic_string() + : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { } + + // operator+ + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc> + operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { + basic_string<_CharT, _Traits, _Alloc> __str(__lhs); + __str.append(__rhs); + return __str; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT,_Traits,_Alloc> + operator+(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Alloc>& __rhs); + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT,_Traits,_Alloc> + operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); + + template<typename _CharT, typename _Traits, typename _Alloc> + inline basic_string<_CharT, _Traits, _Alloc> + operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { + basic_string<_CharT, _Traits, _Alloc> __str(__lhs); + __str.append(__rhs); + return __str; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline basic_string<_CharT, _Traits, _Alloc> + operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) + { + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + __string_type __str(__lhs); + __str.append(__size_type(1), __rhs); + return __str; + } + + // operator == + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __lhs.compare(__rhs) == 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator==(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) == 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) == 0; } + + // operator != + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) != 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator!=(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) != 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) != 0; } + + // operator < + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __lhs.compare(__rhs) < 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) < 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) > 0; } + + // operator > + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __lhs.compare(__rhs) > 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) > 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) < 0; } + + // operator <= + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __lhs.compare(__rhs) <= 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) <= 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator<=(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) >= 0; } + + // operator >= + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __lhs.compare(__rhs) >= 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { return __lhs.compare(__rhs) >= 0; } + + template<typename _CharT, typename _Traits, typename _Alloc> + inline bool + operator>=(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { return __rhs.compare(__lhs) <= 0; } + + + template<typename _CharT, typename _Traits, typename _Alloc> + inline void + swap(basic_string<_CharT, _Traits, _Alloc>& __lhs, + basic_string<_CharT, _Traits, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, + basic_string<_CharT, _Traits, _Alloc>& __str); + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const basic_string<_CharT, _Traits, _Alloc>& __str); + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_istream<_CharT,_Traits>& + getline(basic_istream<_CharT, _Traits>& __is, + basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim); + + template<typename _CharT, typename _Traits, typename _Alloc> + inline basic_istream<_CharT,_Traits>& + getline(basic_istream<_CharT, _Traits>& __is, + basic_string<_CharT, _Traits, _Alloc>& __str); +} // namespace std + +#endif /* _CPP_BITS_STRING_H */ diff --git a/contrib/libstdc++/include/bits/basic_string.tcc b/contrib/libstdc++/include/bits/basic_string.tcc new file mode 100644 index 0000000000000..35a2f11f7e761 --- /dev/null +++ b/contrib/libstdc++/include/bits/basic_string.tcc @@ -0,0 +1,981 @@ +// Components for manipulating sequences of characters -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 21 Strings library +// + +// This file is included by <string>. It is not meant to be included +// separately. + +// Written by Jason Merrill based upon the specification by Takanori Adachi +// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882. + +#ifndef _CPP_BITS_STRING_TCC +#define _CPP_BITS_STRING_TCC 1 + +#pragma GCC system_header + +namespace std +{ + template<typename _CharT, typename _Traits, typename _Alloc> + const typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + _Rep::_S_max_size = (((npos - sizeof(_Rep))/sizeof(_CharT)) - 1) / 4; + + template<typename _CharT, typename _Traits, typename _Alloc> + const _CharT + basic_string<_CharT, _Traits, _Alloc>:: + _Rep::_S_terminal = _CharT(); + + template<typename _CharT, typename _Traits, typename _Alloc> + const typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>::npos; + + // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string) + // at static init time (before static ctors are run). + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>::_S_empty_rep_storage[ + (sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)]; + + // NB: This is the special case for Input Iterators, used in + // istreambuf_iterators, etc. + // Input Iterators have a cost structure very different from + // pointers, calling for a different coding style. + template<typename _CharT, typename _Traits, typename _Alloc> + template<typename _InIter> + _CharT* + basic_string<_CharT, _Traits, _Alloc>:: + _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, + input_iterator_tag) + { + if (__beg == __end && __a == _Alloc()) + return _S_empty_rep()._M_refcopy(); + // Avoid reallocation for common case. + _CharT __buf[100]; + size_type __i = 0; + while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT)) + { + __buf[__i++] = *__beg; + ++__beg; + } + _Rep* __r = _Rep::_S_create(__i, __a); + traits_type::copy(__r->_M_refdata(), __buf, __i); + __r->_M_length = __i; + try + { + // NB: this loop looks precisely this way because + // it avoids comparing __beg != __end any more + // than strictly necessary; != might be expensive! + for (;;) + { + _CharT* __p = __r->_M_refdata() + __r->_M_length; + _CharT* __last = __r->_M_refdata() + __r->_M_capacity; + for (;;) + { + if (__beg == __end) + { + __r->_M_length = __p - __r->_M_refdata(); + *__p = _Rep::_S_terminal; // grrr. + return __r->_M_refdata(); + } + if (__p == __last) + break; + *__p++ = *__beg; + ++__beg; + } + // Allocate more space. + size_type __len = __p - __r->_M_refdata(); + _Rep* __another = _Rep::_S_create(__len + 1, __a); + traits_type::copy(__another->_M_refdata(), + __r->_M_refdata(), __len); + __r->_M_destroy(__a); + __r = __another; + __r->_M_length = __len; + } + } + catch(...) + { + __r->_M_destroy(__a); + __throw_exception_again; + } + return 0; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + template <class _InIter> + _CharT* + basic_string<_CharT, _Traits, _Alloc>:: + _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, + forward_iterator_tag) + { + size_type __dnew = static_cast<size_type>(distance(__beg, __end)); + + // NB: Not required, but considered best practice. + if (__builtin_expect(__beg == _InIter(0), 0)) + __throw_logic_error("attempt to create string with null pointer"); + + if (__beg == __end && __a == _Alloc()) + return _S_empty_rep()._M_refcopy(); + + // Check for out_of_range and length_error exceptions. + _Rep* __r = _Rep::_S_create(__dnew, __a); + try + { _S_copy_chars(__r->_M_refdata(), __beg, __end); } + catch(...) + { + __r->_M_destroy(__a); + __throw_exception_again; + } + __r->_M_length = __dnew; + + __r->_M_refdata()[__dnew] = _Rep::_S_terminal; // grrr. + return __r->_M_refdata(); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + _CharT* + basic_string<_CharT, _Traits, _Alloc>:: + _S_construct(size_type __n, _CharT __c, const _Alloc& __a) + { + if (__n == 0 && __a == _Alloc()) + return _S_empty_rep()._M_refcopy(); + + // Check for out_of_range and length_error exceptions. + _Rep* __r = _Rep::_S_create(__n, __a); + try + { + if (__n) + traits_type::assign(__r->_M_refdata(), __n, __c); + } + catch(...) + { + __r->_M_destroy(__a); + __throw_exception_again; + } + __r->_M_length = __n; + __r->_M_refdata()[__n] = _Rep::_S_terminal; // grrr + return __r->_M_refdata(); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const basic_string& __str) + : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()), + __str.get_allocator()) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const _Alloc& __a) + : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const basic_string& __str, size_type __pos, size_type __n) + : _M_dataplus(_S_construct(__str._M_check(__pos), + __str._M_fold(__pos, __n), _Alloc()), _Alloc()) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const basic_string& __str, size_type __pos, + size_type __n, const _Alloc& __a) + : _M_dataplus(_S_construct(__str._M_check(__pos), + __str._M_fold(__pos, __n), __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const _CharT* __s, size_type __n, const _Alloc& __a) + : _M_dataplus(_S_construct(__s, __s + __n, __a), __a) + { } + + 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 ? __s + traits_type::length(__s) : 0, + __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(size_type __n, _CharT __c, const _Alloc& __a) + : _M_dataplus(_S_construct(__n, __c, __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + template<typename _InputIter> + basic_string<_CharT, _Traits, _Alloc>:: + basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a) + : _M_dataplus(_S_construct(__beg, __end, __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str) + { + if (_M_rep() != __str._M_rep()) + { + // XXX MT + allocator_type __a = this->get_allocator(); + _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator()); + _M_rep()->_M_dispose(__a); + _M_data(__tmp); + } + return *this; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>::_Rep:: + _M_destroy(const _Alloc& __a) throw () + { + size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT); + _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard() + { + if (_M_rep()->_M_is_shared()) + _M_mutate(0, 0, 0); + _M_rep()->_M_set_leaked(); + } + + // _M_mutate and, below, _M_clone, include, in the same form, an exponential + // growth policy, necessary to meet amortized linear time requirements of + // the library: see http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. + // The policy is active for allocations requiring an amount of memory above + // system pagesize. This is consistent with the requirements of the standard: + // see, f.i., http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>:: + _M_mutate(size_type __pos, size_type __len1, size_type __len2) + { + size_type __old_size = this->size(); + const size_type __new_size = __old_size + __len2 - __len1; + const _CharT* __src = _M_data() + __pos + __len1; + const size_type __how_much = __old_size - __pos - __len1; + + if (_M_rep()->_M_is_shared() || __new_size > capacity()) + { + // Must reallocate. + allocator_type __a = get_allocator(); + // See below (_S_create) for the meaning and value of these + // constants. + const size_type __pagesize = 4096; + const size_type __malloc_header_size = 4 * sizeof (void*); + // The biggest string which fits in a memory page + const size_type __page_capacity = (__pagesize - __malloc_header_size + - sizeof(_Rep) - sizeof(_CharT)) + / sizeof(_CharT); + _Rep* __r; + if (__new_size > capacity() && __new_size > __page_capacity) + // Growing exponentially. + __r = _Rep::_S_create(__new_size > 2*capacity() ? + __new_size : 2*capacity(), __a); + else + __r = _Rep::_S_create(__new_size, __a); + try + { + if (__pos) + traits_type::copy(__r->_M_refdata(), _M_data(), __pos); + if (__how_much) + traits_type::copy(__r->_M_refdata() + __pos + __len2, + __src, __how_much); + } + catch(...) + { + __r->_M_dispose(get_allocator()); + __throw_exception_again; + } + _M_rep()->_M_dispose(__a); + _M_data(__r->_M_refdata()); + } + else if (__how_much && __len1 != __len2) + { + // Work in-place + traits_type::move(_M_data() + __pos + __len2, __src, __how_much); + } + _M_rep()->_M_set_sharable(); + _M_rep()->_M_length = __new_size; + _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4) + // You cannot leave those LWG people alone for a second. + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res) + { + if (__res > this->capacity() || _M_rep()->_M_is_shared()) + { + if (__res > this->max_size()) + __throw_length_error("basic_string::reserve"); + // Make sure we don't shrink below the current size + if (__res < this->size()) + __res = this->size(); + allocator_type __a = get_allocator(); + _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); + _M_rep()->_M_dispose(__a); + _M_data(__tmp); + } + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s) + { + if (_M_rep()->_M_is_leaked()) + _M_rep()->_M_set_sharable(); + if (__s._M_rep()->_M_is_leaked()) + __s._M_rep()->_M_set_sharable(); + if (this->get_allocator() == __s.get_allocator()) + { + _CharT* __tmp = _M_data(); + _M_data(__s._M_data()); + __s._M_data(__tmp); + } + // The code below can usually be optimized away. + else + { + basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator()); + basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), + this->get_allocator()); + *this = __tmp2; + __s = __tmp1; + } + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::_Rep* + basic_string<_CharT, _Traits, _Alloc>::_Rep:: + _S_create(size_t __capacity, const _Alloc& __alloc) + { + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + // 83. String::npos vs. string::max_size() + if (__capacity > _S_max_size) +#else + if (__capacity == npos) +#endif + __throw_length_error("basic_string::_S_create"); + + // NB: Need an array of char_type[__capacity], plus a + // terminating null char_type() element, plus enough for the + // _Rep data structure. Whew. Seemingly so needy, yet so elemental. + size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); + + // The standard places no restriction on allocating more memory + // than is strictly needed within this layer at the moment or as + // requested by an explicit application call to reserve(). Many + // malloc implementations perform quite poorly when an + // application attempts to allocate memory in a stepwise fashion + // growing each allocation size by only 1 char. Additionally, + // it makes little sense to allocate less linear memory than the + // natural blocking size of the malloc implementation. + // Unfortunately, we would need a somewhat low-level calculation + // with tuned parameters to get this perfect for any particular + // malloc implementation. Fortunately, generalizations about + // common features seen among implementations seems to suffice. + + // __pagesize need not match the actual VM page size for good + // results in practice, thus we pick a common value on the low + // side. __malloc_header_size is an estimate of the amount of + // overhead per memory allocation (in practice seen N * sizeof + // (void*) where N is 0, 2 or 4). According to folklore, + // picking this value on the high side is better than + // low-balling it (especially when this algorithm is used with + // malloc implementations that allocate memory blocks rounded up + // to a size which is a power of 2). + const size_t __pagesize = 4096; // must be 2^i * __subpagesize + const size_t __subpagesize = 128; // should be >> __malloc_header_size + const size_t __malloc_header_size = 4 * sizeof (void*); + if ((__size + __malloc_header_size) > __pagesize) + { + size_t __extra = + (__pagesize - ((__size + __malloc_header_size) % __pagesize)) + % __pagesize; + __capacity += __extra / sizeof(_CharT); + __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); + } + else if (__size > __subpagesize) + { + size_t __extra = + (__subpagesize - ((__size + __malloc_header_size) % __subpagesize)) + % __subpagesize; + __capacity += __extra / sizeof(_CharT); + __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep); + } + + // NB: Might throw, but no worries about a leak, mate: _Rep() + // does not throw. + 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_length = 0; + return __p; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + _CharT* + basic_string<_CharT, _Traits, _Alloc>::_Rep:: + _M_clone(const _Alloc& __alloc, size_type __res) + { + // Requested capacity of the clone. + const size_type __requested_cap = _M_length + __res; + // See above (_S_create) for the meaning and value of these constants. + const size_type __pagesize = 4096; + const size_type __malloc_header_size = 4 * sizeof (void*); + // The biggest string which fits in a memory page. + const size_type __page_capacity = + (__pagesize - __malloc_header_size - sizeof(_Rep) - sizeof(_CharT)) + / sizeof(_CharT); + _Rep* __r; + if (__requested_cap > _M_capacity && __requested_cap > __page_capacity) + // Growing exponentially. + __r = _Rep::_S_create(__requested_cap > 2*_M_capacity ? + __requested_cap : 2*_M_capacity, __alloc); + else + __r = _Rep::_S_create(__requested_cap, __alloc); + + if (_M_length) + { + try + { traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); } + catch(...) + { + __r->_M_destroy(__alloc); + __throw_exception_again; + } + } + __r->_M_length = _M_length; + return __r->_M_refdata(); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c) + { + if (__n > max_size()) + __throw_length_error("basic_string::resize"); + size_type __size = this->size(); + if (__size < __n) + this->append(__n - __size, __c); + else if (__n < __size) + 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) + template<typename _CharT, typename _Traits, typename _Alloc> + template<typename _InputIter> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + _M_replace(iterator __i1, iterator __i2, _InputIter __k1, + _InputIter __k2, input_iterator_tag) + { + // Save concerned source string data in a temporary. + basic_string __s(__k1, __k2); + return _M_replace_safe(__i1, __i2, __s._M_ibegin(), __s._M_iend()); + } + + // This is a special replace helper, which does not buffer internally + // and can be used in the "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>& + basic_string<_CharT, _Traits, _Alloc>:: + _M_replace_safe(iterator __i1, iterator __i2, _ForwardIter __k1, + _ForwardIter __k2) + { + size_type __dnew = static_cast<size_type>(distance(__k1, __k2)); + size_type __dold = __i2 - __i1; + size_type __dmax = this->max_size(); + + if (__dmax <= __dnew) + __throw_length_error("basic_string::_M_replace"); + size_type __off = __i1 - _M_ibegin(); + _M_mutate(__off, __dold, __dnew); + + // Invalidated __i1, __i2 + if (__dnew) + _S_copy_chars(_M_data() + __off, __k1, __k2); + + return *this; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + replace(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2) + { + const size_type __strsize = __str.size(); + if (__pos2 > __strsize) + __throw_out_of_range("basic_string::replace"); + const bool __testn2 = __n2 < __strsize - __pos2; + const size_type __foldn2 = __testn2 ? __n2 : __strsize - __pos2; + return this->replace(__pos1, __n1, + __str._M_data() + __pos2, __foldn2); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + append(const basic_string& __str) + { + // Iff appending itself, string needs to pre-reserve the + // correct size so that _M_mutate does not clobber the + // iterators formed here. + size_type __size = __str.size(); + size_type __len = __size + this->size(); + if (__len > this->capacity()) + this->reserve(__len); + return _M_replace_safe(_M_iend(), _M_iend(), __str._M_ibegin(), + __str._M_iend()); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + append(const basic_string& __str, size_type __pos, size_type __n) + { + // Iff appending itself, string needs to pre-reserve the + // correct size so that _M_mutate does not clobber the + // iterators formed here. + size_type __len = min(__str.size() - __pos, __n) + this->size(); + if (__len > this->capacity()) + this->reserve(__len); + return _M_replace_safe(_M_iend(), _M_iend(), __str._M_check(__pos), + __str._M_fold(__pos, __n)); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + append(const _CharT* __s, size_type __n) + { + size_type __len = __n + this->size(); + if (__len > this->capacity()) + this->reserve(__len); + return _M_replace_safe(_M_iend(), _M_iend(), __s, __s + __n); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + append(size_type __n, _CharT __c) + { + size_type __len = __n + this->size(); + if (__len > this->capacity()) + this->reserve(__len); + return this->replace(_M_iend(), _M_iend(), __n, __c); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc> + operator+(const _CharT* __lhs, + const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + __size_type __len = _Traits::length(__lhs); + __string_type __str; + __str.reserve(__len + __rhs.size()); + __str.append(__lhs, __lhs + __len); + __str.append(__rhs); + return __str; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc> + operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) + { + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + __string_type __str; + __size_type __len = __rhs.size(); + __str.reserve(__len + 1); + __str.append(__size_type(1), __lhs); + __str.append(__rhs); + return __str; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>& + basic_string<_CharT, _Traits, _Alloc>:: + replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c) + { + size_type __n1 = __i2 - __i1; + size_type __off1 = __i1 - _M_ibegin(); + if (max_size() - (this->size() - __n1) <= __n2) + __throw_length_error("basic_string::replace"); + _M_mutate (__off1, __n1, __n2); + // Invalidated __i1, __i2 + if (__n2) + traits_type::assign(_M_data() + __off1, __n2, __c); + return *this; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + copy(_CharT* __s, size_type __n, size_type __pos) const + { + if (__pos > this->size()) + __throw_out_of_range("basic_string::copy"); + + if (__n > this->size() - __pos) + __n = this->size() - __pos; + + traits_type::copy(__s, _M_data() + __pos, __n); + // 21.3.5.7 par 3: do not append null. (good.) + return __n; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find(const _CharT* __s, size_type __pos, size_type __n) const + { + size_type __size = this->size(); + size_t __xpos = __pos; + const _CharT* __data = _M_data(); + for (; __xpos + __n <= __size; ++__xpos) + if (traits_type::compare(__data + __xpos, __s, __n) == 0) + return __xpos; + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find(_CharT __c, size_type __pos) const + { + size_type __size = this->size(); + size_type __ret = npos; + if (__pos < __size) + { + const _CharT* __data = _M_data(); + size_type __n = __size - __pos; + const _CharT* __p = traits_type::find(__data + __pos, __n, __c); + if (__p) + __ret = __p - __data; + } + return __ret; + } + + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + rfind(const _CharT* __s, size_type __pos, size_type __n) const + { + size_type __size = this->size(); + if (__n <= __size) + { + __pos = std::min(__size - __n, __pos); + const _CharT* __data = _M_data(); + do + { + if (traits_type::compare(__data + __pos, __s, __n) == 0) + return __pos; + } + while (__pos-- > 0); + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + rfind(_CharT __c, size_type __pos) const + { + size_type __size = this->size(); + if (__size) + { + size_t __xpos = __size - 1; + if (__xpos > __pos) + __xpos = __pos; + + for (++__xpos; __xpos-- > 0; ) + if (traits_type::eq(_M_data()[__xpos], __c)) + return __xpos; + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + { + for (; __n && __pos < this->size(); ++__pos) + { + const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]); + if (__p) + return __pos; + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + { + size_type __size = this->size(); + if (__size && __n) + { + if (--__size > __pos) + __size = __pos; + do + { + if (traits_type::find(__s, __n, _M_data()[__size])) + return __size; + } + while (__size-- != 0); + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const + { + size_t __xpos = __pos; + for (; __xpos < this->size(); ++__xpos) + if (!traits_type::find(__s, __n, _M_data()[__xpos])) + return __xpos; + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_first_not_of(_CharT __c, size_type __pos) const + { + size_t __xpos = __pos; + for (; __xpos < this->size(); ++__xpos) + if (!traits_type::eq(_M_data()[__xpos], __c)) + return __xpos; + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const + { + size_type __size = this->size(); + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::find(__s, __n, _M_data()[__size])) + return __size; + } + while (__size--); + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + typename basic_string<_CharT, _Traits, _Alloc>::size_type + basic_string<_CharT, _Traits, _Alloc>:: + find_last_not_of(_CharT __c, size_type __pos) const + { + size_type __size = this->size(); + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::eq(_M_data()[__size], __c)) + return __size; + } + while (__size--); + } + return npos; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + int + basic_string<_CharT, _Traits, _Alloc>:: + compare(size_type __pos, size_type __n, const basic_string& __str) const + { + size_type __size = this->size(); + size_type __osize = __str.size(); + if (__pos > __size) + __throw_out_of_range("basic_string::compare"); + + size_type __rsize= min(__size - __pos, __n); + size_type __len = min(__rsize, __osize); + int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len); + if (!__r) + __r = __rsize - __osize; + return __r; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + int + basic_string<_CharT, _Traits, _Alloc>:: + compare(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2) const + { + size_type __size = this->size(); + size_type __osize = __str.size(); + if (__pos1 > __size || __pos2 > __osize) + __throw_out_of_range("basic_string::compare"); + + size_type __rsize = min(__size - __pos1, __n1); + size_type __rosize = min(__osize - __pos2, __n2); + size_type __len = min(__rsize, __rosize); + int __r = traits_type::compare(_M_data() + __pos1, + __str.data() + __pos2, __len); + if (!__r) + __r = __rsize - __rosize; + return __r; + } + + + template<typename _CharT, typename _Traits, typename _Alloc> + int + basic_string<_CharT, _Traits, _Alloc>:: + compare(const _CharT* __s) const + { + size_type __size = this->size(); + int __r = traits_type::compare(_M_data(), __s, __size); + if (!__r) + __r = __size - traits_type::length(__s); + return __r; + } + + + template<typename _CharT, typename _Traits, typename _Alloc> + int + basic_string <_CharT, _Traits, _Alloc>:: + compare(size_type __pos, size_type __n1, const _CharT* __s) const + { + size_type __size = this->size(); + if (__pos > __size) + __throw_out_of_range("basic_string::compare"); + + size_type __osize = traits_type::length(__s); + size_type __rsize = min(__size - __pos, __n1); + size_type __len = min(__rsize, __osize); + int __r = traits_type::compare(_M_data() + __pos, __s, __len); + if (!__r) + __r = __rsize - __osize; + return __r; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + int + basic_string <_CharT, _Traits, _Alloc>:: + compare(size_type __pos, size_type __n1, const _CharT* __s, + size_type __n2) const + { + size_type __size = this->size(); + if (__pos > __size) + __throw_out_of_range("basic_string::compare"); + + size_type __osize = min(traits_type::length(__s), __n2); + size_type __rsize = min(__size - __pos, __n1); + size_type __len = min(__rsize, __osize); + int __r = traits_type::compare(_M_data() + __pos, __s, __len); + if (!__r) + __r = __rsize - __osize; + return __r; + } + + template <class _CharT, class _Traits, class _Alloc> + void + _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str, + _CharT* __buf, typename _Alloc::size_type __bufsiz) + { + typedef typename _Alloc::size_type size_type; + size_type __strsize = __str.size(); + size_type __bytes = min(__strsize, __bufsiz - 1); + _Traits::copy(__buf, __str.data(), __bytes); + __buf[__bytes] = _CharT(); + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class basic_string<char>; + extern template + basic_istream<char>& + operator>>(basic_istream<char>&, string&); + extern template + basic_ostream<char>& + operator<<(basic_ostream<char>&, const string&); + extern template + basic_istream<char>& + getline(basic_istream<char>&, string&, char); + extern template + basic_istream<char>& + getline(basic_istream<char>&, string&); + + extern template class basic_string<wchar_t>; + extern template + basic_istream<wchar_t>& + operator>>(basic_istream<wchar_t>&, wstring&); + extern template + basic_ostream<wchar_t>& + operator<<(basic_ostream<wchar_t>&, const wstring&); + extern template + basic_istream<wchar_t>& + getline(basic_istream<wchar_t>&, wstring&, wchar_t); + extern template + basic_istream<wchar_t>& + getline(basic_istream<wchar_t>&, wstring&); +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/boost_concept_check.h b/contrib/libstdc++/include/bits/boost_concept_check.h new file mode 100644 index 0000000000000..29ca61baef72c --- /dev/null +++ b/contrib/libstdc++/include/bits/boost_concept_check.h @@ -0,0 +1,899 @@ +// +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// + +// GCC Note: based on version 1.12.0 of the Boost library. + +/** @file boost_concept_check.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _GLIBCPP_BOOST_CONCEPT_CHECK +#define _GLIBCPP_BOOST_CONCEPT_CHECK 1 + +#pragma GCC system_header +#include <cstddef> // for ptrdiff_t, used next +#include <bits/stl_iterator_base_types.h> // for traits and tags +#include <utility> // for pair<> + + +namespace __gnu_cxx +{ + +#define _IsUnused __attribute__ ((__unused__)) + +// When the C-C code is in use, we would like this function to do as little +// as possible at runtime, use as few resources as possible, and hopefully +// be elided out of existence... hmmm. +template <class _Concept> +inline void __function_requires() +{ + void (_Concept::*__x)() _IsUnused = &_Concept::__constraints; +} + + +// ??? Should the "concept_checking*" structs begin with more than _ ? +#define _GLIBCPP_CLASS_REQUIRES(_type_var, _ns, _concept) \ + typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \ + template <_func##_type_var##_concept _Tp1> \ + struct _concept_checking##_type_var##_concept { }; \ + typedef _concept_checking##_type_var##_concept< \ + &_ns::_concept <_type_var>::__constraints> \ + _concept_checking_typedef##_type_var##_concept + +#define _GLIBCPP_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \ + template <_func##_type_var1##_type_var2##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_concept< \ + &_ns::_concept <_type_var1,_type_var2>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_concept + +#define _GLIBCPP_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept + +#define _GLIBCPP_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept + + +template <class _Tp1, class _Tp2> +struct _Aux_require_same { }; + +template <class _Tp> +struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; + + template <class _Tp1, class _Tp2> + struct _SameTypeConcept + { + void __constraints() { + typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required; + } + }; + + template <class _Tp> + struct _IntegerConcept { + void __constraints() { + __error_type_must_be_an_integer_type(); + } + }; + template <> struct _IntegerConcept<short> { void __constraints() {} }; + template <> struct _IntegerConcept<unsigned short> { void __constraints(){} }; + template <> struct _IntegerConcept<int> { void __constraints() {} }; + template <> struct _IntegerConcept<unsigned int> { void __constraints() {} }; + template <> struct _IntegerConcept<long> { void __constraints() {} }; + template <> struct _IntegerConcept<unsigned long> { void __constraints() {} }; + template <> struct _IntegerConcept<long long> { void __constraints() {} }; + template <> struct _IntegerConcept<unsigned long long> + { void __constraints() {} }; + + template <class _Tp> + struct _SignedIntegerConcept { + void __constraints() { + __error_type_must_be_a_signed_integer_type(); + } + }; + template <> struct _SignedIntegerConcept<short> { void __constraints() {} }; + template <> struct _SignedIntegerConcept<int> { void __constraints() {} }; + template <> struct _SignedIntegerConcept<long> { void __constraints() {} }; + template <> struct _SignedIntegerConcept<long long> { void __constraints(){}}; + + template <class _Tp> + struct _UnsignedIntegerConcept { + void __constraints() { + __error_type_must_be_an_unsigned_integer_type(); + } + }; + template <> struct _UnsignedIntegerConcept<unsigned short> + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept<unsigned int> + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept<unsigned long> + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept<unsigned long long> + { void __constraints() {} }; + + //=========================================================================== + // Basic Concepts + + template <class _Tp> + struct _DefaultConstructibleConcept + { + void __constraints() { + _Tp __a _IsUnused; // require default constructor + } + }; + + template <class _Tp> + struct _AssignableConcept + { + void __constraints() { + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + __a = __b; // const required for argument to assignment + } + _Tp __a; + }; + + template <class _Tp> + struct _CopyConstructibleConcept + { + void __constraints() { + _Tp __a(__b); // require copy constructor + _Tp* __ptr _IsUnused = &__a; // require address of operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __a) { + _Tp __c(__a) _IsUnused; // require const copy constructor + const _Tp* __ptr _IsUnused = &__a; // require const address of operator + } + _Tp __b; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + template <class _Tp> + struct _SGIAssignableConcept + { + void __constraints() { + _Tp __b(__a) _IsUnused; + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + _Tp __c(__b) _IsUnused; + __a = __b; // const required for argument to assignment + } + _Tp __a; + }; + + template <class _From, class _To> + struct _ConvertibleConcept + { + void __constraints() { + _To __y _IsUnused = __x; + } + _From __x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template <class _Tp> + void __aux_require_boolean_expr(const _Tp& __t) { + bool __x _IsUnused = __t; + } + +// FIXME + template <class _Tp> + struct _EqualityComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a == __b); + __aux_require_boolean_expr(__a != __b); + } + _Tp __a, __b; + }; + + template <class _Tp> + struct _LessThanComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + } + _Tp __a, __b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template <class _Tp> + struct _ComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + __aux_require_boolean_expr(__a > __b); + __aux_require_boolean_expr(__a <= __b); + __aux_require_boolean_expr(__a >= __b); + } + _Tp __a, __b; + }; + +#define _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \ + template <class _First, class _Second> \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + bool __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + +#define _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ + template <class _Ret, class _First, class _Second> \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + _Ret __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept); + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept); + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept); + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept); + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept); + _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept); + + _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept); + _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept); + _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept); + _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept); + _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept); + +#undef _GLIBCPP_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT +#undef _GLIBCPP_DEFINE_BINARY_OPERATOR_CONSTRAINT + + //=========================================================================== + // Function Object Concepts + + template <class _Func, class _Return> + struct _GeneratorConcept + { + void __constraints() { + const _Return& __r _IsUnused = __f();// require operator() member function + } + _Func __f; + }; + + + template <class _Func> + struct _GeneratorConcept<_Func,void> + { + void __constraints() { + __f(); // require operator() member function + } + _Func __f; + }; + + template <class _Func, class _Return, class _Arg> + struct _UnaryFunctionConcept + { + void __constraints() { + __r = __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + _Return __r; + }; + + template <class _Func, class _Arg> + struct _UnaryFunctionConcept<_Func, void, _Arg> { + void __constraints() { + __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + }; + + template <class _Func, class _Return, class _First, class _Second> + struct _BinaryFunctionConcept + { + void __constraints() { + __r = __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + _Return __r; + }; + + template <class _Func, class _First, class _Second> + struct _BinaryFunctionConcept<_Func, void, _First, _Second> + { + void __constraints() { + __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + }; + + template <class _Func, class _Arg> + struct _UnaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__arg)); // require op() returning bool + } + _Func __f; + _Arg __arg; + }; + + template <class _Func, class _First, class _Second> + struct _BinaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool + } + _Func __f; + _First __a; + _Second __b; + }; + + // use this when functor is used inside a container class like std::set + template <class _Func, class _First, class _Second> + struct _Const_BinaryPredicateConcept { + void __constraints() { + __const_constraints(__f); + } + void __const_constraints(const _Func& __fun) { + __function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >(); + // operator() must be a const member function + __aux_require_boolean_expr(__fun(__a, __b)); + } + _Func __f; + _First __a; + _Second __b; + }; + + //=========================================================================== + // Iterator Concepts + + template <class _Tp> + struct _TrivialIteratorConcept + { + void __constraints() { + __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _AssignableConcept<_Tp> >(); + __function_requires< _EqualityComparableConcept<_Tp> >(); +// typedef typename std::iterator_traits<_Tp>::value_type _V; + (void)*__i; // require dereference operator + } + _Tp __i; + }; + + template <class _Tp> + struct _Mutable_TrivialIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + *__i = *__j; // require dereference and assignment + } + _Tp __i, __j; + }; + + template <class _Tp> + struct _InputIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + // require iterator_traits typedef's + typedef typename std::iterator_traits<_Tp>::difference_type _D; +// __function_requires< _SignedIntegerConcept<_D> >(); + typedef typename std::iterator_traits<_Tp>::reference _R; + typedef typename std::iterator_traits<_Tp>::pointer _Pt; + typedef typename std::iterator_traits<_Tp>::iterator_category _Cat; + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::input_iterator_tag> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + } + _Tp __i; + }; + + template <class _Tp, class _ValueT> + struct _OutputIteratorConcept + { + void __constraints() { + __function_requires< _AssignableConcept<_Tp> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + *__i++ = __t; // require postincrement and assignment + } + _Tp __i; + _ValueT __t; + }; + + template <class _Tp> + struct _ForwardIteratorConcept + { + void __constraints() { + __function_requires< _InputIteratorConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::forward_iterator_tag> >(); + typedef typename std::iterator_traits<_Tp>::reference _R; + _R __r _IsUnused = *__i; + } + _Tp __i; + }; + + template <class _Tp> + struct _Mutable_ForwardIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + *__i++ = *__i; // require postincrement and assignment + } + _Tp __i; + }; + + template <class _Tp> + struct _BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::bidirectional_iterator_tag> >(); + --__i; // require predecrement operator + __i--; // require postdecrement operator + } + _Tp __i; + }; + + template <class _Tp> + struct _Mutable_BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); + *__i-- = *__i; // require postdecrement and assignment + } + _Tp __i; + }; + + + template <class _Tp> + struct _RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _ComparableConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::random_access_iterator_tag> >(); + // ??? We don't use _R, are we just checking for "referenceability"? + typedef typename std::iterator_traits<_Tp>::reference _R; + + __i += __n; // require assignment addition operator + __i = __i + __n; __i = __n + __i; // require addition with difference type + __i -= __n; // require assignment subtraction op + __i = __i - __n; // require subtraction with + // difference type + __n = __i - __j; // require difference operator + (void)__i[__n]; // require element access operator + } + _Tp __a, __b; + _Tp __i, __j; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + template <class _Tp> + struct _Mutable_RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _RandomAccessIteratorConcept<_Tp> >(); + __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); + __i[__n] = *__i; // require element access and assignment + } + _Tp __i; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + //=========================================================================== + // Container Concepts + + template <class _Container> + struct _ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::difference_type _Difference_type; + typedef typename _Container::size_type _Size_type; + typedef typename _Container::const_reference _Const_reference; + typedef typename _Container::const_pointer _Const_pointer; + typedef typename _Container::const_iterator _Const_iterator; + + void __constraints() { + __function_requires< _InputIteratorConcept<_Const_iterator> >(); + __function_requires< _AssignableConcept<_Container> >(); + const _Container __c; + __i = __c.begin(); + __i = __c.end(); + __n = __c.size(); + __n = __c.max_size(); + __b = __c.empty(); + } + bool __b; + _Const_iterator __i; + _Size_type __n; + }; + + template <class _Container> + struct _Mutable_ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::reference _Reference; + typedef typename _Container::iterator _Iterator; + typedef typename _Container::pointer _Pointer; + + void __constraints() { + __function_requires< _ContainerConcept<_Container> >(); + __function_requires< _AssignableConcept<_Value_type> >(); + __function_requires< _InputIteratorConcept<_Iterator> >(); + + __i = __c.begin(); + __i = __c.end(); + __c.swap(__c2); + } + _Iterator __i; + _Container __c, __c2; + }; + + template <class _ForwardContainer> + struct _ForwardContainerConcept + { + void __constraints() { + __function_requires< _ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::const_iterator _Const_iterator; + __function_requires< _ForwardIteratorConcept<_Const_iterator> >(); + } + }; + + template <class _ForwardContainer> + struct _Mutable_ForwardContainerConcept + { + void __constraints() { + __function_requires< _ForwardContainerConcept<_ForwardContainer> >(); + __function_requires< _Mutable_ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::iterator _Iterator; + __function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >(); + } + }; + + template <class _ReversibleContainer> + struct _ReversibleContainerConcept + { + typedef typename _ReversibleContainer::const_iterator _Const_iterator; + typedef typename _ReversibleContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< _ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires< _BidirectionalIteratorConcept<_Const_iterator> >(); + __function_requires< + _BidirectionalIteratorConcept<_Const_reverse_iterator> >(); + + const _ReversibleContainer __c; + _Const_reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + }; + + template <class _ReversibleContainer> + struct _Mutable_ReversibleContainerConcept + { + typedef typename _ReversibleContainer::iterator _Iterator; + typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires<_ReversibleContainerConcept<_ReversibleContainer> >(); + __function_requires< + _Mutable_ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >(); + + _Reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + _ReversibleContainer __c; + }; + + template <class _RandomAccessContainer> + struct _RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::const_reference _Const_reference; + typedef typename _RandomAccessContainer::const_iterator _Const_iterator; + typedef typename _RandomAccessContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< + _ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _RandomAccessIteratorConcept<_Const_iterator> >(); + __function_requires< + _RandomAccessIteratorConcept<_Const_reverse_iterator> >(); + + const _RandomAccessContainer __c; + _Const_reference __r _IsUnused = __c[__n]; + } + _Size_type __n; + }; + + template <class _RandomAccessContainer> + struct _Mutable_RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::reference _Reference; + typedef typename _RandomAccessContainer::iterator _Iterator; + typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires< + _RandomAccessContainerConcept<_RandomAccessContainer> >(); + __function_requires< + _Mutable_ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >(); + + _Reference __r _IsUnused = __c[__i]; + } + _Size_type __i; + _RandomAccessContainer __c; + }; + + // A Sequence is inherently mutable + template <class _Sequence> + struct _SequenceConcept + { + typedef typename _Sequence::reference _Reference; + typedef typename _Sequence::const_reference _Const_reference; + + void __constraints() { + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // function_requires< DefaultConstructible<Sequence> >(); + __function_requires< _Mutable_ForwardContainerConcept<_Sequence> >(); + __function_requires< _DefaultConstructibleConcept<_Sequence> >(); + + _Sequence + __c(__n) _IsUnused, + __c2(__n, __t) _IsUnused, + __c3(__first, __last) _IsUnused; + + __c.insert(__p, __t); + __c.insert(__p, __n, __t); + __c.insert(__p, __first, __last); + + __c.erase(__p); + __c.erase(__p, __q); + + _Reference __r _IsUnused = __c.front(); + + __const_constraints(__c); + } + void __const_constraints(const _Sequence& __c) { + _Const_reference __r _IsUnused = __c.front(); + } + typename _Sequence::value_type __t; + typename _Sequence::size_type __n; + typename _Sequence::value_type *__first, *__last; + typename _Sequence::iterator __p, __q; + }; + + template <class _FrontInsertionSequence> + struct _FrontInsertionSequenceConcept + { + void __constraints() { + __function_requires< _SequenceConcept<_FrontInsertionSequence> >(); + + __c.push_front(__t); + __c.pop_front(); + } + _FrontInsertionSequence __c; + typename _FrontInsertionSequence::value_type __t; + }; + + template <class _BackInsertionSequence> + struct _BackInsertionSequenceConcept + { + typedef typename _BackInsertionSequence::reference _Reference; + typedef typename _BackInsertionSequence::const_reference _Const_reference; + + void __constraints() { + __function_requires< _SequenceConcept<_BackInsertionSequence> >(); + + __c.push_back(__t); + __c.pop_back(); + _Reference __r _IsUnused = __c.back(); + } + void __const_constraints(const _BackInsertionSequence& __c) { + _Const_reference __r _IsUnused = __c.back(); + }; + _BackInsertionSequence __c; + typename _BackInsertionSequence::value_type __t; + }; + + template <class _AssociativeContainer> + struct _AssociativeContainerConcept + { + void __constraints() { + __function_requires< _ForwardContainerConcept<_AssociativeContainer> >(); + __function_requires< + _DefaultConstructibleConcept<_AssociativeContainer> >(); + + __i = __c.find(__k); + __r = __c.equal_range(__k); + __c.erase(__k); + __c.erase(__i); + __c.erase(__r.first, __r.second); + __const_constraints(__c); + } + void __const_constraints(const _AssociativeContainer& __c) { + __ci = __c.find(__k); + __n = __c.count(__k); + __cr = __c.equal_range(__k); + } + typedef typename _AssociativeContainer::iterator _Iterator; + typedef typename _AssociativeContainer::const_iterator _Const_iterator; + + _AssociativeContainer __c; + _Iterator __i; + std::pair<_Iterator,_Iterator> __r; + _Const_iterator __ci; + std::pair<_Const_iterator,_Const_iterator> __cr; + typename _AssociativeContainer::key_type __k; + typename _AssociativeContainer::size_type __n; + }; + + template <class _UniqueAssociativeContainer> + struct _UniqueAssociativeContainerConcept + { + void __constraints() { + __function_requires< + _AssociativeContainerConcept<_UniqueAssociativeContainer> >(); + + _UniqueAssociativeContainer __c(__first, __last); + + __pos_flag = __c.insert(__t); + __c.insert(__first, __last); + } + std::pair<typename _UniqueAssociativeContainer::iterator, bool> __pos_flag; + typename _UniqueAssociativeContainer::value_type __t; + typename _UniqueAssociativeContainer::value_type *__first, *__last; + }; + + template <class _MultipleAssociativeContainer> + struct _MultipleAssociativeContainerConcept + { + void __constraints() { + __function_requires< + _AssociativeContainerConcept<_MultipleAssociativeContainer> >(); + + _MultipleAssociativeContainer __c(__first, __last); + + __pos = __c.insert(__t); + __c.insert(__first, __last); + + } + typename _MultipleAssociativeContainer::iterator __pos _IsUnused; + typename _MultipleAssociativeContainer::value_type __t; + typename _MultipleAssociativeContainer::value_type *__first, *__last; + }; + + template <class _SimpleAssociativeContainer> + struct _SimpleAssociativeContainerConcept + { + void __constraints() { + __function_requires< + _AssociativeContainerConcept<_SimpleAssociativeContainer> >(); + typedef typename _SimpleAssociativeContainer::key_type _Key_type; + typedef typename _SimpleAssociativeContainer::value_type _Value_type; + typedef typename _Aux_require_same<_Key_type, _Value_type>::_Type + _Requqired; + } + }; + + template <class _SimpleAssociativeContainer> + struct _PairAssociativeContainerConcept + { + void __constraints() { + __function_requires< + _AssociativeContainerConcept<_SimpleAssociativeContainer> >(); + typedef typename _SimpleAssociativeContainer::key_type _Key_type; + typedef typename _SimpleAssociativeContainer::value_type _Value_type; + typedef typename _SimpleAssociativeContainer::mapped_type _Mapped_type; + typedef std::pair<const _Key_type, _Mapped_type> _Required_value_type; + typedef typename _Aux_require_same<_Value_type, + _Required_value_type>::_Type _Required; + } + }; + + template <class _SortedAssociativeContainer> + struct _SortedAssociativeContainerConcept + { + void __constraints() { + __function_requires< + _AssociativeContainerConcept<_SortedAssociativeContainer> >(); + __function_requires< + _ReversibleContainerConcept<_SortedAssociativeContainer> >(); + + _SortedAssociativeContainer + __c(__kc) _IsUnused, + __c2(__first, __last) _IsUnused, + __c3(__first, __last, __kc) _IsUnused; + + __p = __c.upper_bound(__k); + __p = __c.lower_bound(__k); + __r = __c.equal_range(__k); + + __c.insert(__p, __t); + } + void __const_constraints(const _SortedAssociativeContainer& __c) { + __kc = __c.key_comp(); + __vc = __c.value_comp(); + + __cp = __c.upper_bound(__k); + __cp = __c.lower_bound(__k); + __cr = __c.equal_range(__k); + } + typename _SortedAssociativeContainer::key_compare __kc; + typename _SortedAssociativeContainer::value_compare __vc; + typename _SortedAssociativeContainer::value_type __t; + typename _SortedAssociativeContainer::key_type __k; + typedef typename _SortedAssociativeContainer::iterator _Iterator; + typedef typename _SortedAssociativeContainer::const_iterator + _Const_iterator; + + _Iterator __p; + _Const_iterator __cp; + std::pair<_Iterator,_Iterator> __r; + std::pair<_Const_iterator,_Const_iterator> __cr; + typename _SortedAssociativeContainer::value_type *__first, *__last; + }; + + // HashedAssociativeContainer + +} // namespace __gnu_cxx + +#undef _IsUnused + +#endif // _GLIBCPP_BOOST_CONCEPT_CHECK + + diff --git a/contrib/libstdc++/include/bits/c++config b/contrib/libstdc++/include/bits/c++config new file mode 100644 index 0000000000000..d5bf45841e583 --- /dev/null +++ b/contrib/libstdc++/include/bits/c++config @@ -0,0 +1,77 @@ +// Predefined symbols and macros -*- C++ -*- + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef _CPP_CPPCONFIG +#define _CPP_CPPCONFIG 1 + +// Pick up any OS-specific definitions. +#include <bits/os_defines.h> + +// The current version of the C++ library in compressed ISO date format. +#define __GLIBCPP__ 20020513 + +// This is necessary until GCC supports separate template +// compilation. +#define _GLIBCPP_NO_TEMPLATE_EXPORT 1 + +// This is a hack around not having either pre-compiled headers or +// export compilation. If defined, the io, string, and valarray +// headers will include all the necessary bits. If not defined, the +// implementation optimizes the headers for the most commonly-used +// types. For the io library, this means that larger, out-of-line +// member functions are only declared, and definitions are not parsed +// by the compiler, but instead instantiated into the library binary. +#define _GLIBCPP_FULLY_COMPLIANT_HEADERS 1 + +// To enable older, ARM-style iostreams and other anachronisms use this. +//#define _GLIBCPP_DEPRECATED 1 + +// Use corrected code from the committee library group's issues list. +#define _GLIBCPP_RESOLVE_LIB_DEFECTS 1 + +// 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 +// threading models has been removed. Note: gthr.h may well map to +// gthr-single.h which is a correct way to express no threads support +// in gcc. Support for the undocumented _NOTHREADS has been removed. + +// Default to the typically high-speed, pool-based allocator (as +// libstdc++-v2) instead of the malloc-based allocator (libstdc++-v3 +// snapshots). See libstdc++-v3/docs/html/17_intro/howto.html for +// details on why you don't want to override this setting. Ensure +// 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. + +// The remainder of the prewritten config is mostly automatic; all the +// user hooks are listed above. + +// End of prewritten config; the discovered settings follow. diff --git a/contrib/libstdc++/include/bits/char_traits.h b/contrib/libstdc++/include/bits/char_traits.h new file mode 100644 index 0000000000000..7d14838ab2687 --- /dev/null +++ b/contrib/libstdc++/include/bits/char_traits.h @@ -0,0 +1,280 @@ +// Character Traits for use by standard string and iostream -*- C++ -*- + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 21 Strings library +// + +/** @file char_traits.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_CHAR_TRAITS_H +#define _CPP_BITS_CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include <cstring> // For memmove, memset, memchr +#include <bits/fpos.h> // For streampos + +namespace std +{ + /// 21.1.2 Basis for explicit _Traits specialization + /// NB: That for any given actual character type this definition is + /// probably wrong. + template<class _CharT> + struct char_traits + { + typedef _CharT char_type; + // Unsigned as wint_t in 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; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __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; + } + + static size_t + length(const char_type* __s) + { + const char_type* __p = __s; + while (*__p) ++__p; + return (__p - __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; + } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { return (char_type*) memmove(__s1, __s2, __n * sizeof(char_type)); } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { return (char_type*) memcpy(__s1, __s2, __n * sizeof(char_type)); } + + 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; + } + + static char_type + to_char_type(const int_type& __c) + { return char_type(__c); } + + static int_type + to_int_type(const char_type& __c) { return int_type(__c); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() { return static_cast<int_type>(-1); } + + static int_type + not_eof(const int_type& __c) + { return eq_int_type(__c, eof()) ? int_type(0) : __c; } + }; + + + /// 21.1.4 char_traits specializations + template<> + struct char_traits<char> + { + typedef char char_type; + typedef int 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; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { return memcmp(__s1, __s2, __n); } + + static size_t + length(const char_type* __s) + { return strlen(__s); } + + static const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { return static_cast<const char_type*>(memchr(__s, __a, __n)); } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { return static_cast<char_type*>(memmove(__s1, __s2, __n)); } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { return static_cast<char_type*>(memcpy(__s1, __s2, __n)); } + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { return static_cast<char_type*>(memset(__s, __a, __n)); } + + static char_type + to_char_type(const int_type& __c) + { return static_cast<char_type>(__c); } + + // To keep both the byte 0xff and the eof symbol 0xffffffff + // from ending up as 0xffffffff. + static int_type + to_int_type(const char_type& __c) + { return static_cast<int_type>(static_cast<unsigned char>(__c)); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() { return static_cast<int_type>(EOF); } + + static int_type + not_eof(const int_type& __c) + { return (__c == eof()) ? 0 : __c; } + }; + + +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + struct char_traits<wchar_t> + { + typedef wchar_t char_type; + typedef wint_t int_type; + typedef streamoff off_type; + typedef wstreampos pos_type; + typedef mbstate_t state_type; + + static void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { return wmemcmp(__s1, __s2, __n); } + + static size_t + length(const char_type* __s) + { return wcslen(__s); } + + static const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { return wmemchr(__s, __a, __n); } + + static char_type* + move(char_type* __s1, const char_type* __s2, int_type __n) + { return wmemmove(__s1, __s2, __n); } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { return wmemcpy(__s1, __s2, __n); } + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { return wmemset(__s, __a, __n); } + + static char_type + to_char_type(const int_type& __c) { return char_type(__c); } + + static int_type + to_int_type(const char_type& __c) { return int_type(__c); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() { return static_cast<int_type>(WEOF); } + + static int_type + not_eof(const int_type& __c) + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCPP_USE_WCHAR_T + + template<typename _CharT, typename _Traits> + struct _Char_traits_match + { + _CharT _M_c; + _Char_traits_match(_CharT const& __c) : _M_c(__c) { } + + bool + operator()(_CharT const& __a) { return _Traits::eq(_M_c, __a); } + }; +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/codecvt.h b/contrib/libstdc++/include/bits/codecvt.h new file mode 100644 index 0000000000000..506752f3432c1 --- /dev/null +++ b/contrib/libstdc++/include/bits/codecvt.h @@ -0,0 +1,336 @@ +// Locale support (codecvt) -*- C++ -*- + +// Copyright (C) 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 22.2.1.5 Template class codecvt +// + +// Written by Benjamin Kosnik <bkoz@cygnus.com> + +/** @file codecvt.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_CODECVT_H +#define _CPP_BITS_CODECVT_H 1 + +#pragma GCC system_header + + // 22.2.1.5 Template class codecvt + class codecvt_base + { + public: + enum result + { + ok, + partial, + error, + noconv + }; + }; + + // Template class __codecvt_abstract_base + // NB: An abstract base class that fills in the public inlines, so + // that the specializations don't have to re-copy the public + // interface. + template<typename _InternT, typename _ExternT, typename _StateT> + class __codecvt_abstract_base + : public locale::facet, public codecvt_base + { + public: + // Types: + 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 + out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const + { + return this->do_out(__state, __from, __from_end, __from_next, + __to, __to_end, __to_next); + } + + result + unshift(state_type& __state, extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const + { return this->do_unshift(__state, __to,__to_end,__to_next); } + + result + in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const + { + return this->do_in(__state, __from, __from_end, __from_next, + __to, __to_end, __to_next); + } + + int + encoding() const throw() + { return this->do_encoding(); } + + bool + always_noconv() const throw() + { return this->do_always_noconv(); } + + int + length(const state_type& __state, const extern_type* __from, + const extern_type* __end, size_t __max) const + { return this->do_length(__state, __from, __end, __max); } + + int + max_length() const throw() + { return this->do_max_length(); } + + protected: + explicit + __codecvt_abstract_base(size_t __refs = 0) : locale::facet(__refs) { } + + virtual + ~__codecvt_abstract_base() { } + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const = 0; + + virtual result + do_unshift(state_type& __state, extern_type* __to, + extern_type* __to_end, extern_type*& __to_next) const = 0; + + virtual result + do_in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const = 0; + + virtual int + do_encoding() const throw() = 0; + + virtual bool + do_always_noconv() const throw() = 0; + + virtual int + do_length(const state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const = 0; + + virtual int + do_max_length() const throw() = 0; + }; + + // 22.2.1.5 Template class codecvt + // NB: Generic, mostly useless implementation. + template<typename _InternT, typename _ExternT, typename _StateT> + class codecvt + : public __codecvt_abstract_base<_InternT, _ExternT, _StateT> + { + public: + // Types: + typedef codecvt_base::result result; + typedef _InternT intern_type; + typedef _ExternT extern_type; + typedef _StateT state_type; + + // Data Members: + static locale::id id; + + explicit + codecvt(size_t __refs = 0) + : __codecvt_abstract_base<_InternT,_ExternT,_StateT> (__refs) { } + + protected: + virtual + ~codecvt() { } + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_unshift(state_type& __state, extern_type* __to, + extern_type* __to_end, extern_type*& __to_next) const; + + virtual result + do_in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const; + + virtual int + do_encoding() const throw(); + + virtual bool + do_always_noconv() const throw(); + + virtual int + do_length(const state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const; + + virtual int + do_max_length() const throw(); + }; + + template<typename _InternT, typename _ExternT, typename _StateT> + locale::id codecvt<_InternT, _ExternT, _StateT>::id; + + // codecvt<char, char, mbstate_t> required specialization + template<> + class codecvt<char, char, mbstate_t> + : public __codecvt_abstract_base<char, char, mbstate_t> + { + public: + // Types: + typedef char intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + // Data Members: + static locale::id id; + + explicit + codecvt(size_t __refs = 0); + + protected: + virtual + ~codecvt(); + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_unshift(state_type& __state, extern_type* __to, + extern_type* __to_end, extern_type*& __to_next) const; + + virtual result + do_in(state_type& __state, const extern_type* __from, + const extern_type* __from_end, const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const; + + virtual int + do_encoding() const throw(); + + virtual bool + do_always_noconv() const throw(); + + virtual int + do_length(const state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const; + + virtual int + do_max_length() const throw(); + }; + +#ifdef _GLIBCPP_USE_WCHAR_T + // codecvt<wchar_t, char, mbstate_t> required specialization + template<> + class codecvt<wchar_t, char, mbstate_t> + : public __codecvt_abstract_base<wchar_t, char, mbstate_t> + { + public: + // Types: + typedef wchar_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + // Data Members: + static locale::id id; + + explicit + codecvt(size_t __refs = 0); + + protected: + virtual + ~codecvt(); + + virtual result + do_out(state_type& __state, const intern_type* __from, + const intern_type* __from_end, const intern_type*& __from_next, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_unshift(state_type& __state, + extern_type* __to, extern_type* __to_end, + extern_type*& __to_next) const; + + virtual result + do_in(state_type& __state, + const extern_type* __from, const extern_type* __from_end, + const extern_type*& __from_next, + intern_type* __to, intern_type* __to_end, + intern_type*& __to_next) const; + + virtual + int do_encoding() const throw(); + + virtual + bool do_always_noconv() const throw(); + + virtual + int do_length(const state_type&, const extern_type* __from, + const extern_type* __end, size_t __max) const; + + virtual int + do_max_length() const throw(); + }; +#endif //_GLIBCPP_USE_WCHAR_T + + // 22.2.1.6 Template class codecvt_byname + template<typename _InternT, typename _ExternT, typename _StateT> + class codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> + { + public: + explicit + codecvt_byname(const char*, size_t __refs = 0) + : codecvt<_InternT, _ExternT, _StateT>(__refs) { } + protected: + virtual + ~codecvt_byname() { } + }; + + // Include host and configuration specific partial specializations + // with additional functionality, if possible. +#ifdef _GLIBCPP_USE_WCHAR_T + #include <bits/codecvt_specializations.h> +#endif + +#endif // _CPP_BITS_CODECVT_H diff --git a/contrib/libstdc++/include/bits/concept_check.h b/contrib/libstdc++/include/bits/concept_check.h new file mode 100644 index 0000000000000..92ceefbd685e0 --- /dev/null +++ b/contrib/libstdc++/include/bits/concept_check.h @@ -0,0 +1,86 @@ +// Concept-checking control -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file concept_check.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _GLIBCPP_CONCEPT_CHECK +#define _GLIBCPP_CONCEPT_CHECK 1 + +#pragma GCC system_header + +#include <bits/c++config.h> + +// All places in libstdc++-v3 where these are used, or /might/ be used, or +// don't need to be used, or perhaps /should/ be used, are commented with +// "concept requirements" (and maybe some more text). So grep like crazy +// if you're looking for additional places to use these. + +// Concept-checking code is off by default unless users turn it on via +// configure options or editing c++config.h. + +#ifndef _GLIBCPP_CONCEPT_CHECKS + +#define __glibcpp_function_requires(...) +#define __glibcpp_class_requires(_a,_b) +#define __glibcpp_class_requires2(_a,_b,_c) +#define __glibcpp_class_requires3(_a,_b,_c,_d) +#define __glibcpp_class_requires4(_a,_b,_c,_d,_e) + +#else // the checks are on + +#include <bits/boost_concept_check.h> + +// Note that the obvious and elegant approach of +// +//#define glibcpp_function_requires(C) \ +// boost::function_requires< boost::C >() +// +// won't work due to concept templates with more than one parameter, e.g., +// BinaryPredicateConcept. The preprocessor tries to split things up on +// the commas in the template argument list. We can't use an inner pair of +// parenthesis to hide the commas, because "boost::(Temp<Foo,Bar>)" isn't +// a valid instantiation pattern. Thus, we steal a feature from C99. + +#define __glibcpp_function_requires(...) \ + __gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >(); +#define __glibcpp_class_requires(_a,_C) \ + _GLIBCPP_CLASS_REQUIRES(_a, __gnu_cxx, _C); +#define __glibcpp_class_requires2(_a,_b,_C) \ + _GLIBCPP_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C); +#define __glibcpp_class_requires3(_a,_b,_c,_C) \ + _GLIBCPP_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C); +#define __glibcpp_class_requires4(_a,_b,_c,_d,_C) \ + _GLIBCPP_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C); + +#endif // enable/disable + +#endif // _GLIBCPP_CONCEPT_CHECK diff --git a/contrib/libstdc++/include/bits/cpp_type_traits.h b/contrib/libstdc++/include/bits/cpp_type_traits.h new file mode 100644 index 0000000000000..d66fe7638410f --- /dev/null +++ b/contrib/libstdc++/include/bits/cpp_type_traits.h @@ -0,0 +1,300 @@ +// The -*- C++ -*- type traits classes for internal use in libstdc++ + +// Copyright (C) 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr> + +/** @file cpp_type_traits.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_CPP_TYPE_TRAITS_H +#define _CPP_BITS_CPP_TYPE_TRAITS_H 1 + +#pragma GCC system_header + +// +// This file provides some compile-time information about various types. +// These representations were designed, on purpose, to be constant-expressions +// and not types as found in <stl/bits/type_traits.h>. In particular, they +// can be used in control structures and the optimizer hopefully will do +// the obvious thing. +// +// Why integral expressions, and not functions nor types? +// Firstly, these compile-time entities are used as template-arguments +// so function return values won't work: We need compile-time entities. +// We're left with types and constant integral expressions. +// Secondly, from the point of view of ease of use, type-based compile-time +// information is -not- *that* convenient. On has to write lots of +// overloaded functions and to hope that the compiler will select the right +// one. As a net effect, the overall structure isn't very clear at first +// glance. +// Thirdly, partial ordering and overload resolution (of function templates) +// is highly costly in terms of compiler-resource. It is a Good Thing to +// keep these resource consumption as least as possible. +// +// See valarray_array.h for a case use. +// +// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. +// + +namespace std +{ + template<typename _Tp> + struct __is_void + { + enum + { + _M_type = 0 + }; + }; + + template<> + struct __is_void<void> + { + enum + { + _M_type = 1 + }; + }; + + // + // Integer types + // + template<typename _Tp> + struct __is_integer + { + enum + { + _M_type = 0 + }; + }; + + // Thirteen specializations (yes there are eleven standard integer + // types; 'long long' and 'unsigned long long' are supported as + // extensions) + template<> + struct __is_integer<bool> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<char> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<signed char> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<unsigned char> + { + enum + { + _M_type = 1 + }; + }; + +# ifdef _GLIBCPP_USE_WCHAR_T + template<> + struct __is_integer<wchar_t> + { + enum + { + _M_type = 1 + }; + }; +# endif + + template<> + struct __is_integer<short> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<unsigned short> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<int> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<unsigned int> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<long> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<unsigned long> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<long long> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_integer<unsigned long long> + { + enum + { + _M_type = 1 + }; + }; + + // + // Floating point types + // + template<typename _Tp> + struct __is_floating + { + enum + { + _M_type = 0 + }; + }; + + // three specializations (float, double and 'long double') + template<> + struct __is_floating<float> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_floating<double> + { + enum + { + _M_type = 1 + }; + }; + + template<> + struct __is_floating<long double> + { + enum + { + _M_type = 1 + }; + }; + + // + // An arithmetic type is an integer type or a floating point type + // + template<typename _Tp> + struct __is_arithmetic + { + enum + { + _M_type = __is_integer<_Tp>::_M_type || __is_floating<_Tp>::_M_type + }; + }; + + // + // A fundamental type is `void' or and arithmetic type + // + template<typename _Tp> + struct __is_fundamental + { + enum + { + _M_type = __is_void<_Tp>::_M_type || __is_arithmetic<_Tp>::_M_type + }; + }; + + // + // For the immediate use, the following is a good approximation + // + template<typename _Tp> + struct __is_pod + { + enum + { + _M_type = __is_fundamental<_Tp>::_M_type + }; + }; + +} // namespace std + + +#endif //_CPP_BITS_CPP_TYPE_TRAITS_H diff --git a/contrib/libstdc++/include/bits/fpos.h b/contrib/libstdc++/include/bits/fpos.h new file mode 100644 index 0000000000000..3cb3e4b51a261 --- /dev/null +++ b/contrib/libstdc++/include/bits/fpos.h @@ -0,0 +1,123 @@ +// File position object and stream types + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27 Input/output library +// + +/** @file fpos.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_FPOS_H +#define _CPP_BITS_FPOS_H 1 + +#pragma GCC system_header + +#include <bits/c++io.h> +#include <cwchar> // For mbstate_t. + +namespace std +{ + // 27.4.1 Types + + // 27.4.3 Template class fpos + template<typename _StateT> + class fpos + { + public: + // Types: + typedef _StateT __state_type; + + private: + streamoff _M_off; + __state_type _M_st; + + public: + __state_type + state() const { return _M_st; } + + void + state(__state_type __st) { _M_st = __st; } + + // NB: The standard defines only the implicit copy ctor and the + // previous two members. The rest is a "conforming extension". + fpos(): _M_off(streamoff()), _M_st(__state_type()) { } + + fpos(streamoff __off, __state_type __st = __state_type()) + : _M_off(__off), _M_st(__st) { } + + operator streamoff() const { return _M_off; } + + fpos& + operator+=(streamoff __off) { _M_off += __off; return *this; } + + fpos& + operator-=(streamoff __off) { _M_off -= __off; return *this; } + + fpos + operator+(streamoff __off) + { + fpos __t(*this); + __t += __off; + return __t; + } + + fpos + operator-(streamoff __off) + { + fpos __t(*this); + __t -= __off; + return __t; + } + + bool + operator==(const fpos& __pos) const + { return _M_off == __pos._M_off; } + + bool + operator!=(const fpos& __pos) const + { return _M_off != __pos._M_off; } + + streamoff + _M_position() const { return _M_off; } + + void + _M_position(streamoff __off) { _M_off = __off; } + }; + + // 27.2, paragraph 10 about fpos/char_traits circularity + typedef fpos<mbstate_t> streampos; +# ifdef _GLIBCPP_USE_WCHAR_T + typedef fpos<mbstate_t> wstreampos; +# endif +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/fstream.tcc b/contrib/libstdc++/include/bits/fstream.tcc new file mode 100644 index 0000000000000..90850f54f0d70 --- /dev/null +++ b/contrib/libstdc++/include/bits/fstream.tcc @@ -0,0 +1,589 @@ +// File based streams -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.8 File-based streams +// + +#ifndef _CPP_BITS_FSTREAM_TCC +#define _CPP_BITS_FSTREAM_TCC 1 + +#pragma GCC system_header + +namespace std +{ + template<typename _CharT, typename _Traits> + void + basic_filebuf<_CharT, _Traits>:: + _M_allocate_internal_buffer() + { + if (!_M_buf && _M_buf_size_opt) + { + _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_allocated = true; + } + } + + // Both close and setbuf need to deallocate internal buffers, if it exists. + template<typename _CharT, typename _Traits> + void + basic_filebuf<_CharT, _Traits>:: + _M_destroy_internal_buffer() + { + if (_M_buf_allocated) + { + delete [] _M_buf; + _M_buf = NULL; + _M_buf_allocated = false; + this->setg(NULL, NULL, NULL); + this->setp(NULL, NULL); + } + } + + template<typename _CharT, typename _Traits> + basic_filebuf<_CharT, _Traits>:: + 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* + basic_filebuf<_CharT, _Traits>:: + open(const char* __s, ios_base::openmode __mode) + { + __filebuf_type *__ret = NULL; + if (!this->is_open()) + { + _M_file.open(__s, __mode); + if (this->is_open()) + { + _M_allocate_internal_buffer(); + _M_mode = __mode; + + // For time being, set both (in/out) sets of pointers. + _M_set_indeterminate(); + if ((__mode & ios_base::ate) + && this->seekoff(0, ios_base::end, __mode) < 0) + this->close(); + __ret = this; + } + } + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::__filebuf_type* + basic_filebuf<_CharT, _Traits>:: + close() + { + __filebuf_type *__ret = NULL; + if (this->is_open()) + { + 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) + 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 0 + // XXX not done + if (_M_last_overflowed) + { + _M_output_unshift(); + _M_really_overflow(__eof); + } +#endif + + if (_M_file.close()) + __ret = this; + } + + _M_last_overflowed = false; + return __ret; + } + + template<typename _CharT, typename _Traits> + streamsize + basic_filebuf<_CharT, _Traits>:: + showmanyc() + { + streamsize __ret = -1; + 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>:: + _M_underflow_common(bool __bump) + { + 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(); + else if (_M_in_cur != _M_filepos) + _M_file.seekoff(_M_in_cur - _M_filepos, + 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 (__bump) + _M_in_cur_move(1); + else if (_M_buf_size == 1) + { + // If we are synced with stdio, we have to unget the + // character we just read so that the file pointer + // doesn't move. + _M_file.sys_ungetc(*_M_in_cur); + _M_set_indeterminate(); + } + } + } + } + _M_last_overflowed = false; + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::int_type + basic_filebuf<_CharT, _Traits>:: + pbackfail(int_type __i) + { + int_type __ret = traits_type::eof(); + bool __testin = _M_mode & ios_base::in; + + if (__testin) + { + bool __testpb = _M_in_beg < _M_in_cur; + char_type __c = traits_type::to_char_type(__i); + bool __testeof = traits_type::eq_int_type(__i, __ret); + + if (__testpb) + { + bool __testout = _M_mode & ios_base::out; + bool __testeq = traits_type::eq(__c, this->gptr()[-1]); + + // Try to put back __c into input sequence in one of three ways. + // Order these tests done in is unspecified by the standard. + if (!__testeof && __testeq) + { + --_M_in_cur; + if (__testout) + --_M_out_cur; + __ret = __i; + } + else if (__testeof) + { + --_M_in_cur; + if (__testout) + --_M_out_cur; + __ret = traits_type::not_eof(__i); + } + else if (!__testeof) + { + --_M_in_cur; + if (__testout) + --_M_out_cur; + _M_pback_create(); + *_M_in_cur = __c; + __ret = __i; + } + } + else + { + // At the beginning of the buffer, need to make a + // putback position available. + this->seekoff(-1, ios_base::cur); + this->underflow(); + if (!__testeof) + { + if (!traits_type::eq(__c, *_M_in_cur)) + { + _M_pback_create(); + *_M_in_cur = __c; + } + __ret = __i; + } + else + __ret = traits_type::not_eof(__i); + } + } + _M_last_overflowed = false; + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::int_type + basic_filebuf<_CharT, _Traits>:: + overflow(int_type __c) + { + int_type __ret = traits_type::eof(); + bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size; + bool __testout = _M_mode & ios_base::out; + + if (__testout) + { + if (__testput) + { + *_M_out_cur = traits_type::to_char_type(__c); + _M_out_cur_move(1); + __ret = traits_type::not_eof(__c); + } + else + __ret = this->_M_really_overflow(__c); + } + + _M_last_overflowed = false; // Set in _M_really_overflow, below. + return __ret; + } + + template<typename _CharT, typename _Traits> + void + basic_filebuf<_CharT, _Traits>:: + _M_convert_to_external(_CharT* __ibuf, streamsize __ilen, + streamsize& __elen, streamsize& __plen) + { + const locale __loc = this->getloc(); + const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); + + if (__cvt.always_noconv() && __ilen) + { + __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen); + __plen += __ilen; + } + else + { + // Worst-case number of external bytes needed. + int __ext_multiplier = __cvt.encoding(); + if (__ext_multiplier == -1 || __ext_multiplier == 0) + __ext_multiplier = sizeof(char_type); + streamsize __blen = __ilen * __ext_multiplier; + char* __buf = static_cast<char*>(__builtin_alloca(__blen)); + char* __bend; + const char_type* __iend; + __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, + __iend, __buf, __buf + __blen, __bend); + // Result == ok, partial, noconv + if (__r != codecvt_base::error) + __blen = __bend - __buf; + // Result == error + else + __blen = 0; + + if (__blen) + { + __elen += _M_file.xsputn(__buf, __blen); + __plen += __blen; + } + + // Try once more for partial conversions. + if (__r == codecvt_base::partial) + { + const char_type* __iresume = __iend; + streamsize __rlen = _M_out_end - __iend; + __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, + __iend, __buf, __buf + __blen, __bend); + if (__r != codecvt_base::error) + __rlen = __bend - __buf; + else + __rlen = 0; + if (__rlen) + { + __elen += _M_file.xsputn(__buf, __rlen); + __plen += __rlen; + } + } + } + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::int_type + basic_filebuf<_CharT, _Traits>:: + _M_really_overflow(int_type __c) + { + int_type __ret = traits_type::eof(); + bool __testput = _M_out_cur && _M_out_beg < _M_out_end; + bool __testunbuffered = _M_file.is_open() && !_M_buf_size; + + if (__testput || __testunbuffered) + { + // Sizes of external and pending output. + 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) + _M_convert_to_external(_M_out_beg, _M_out_end - _M_out_beg, + __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); + + // 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); + } + } + _M_last_overflowed = true; + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::__streambuf_type* + basic_filebuf<_CharT, _Traits>:: + setbuf(char_type* __s, streamsize __n) + { + if (!this->is_open() && __s == 0 && __n == 0) + _M_buf_size_opt = 0; + else if (__s && __n) + { + // This is implementation-defined behavior, and assumes + // that an external char_type array of length (__s + __n) + // exists and has been pre-allocated. If this is not the + // case, things will quickly blow up. + // Step 1: Destroy the current internal array. + _M_destroy_internal_buffer(); + + // Step 2: Use the external array. + _M_buf = __s; + _M_buf_size_opt = _M_buf_size = __n; + _M_set_indeterminate(); + } + _M_last_overflowed = false; + return this; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::pos_type + basic_filebuf<_CharT, _Traits>:: + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) + { + pos_type __ret = pos_type(off_type(-1)); + 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; + + if (this->is_open() && !__testfail && (__testin || __testout)) + { + // Ditch any pback buffers to avoid confusion. + _M_pback_destroy(); + + if (__way != ios_base::cur || __off != 0) + { + off_type __computed_off = __width * __off; + + bool __testget = _M_in_cur && _M_in_beg < _M_in_end; + bool __testput = _M_out_cur && _M_out_beg < _M_out_end; + // Sync the internal and external streams. + // out + if (__testput || _M_last_overflowed) + { + // Part one: update the output sequence. + this->sync(); + // Part two: output unshift sequence. + _M_output_unshift(); + } + //in + else if (__testget && __way == ios_base::cur) + __computed_off += _M_in_cur - _M_filepos; + + __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 + else + { + __ret = _M_file.seekoff(__off, ios_base::cur, __mode); + __ret += max(_M_out_cur, _M_in_cur) - _M_filepos; + } + } + _M_last_overflowed = false; + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_filebuf<_CharT, _Traits>::pos_type + basic_filebuf<_CharT, _Traits>:: + seekpos(pos_type __pos, ios_base::openmode __mode) + { +#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> + void + basic_filebuf<_CharT, _Traits>:: + _M_output_unshift() + { } + + template<typename _CharT, typename _Traits> + void + basic_filebuf<_CharT, _Traits>:: + imbue(const locale& __loc) + { + bool __testbeg = gptr() == eback() && pptr() == pbase(); + + if (__testbeg && _M_buf_locale != __loc) + { + _M_buf_locale = __loc; + _M_buf_locale_init = true; + } + + // NB this may require the reconversion of previously + // converted chars. This in turn may cause the reconstruction + // of the original file. YIKES!! + // XXX The part in the above comment is not done. + _M_last_overflowed = false; + } + + // Inhibit implicit instantiations for required instantiations, + // 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>; + extern template class basic_fstream<wchar_t>; +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/functexcept.h b/contrib/libstdc++/include/bits/functexcept.h new file mode 100644 index 0000000000000..eac2c95b4327a --- /dev/null +++ b/contrib/libstdc++/include/bits/functexcept.h @@ -0,0 +1,85 @@ +// Function-Based Exception Support -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 19.1 Exception classes +// + +#include <exception_defines.h> + +namespace std +{ + // Helper for exception objects in <except> + void + __throw_bad_exception(void); + + // Helper for exception objects in <new> + void + __throw_bad_alloc(void); + + // Helper for exception objects in <typeinfo> + void + __throw_bad_cast(void); + + void + __throw_bad_typeid(void); + + // Helpers for exception objects in <stdexcept> + void + __throw_logic_error(const char* __s); + + void + __throw_domain_error(const char* __s); + + void + __throw_invalid_argument(const char* __s); + + void + __throw_length_error(const char* __s); + + void + __throw_out_of_range(const char* __s); + + void + __throw_runtime_error(const char* __s); + + void + __throw_range_error(const char* __s); + + void + __throw_overflow_error(const char* __s); + + void + __throw_underflow_error(const char* __s); + + // Helpers for exception objects in basic_ios + void + __throw_ios_failure(const char* __s); +} // namespace std + diff --git a/contrib/libstdc++/include/bits/generic_shadow.h b/contrib/libstdc++/include/bits/generic_shadow.h new file mode 100644 index 0000000000000..b87e71702e86b --- /dev/null +++ b/contrib/libstdc++/include/bits/generic_shadow.h @@ -0,0 +1,59 @@ +// generic C header shadow file -*- C++ -*- + +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// This file is included by all the standard C <foo.h> headers +// after defining _SHADOW_NAME. + +#ifdef _IN_C_LEGACY_ /* sub-included by a C header */ + + // Get out of the "swamp." + } // Close extern "C" + } // Close namespace _C_legacy:: + +# undef _IN_C_LEGACY_ +# include _SHADOW_NAME + + // Dive back into the "swamp." + namespace _C_legacy { + extern "C" { +# define _IN_C_LEGACY_ + +#else /* not _IN_C_LEGACY_: directly included by user program */ + +# include _SHADOW_NAME + + // Expose global C names, including non-standard ones, but shadow + // some names and types with the std:: C++ version. + + using namespace ::_C_legacy::_C_shadow; + +#endif /* _IN_C_LEGACY_ */ + + + diff --git a/contrib/libstdc++/include/bits/gslice.h b/contrib/libstdc++/include/bits/gslice.h new file mode 100644 index 0000000000000..95781f9bbcc24 --- /dev/null +++ b/contrib/libstdc++/include/bits/gslice.h @@ -0,0 +1,124 @@ +// The template and inlines for the -*- C++ -*- gslice class. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file gslice.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_GSLICE_H +#define _CPP_BITS_GSLICE_H 1 + +#pragma GCC system_header + +namespace std { + + class gslice + { + public: + gslice (); + gslice (size_t, const valarray<size_t>&, const valarray<size_t>&); + // XXX: the IS says the copy-ctor and copy-assignment operators are + // synthetized by the compiler but they are just unsuitable + // for a ref-counted semantic + gslice(const gslice&); + ~gslice(); + + // XXX: See the note above. + gslice& operator= (const gslice&); + + size_t start () const; + valarray<size_t> size () const; + valarray<size_t> stride () const; + + private: + struct _Indexer { + size_t _M_count; + size_t _M_start; + valarray<size_t> _M_size; + valarray<size_t> _M_stride; + valarray<size_t> _M_index; + _Indexer(size_t, const valarray<size_t>&, + const valarray<size_t>&); + void _M_increment_use() { ++_M_count; } + size_t _M_decrement_use() { return --_M_count; } + }; + + _Indexer* _M_index; + + template<typename _Tp> friend class valarray; + }; + + inline size_t + gslice::start () const + { return _M_index ? _M_index->_M_start : 0; } + + inline valarray<size_t> + gslice::size () const + { return _M_index ? _M_index->_M_size : valarray<size_t>(); } + + inline valarray<size_t> + gslice::stride () const + { return _M_index ? _M_index->_M_stride : valarray<size_t>(); } + + inline gslice::gslice () : _M_index(0) {} + + inline + gslice::gslice(size_t __o, const valarray<size_t>& __l, + const valarray<size_t>& __s) + : _M_index(new gslice::_Indexer(__o, __l, __s)) {} + + inline + gslice::gslice(const gslice& __g) : _M_index(__g._M_index) + { if (_M_index) _M_index->_M_increment_use(); } + + inline + gslice::~gslice() + { if (_M_index && _M_index->_M_decrement_use() == 0) delete _M_index; } + + inline gslice& + gslice::operator= (const gslice& __g) + { + if (__g._M_index) __g._M_index->_M_increment_use(); + if (_M_index && _M_index->_M_decrement_use() == 0) delete _M_index; + _M_index = __g._M_index; + return *this; + } + + +} // std:: + + +#endif /* _CPP_BITS_GSLICE_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/gslice_array.h b/contrib/libstdc++/include/bits/gslice_array.h new file mode 100644 index 0000000000000..8989ac5200efb --- /dev/null +++ b/contrib/libstdc++/include/bits/gslice_array.h @@ -0,0 +1,176 @@ +// The template and inlines for the -*- C++ -*- gslice_array class. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file gslice_array.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_GSLICE_ARRAY +#define _CPP_BITS_GSLICE_ARRAY 1 + +#pragma GCC system_header + +namespace std { + + template<typename _Tp> class gslice_array + { + public: + typedef _Tp value_type; + + void operator= (const valarray<_Tp>&) const; + void operator*= (const valarray<_Tp>&) const; + void operator/= (const valarray<_Tp>&) const; + void operator%= (const valarray<_Tp>&) const; + void operator+= (const valarray<_Tp>&) const; + void operator-= (const valarray<_Tp>&) const; + void operator^= (const valarray<_Tp>&) const; + void operator&= (const valarray<_Tp>&) const; + void operator|= (const valarray<_Tp>&) const; + void operator<<=(const valarray<_Tp>&) const; + void operator>>=(const valarray<_Tp>&) const; + void operator=(const _Tp&); + + template<class _Dom> + void operator= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator*= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator/= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator%= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator+= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator-= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator^= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator&= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator|= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator<<= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator>>= (const _Expr<_Dom,_Tp>&) const; + + private: + _Array<_Tp> _M_array; + const valarray<size_t>& _M_index; + + friend class valarray<_Tp>; + + gslice_array (_Array<_Tp>, const valarray<size_t>&); + + // this constructor needs to be implemented. + gslice_array (const gslice_array&); + + // not implemented + gslice_array(); + gslice_array& operator= (const gslice_array&); + }; + + template<typename _Tp> + inline + gslice_array<_Tp>::gslice_array (_Array<_Tp> __a, + const valarray<size_t>& __i) + : _M_array (__a), _M_index (__i) {} + + + template<typename _Tp> + inline + gslice_array<_Tp>::gslice_array (const gslice_array<_Tp>& __a) + : _M_array (__a._M_array), _M_index (__a._M_index) {} + + + template<typename _Tp> + inline void + gslice_array<_Tp>::operator= (const _Tp& __t) + { + __valarray_fill (_M_array, _Array<size_t>(_M_index), + _M_index.size(), __t); + } + + template<typename _Tp> + inline void + gslice_array<_Tp>::operator= (const valarray<_Tp>& __v) const + { + __valarray_copy (_Array<_Tp> (__v), __v.size (), + _M_array, _Array<size_t>(_M_index)); + } + + template<typename _Tp> + template<class E> + inline void + gslice_array<_Tp>::operator= (const _Expr<E, _Tp>& __e) const + { + __valarray_copy (__e, _M_index.size(), _M_array, + _Array<size_t>(_M_index)); + } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(op, name) \ +template<typename _Tp> \ +inline void \ +gslice_array<_Tp>::operator op##= (const valarray<_Tp>& __v) const \ +{ \ + _Array_augmented_##name (_M_array, _Array<size_t>(_M_index), \ + _Array<_Tp> (__v), __v.size ()); \ +} \ + \ +template<typename _Tp> template<class E> \ +inline void \ +gslice_array<_Tp>::operator op##= (const _Expr<E, _Tp>& __e) const \ +{ \ + _Array_augmented_##name (_M_array, _Array<size_t>(_M_index), __e, \ + _M_index.size()); \ +} + +_DEFINE_VALARRAY_OPERATOR(*, multiplies) +_DEFINE_VALARRAY_OPERATOR(/, divides) +_DEFINE_VALARRAY_OPERATOR(%, modulus) +_DEFINE_VALARRAY_OPERATOR(+, plus) +_DEFINE_VALARRAY_OPERATOR(-, minus) +_DEFINE_VALARRAY_OPERATOR(^, xor) +_DEFINE_VALARRAY_OPERATOR(&, and) +_DEFINE_VALARRAY_OPERATOR(|, or) +_DEFINE_VALARRAY_OPERATOR(<<, shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + +} // std:: + +#endif /* _CPP_BITS_GSLICE_ARRAY */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/indirect_array.h b/contrib/libstdc++/include/bits/indirect_array.h new file mode 100644 index 0000000000000..a5737e9eb04d8 --- /dev/null +++ b/contrib/libstdc++/include/bits/indirect_array.h @@ -0,0 +1,176 @@ +// The template and inlines for the -*- C++ -*- indirect_array class. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file indirect_array.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_INDIRECT_ARRAY_H +#define _CPP_BITS_INDIRECT_ARRAY_H 1 + +#pragma GCC system_header + +namespace std +{ + template <class _Tp> + class indirect_array + { + public: + typedef _Tp value_type; + + // XXX: This is a proposed resolution for DR-253. + indirect_array& operator= (const indirect_array&); + + void operator= (const valarray<_Tp>&) const; + void operator*= (const valarray<_Tp>&) const; + void operator/= (const valarray<_Tp>&) const; + void operator%= (const valarray<_Tp>&) const; + void operator+= (const valarray<_Tp>&) const; + void operator-= (const valarray<_Tp>&) const; + void operator^= (const valarray<_Tp>&) const; + void operator&= (const valarray<_Tp>&) const; + void operator|= (const valarray<_Tp>&) const; + void operator<<= (const valarray<_Tp>&) const; + void operator>>= (const valarray<_Tp>&) const; + void operator= (const _Tp&); + // ~indirect_array(); + + template<class _Dom> + void operator= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator*= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator/= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator%= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator+= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator-= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator^= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator&= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator|= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator<<= (const _Expr<_Dom, _Tp>&) const; + template<class _Dom> + void operator>>= (const _Expr<_Dom, _Tp>&) const; + + private: + indirect_array (const indirect_array&); + indirect_array (_Array<_Tp>, size_t, _Array<size_t>); + + friend class valarray<_Tp>; + friend class gslice_array<_Tp>; + + const size_t _M_sz; + const _Array<size_t> _M_index; + const _Array<_Tp> _M_array; + + // not implemented + indirect_array (); + }; + + template<typename _Tp> + inline indirect_array<_Tp>::indirect_array(const indirect_array<_Tp>& __a) + : _M_sz (__a._M_sz), _M_index (__a._M_index), + _M_array (__a._M_array) {} + + template<typename _Tp> + inline + indirect_array<_Tp>::indirect_array (_Array<_Tp> __a, size_t __s, + _Array<size_t> __i) + : _M_sz (__s), _M_index (__i), _M_array (__a) {} + + template<typename _Tp> + inline indirect_array<_Tp>& + indirect_array<_Tp>::operator=(const indirect_array<_Tp>& __a) + { + __valarray_copy(__a._M_array, _M_sz, __a._M_index, _M_array, _M_index); + return *this; + } + + + template<typename _Tp> + inline void + indirect_array<_Tp>::operator= (const _Tp& __t) + { __valarray_fill(_M_array, _M_index, _M_sz, __t); } + + template<typename _Tp> + inline void + indirect_array<_Tp>::operator= (const valarray<_Tp>& __v) const + { __valarray_copy (_Array<_Tp> (__v), _M_sz, _M_array, _M_index); } + + template<typename _Tp> + template<class _Dom> + inline void + indirect_array<_Tp>::operator= (const _Expr<_Dom,_Tp>& __e) const + { __valarray_copy (__e, _M_sz, _M_array, _M_index); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(op, name) \ +template<typename _Tp> \ +inline void \ +indirect_array<_Tp>::operator op##= (const valarray<_Tp>& __v) const \ +{ \ + _Array_augmented_##name (_M_array, _M_index, _Array<_Tp> (__v), _M_sz); \ +} \ + \ +template<typename _Tp> template<class _Dom> \ +inline void \ +indirect_array<_Tp>::operator op##= (const _Expr<_Dom,_Tp>& __e) const \ +{ \ + _Array_augmented_##name (_M_array, _M_index, __e, _M_sz); \ +} + +_DEFINE_VALARRAY_OPERATOR(*, multiplies) +_DEFINE_VALARRAY_OPERATOR(/, divides) +_DEFINE_VALARRAY_OPERATOR(%, modulus) +_DEFINE_VALARRAY_OPERATOR(+, plus) +_DEFINE_VALARRAY_OPERATOR(-, minus) +_DEFINE_VALARRAY_OPERATOR(^, xor) +_DEFINE_VALARRAY_OPERATOR(&, and) +_DEFINE_VALARRAY_OPERATOR(|, or) +_DEFINE_VALARRAY_OPERATOR(<<, shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + +} // std:: + +#endif /* _CPP_BITS_INDIRECT_ARRAY_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/ios_base.h b/contrib/libstdc++/include/bits/ios_base.h new file mode 100644 index 0000000000000..f5b026900f606 --- /dev/null +++ b/contrib/libstdc++/include/bits/ios_base.h @@ -0,0 +1,589 @@ +// Iostreams base classes -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.8 File-based streams +// + +/** @file ios_base.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_IOSBASE_H +#define _CPP_BITS_IOSBASE_H 1 + +#pragma GCC system_header + +#include <bits/atomicity.h> + +namespace std +{ + // The following definitions of bitmask types are enums, not ints, + // as permitted (but not required) in the standard, in order to provide + // better type safety in iostream calls. A side effect is that + // expressions involving them are no longer compile-time constants. + enum _Ios_Fmtflags { _M_ios_fmtflags_end = 1L << 16 }; + + inline _Ios_Fmtflags + operator&(_Ios_Fmtflags __a, _Ios_Fmtflags __b) + { return _Ios_Fmtflags(static_cast<int>(__a) & static_cast<int>(__b)); } + + inline _Ios_Fmtflags + operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b) + { return _Ios_Fmtflags(static_cast<int>(__a) | static_cast<int>(__b)); } + + inline _Ios_Fmtflags + operator^(_Ios_Fmtflags __a, _Ios_Fmtflags __b) + { return _Ios_Fmtflags(static_cast<int>(__a) ^ static_cast<int>(__b)); } + + inline _Ios_Fmtflags + operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) + { return __a = __a | __b; } + + inline _Ios_Fmtflags + operator&=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) + { return __a = __a & __b; } + + inline _Ios_Fmtflags + operator^=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) + { return __a = __a ^ __b; } + + inline _Ios_Fmtflags + operator~(_Ios_Fmtflags __a) + { return _Ios_Fmtflags(~static_cast<int>(__a)); } + + + enum _Ios_Openmode { _M_ios_openmode_end = 1L << 16 }; + + inline _Ios_Openmode + operator&(_Ios_Openmode __a, _Ios_Openmode __b) + { return _Ios_Openmode(static_cast<int>(__a) & static_cast<int>(__b)); } + + inline _Ios_Openmode + operator|(_Ios_Openmode __a, _Ios_Openmode __b) + { return _Ios_Openmode(static_cast<int>(__a) | static_cast<int>(__b)); } + + inline _Ios_Openmode + operator^(_Ios_Openmode __a, _Ios_Openmode __b) + { return _Ios_Openmode(static_cast<int>(__a) ^ static_cast<int>(__b)); } + + inline _Ios_Openmode + operator|=(_Ios_Openmode& __a, _Ios_Openmode __b) + { return __a = __a | __b; } + + inline _Ios_Openmode + operator&=(_Ios_Openmode& __a, _Ios_Openmode __b) + { return __a = __a & __b; } + + inline _Ios_Openmode + operator^=(_Ios_Openmode& __a, _Ios_Openmode __b) + { return __a = __a ^ __b; } + + inline _Ios_Openmode + operator~(_Ios_Openmode __a) + { return _Ios_Openmode(~static_cast<int>(__a)); } + + + enum _Ios_Iostate { _M_ios_iostate_end = 1L << 16 }; + + inline _Ios_Iostate + operator&(_Ios_Iostate __a, _Ios_Iostate __b) + { return _Ios_Iostate(static_cast<int>(__a) & static_cast<int>(__b)); } + + inline _Ios_Iostate + operator|(_Ios_Iostate __a, _Ios_Iostate __b) + { return _Ios_Iostate(static_cast<int>(__a) | static_cast<int>(__b)); } + + inline _Ios_Iostate + operator^(_Ios_Iostate __a, _Ios_Iostate __b) + { return _Ios_Iostate(static_cast<int>(__a) ^ static_cast<int>(__b)); } + + inline _Ios_Iostate + operator|=(_Ios_Iostate& __a, _Ios_Iostate __b) + { return __a = __a | __b; } + + inline _Ios_Iostate + operator&=(_Ios_Iostate& __a, _Ios_Iostate __b) + { return __a = __a & __b; } + + inline _Ios_Iostate + operator^=(_Ios_Iostate& __a, _Ios_Iostate __b) + { return __a = __a ^ __b; } + + inline _Ios_Iostate + operator~(_Ios_Iostate __a) + { return _Ios_Iostate(~static_cast<int>(__a)); } + + enum _Ios_Seekdir { _M_ios_seekdir_end = 1L << 16 }; + + // 27.4.2 Class ios_base + class ios_base + { + public: + + // 27.4.2.1.1 Class ios_base::failure + class failure : public exception + { + public: +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //48. Use of non-existent exception constructor + 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(); + + virtual const char* + what() const throw(); + + private: + enum { _M_bufsize = 256 }; + char _M_name[_M_bufsize]; +#endif + }; + + // 27.4.2.1.2 Type ios_base::fmtflags + typedef _Ios_Fmtflags fmtflags; + // 27.4.2.1.2 Type fmtflags + static const fmtflags boolalpha = fmtflags(__ios_flags::_S_boolalpha); + static const fmtflags dec = fmtflags(__ios_flags::_S_dec); + static const fmtflags fixed = fmtflags(__ios_flags::_S_fixed); + static const fmtflags hex = fmtflags(__ios_flags::_S_hex); + static const fmtflags internal = fmtflags(__ios_flags::_S_internal); + static const fmtflags left = fmtflags(__ios_flags::_S_left); + static const fmtflags oct = fmtflags(__ios_flags::_S_oct); + static const fmtflags right = fmtflags(__ios_flags::_S_right); + static const fmtflags scientific = fmtflags(__ios_flags::_S_scientific); + static const fmtflags showbase = fmtflags(__ios_flags::_S_showbase); + static const fmtflags showpoint = fmtflags(__ios_flags::_S_showpoint); + static const fmtflags showpos = fmtflags(__ios_flags::_S_showpos); + static const fmtflags skipws = fmtflags(__ios_flags::_S_skipws); + static const fmtflags unitbuf = fmtflags(__ios_flags::_S_unitbuf); + static const fmtflags uppercase = fmtflags(__ios_flags::_S_uppercase); + static const fmtflags adjustfield = fmtflags(__ios_flags::_S_adjustfield); + static const fmtflags basefield = fmtflags(__ios_flags::_S_basefield); + static const fmtflags floatfield = fmtflags(__ios_flags::_S_floatfield); + + // 27.4.2.1.3 Type ios_base::iostate + typedef _Ios_Iostate iostate; + static const iostate badbit = iostate(__ios_flags::_S_badbit); + static const iostate eofbit = iostate(__ios_flags::_S_eofbit); + static const iostate failbit = iostate(__ios_flags::_S_failbit); + static const iostate goodbit = iostate(0); + + // 27.4.2.1.4 Type openmode + typedef _Ios_Openmode openmode; + static const openmode app = openmode(__ios_flags::_S_app); + static const openmode ate = openmode(__ios_flags::_S_ate); + static const openmode binary = openmode(__ios_flags::_S_bin); + static const openmode in = openmode(__ios_flags::_S_in); + static const openmode out = openmode(__ios_flags::_S_out); + static const openmode trunc = openmode(__ios_flags::_S_trunc); + + // 27.4.2.1.5 Type seekdir + typedef _Ios_Seekdir seekdir; + static const seekdir beg = seekdir(0); + static const seekdir cur = seekdir(SEEK_CUR); + static const seekdir end = seekdir(SEEK_END); + +#ifdef _GLIBCPP_DEPRECATED + typedef int io_state; + typedef int open_mode; + typedef int seek_dir; +#endif + + // Callbacks; + enum event + { + erase_event, + imbue_event, + copyfmt_event + }; + + typedef void (*event_callback) (event, ios_base&, int); + + void + register_callback(event_callback __fn, int __index); + + protected: + // Data Members + 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 + struct _Callback_list + { + // Data Members + _Callback_list* _M_next; + ios_base::event_callback _M_fn; + int _M_index; + _Atomic_word _M_refcount; // 0 means one reference. + + _Callback_list(ios_base::event_callback __fn, int __index, + _Callback_list* __cb) + : _M_next(__cb), _M_fn(__fn), _M_index(__index), _M_refcount(0) { } + + void + _M_add_reference() { __atomic_add(&_M_refcount, 1); } + + // 0 => OK to delete. + int + _M_remove_reference() { return __exchange_and_add(&_M_refcount, -1); } + }; + + _Callback_list* _M_callbacks; + + void + _M_call_callbacks(event __ev) throw(); + + void + _M_dispose_callbacks(void); + + // 27.4.2.5 Members for iword/pword storage + struct _Words + { + void* _M_pword; + long _M_iword; + _Words() : _M_pword(0), _M_iword(0) { } + }; + + // 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); + + // Members for locale and locale caching. + locale _M_ios_locale; + + void + _M_init(); + + public: + + // 27.4.2.1.6 Class ios_base::Init + // Used to initialize standard streams. In theory, g++ could use + // -finit-priority to order this stuff correctly without going + // through these machinations. + class Init + { + friend class ios_base; + public: + Init(); + ~Init(); + + static void + _S_ios_create(bool __sync); + + static void + _S_ios_destroy(); + + private: + static int _S_ios_base_init; + static bool _S_synced_with_stdio; + }; + + // Fmtflags state: + inline fmtflags + flags() const { return _M_flags; } + + inline fmtflags + flags(fmtflags __fmtfl) + { + fmtflags __old = _M_flags; + _M_flags = __fmtfl; + return __old; + } + + inline fmtflags + setf(fmtflags __fmtfl) + { + fmtflags __old = _M_flags; + _M_flags |= __fmtfl; + return __old; + } + + inline fmtflags + setf(fmtflags __fmtfl, fmtflags __mask) + { + fmtflags __old = _M_flags; + _M_flags &= ~__mask; + _M_flags |= (__fmtfl & __mask); + return __old; + } + + inline void + unsetf(fmtflags __mask) { _M_flags &= ~__mask; } + + inline streamsize + precision() const { return _M_precision; } + + inline streamsize + precision(streamsize __prec) + { + streamsize __old = _M_precision; + _M_precision = __prec; + return __old; + } + + inline streamsize + width() const { return _M_width; } + + inline streamsize + width(streamsize __wide) + { + streamsize __old = _M_width; + _M_width = __wide; + return __old; + } + + static bool + sync_with_stdio(bool __sync = true); + + // Locales: + locale + imbue(const locale& __loc); + + inline locale + getloc() const { return _M_ios_locale; } + + // Storage: + static int + xalloc() throw(); + + inline long& + iword(int __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_size) + ? _M_word[__ix] : _M_grow_words(__ix); + return __word._M_pword; + } + + // Destructor + ~ios_base(); + + protected: + ios_base(); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //50. Copy constructor and assignment operator of ios_base + private: + ios_base(const ios_base&); + + ios_base& + operator=(const ios_base&); +#endif + }; + + // 27.4.5.1 fmtflags manipulators: + inline ios_base& + boolalpha(ios_base& __base) + { + __base.setf(ios_base::boolalpha); + return __base; + } + + inline ios_base& + noboolalpha(ios_base& __base) + { + __base.unsetf(ios_base::boolalpha); + return __base; + } + + inline ios_base& + showbase(ios_base& __base) + { + __base.setf(ios_base::showbase); + return __base; + } + + inline ios_base& + noshowbase(ios_base& __base) + { + __base.unsetf(ios_base::showbase); + return __base; + } + + inline ios_base& + showpoint(ios_base& __base) + { + __base.setf(ios_base::showpoint); + return __base; + } + + inline ios_base& + noshowpoint(ios_base& __base) + { + __base.unsetf(ios_base::showpoint); + return __base; + } + + inline ios_base& + showpos(ios_base& __base) + { + __base.setf(ios_base::showpos); + return __base; + } + + inline ios_base& + noshowpos(ios_base& __base) + { + __base.unsetf(ios_base::showpos); + return __base; + } + + inline ios_base& + skipws(ios_base& __base) + { + __base.setf(ios_base::skipws); + return __base; + } + + inline ios_base& + noskipws(ios_base& __base) + { + __base.unsetf(ios_base::skipws); + return __base; + } + + inline ios_base& + uppercase(ios_base& __base) + { + __base.setf(ios_base::uppercase); + return __base; + } + + inline ios_base& + nouppercase(ios_base& __base) + { + __base.unsetf(ios_base::uppercase); + return __base; + } + + inline ios_base& + unitbuf(ios_base& __base) + { + __base.setf(ios_base::unitbuf); + return __base; + } + + inline ios_base& + nounitbuf(ios_base& __base) + { + __base.unsetf(ios_base::unitbuf); + return __base; + } + + // 27.4.5.2 adjustfield anipulators: + inline ios_base& + internal(ios_base& __base) + { + __base.setf(ios_base::internal, ios_base::adjustfield); + return __base; + } + + inline ios_base& + left(ios_base& __base) + { + __base.setf(ios_base::left, ios_base::adjustfield); + return __base; + } + + inline ios_base& + right(ios_base& __base) + { + __base.setf(ios_base::right, ios_base::adjustfield); + return __base; + } + + // 27.4.5.3 basefield anipulators: + inline ios_base& + dec(ios_base& __base) + { + __base.setf(ios_base::dec, ios_base::basefield); + return __base; + } + + inline ios_base& + hex(ios_base& __base) + { + __base.setf(ios_base::hex, ios_base::basefield); + return __base; + } + + inline ios_base& + oct(ios_base& __base) + { + __base.setf(ios_base::oct, ios_base::basefield); + return __base; + } + + // 27.4.5.4 floatfield anipulators: + inline ios_base& + fixed(ios_base& __base) + { + __base.setf(ios_base::fixed, ios_base::floatfield); + return __base; + } + + inline ios_base& + scientific(ios_base& __base) + { + __base.setf(ios_base::scientific, ios_base::floatfield); + return __base; + } + +} // namespace std + +#endif /* _CPP_BITS_IOSBASE_H */ + diff --git a/contrib/libstdc++/include/bits/istream.tcc b/contrib/libstdc++/include/bits/istream.tcc new file mode 100644 index 0000000000000..636a73863598d --- /dev/null +++ b/contrib/libstdc++/include/bits/istream.tcc @@ -0,0 +1,1228 @@ +// istream classes -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.6.2 Output streams +// + +#pragma GCC system_header + +#include <locale> +#include <ostream> // For flush() + +namespace std +{ + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>::sentry:: + sentry(basic_istream<_CharT, _Traits>& __in, bool __noskipws) + { + if (__in.good()) + { + if (__in.tie()) + __in.tie()->flush(); + if (!__noskipws && (__in.flags() & ios_base::skipws)) + { + const __int_type __eof = traits_type::eof(); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); + + if (__in._M_check_facet(__in._M_fctype)) + while (__c != __eof + && __in._M_fctype->is(ctype_base::space, __c)) + __c = __sb->snextc(); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//195. Should basic_istream::sentry's constructor ever set eofbit? + if (__c == __eof) + __in.setstate(ios_base::eofbit); +#endif + } + } + + if (__in.good()) + _M_ok = true; + else + { + _M_ok = false; + __in.setstate(ios_base::failbit); + } + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(__istream_type& (*__pf)(__istream_type&)) + { + __pf(*this); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(__ios_type& (*__pf)(__ios_type&)) + { + __pf(*this); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(ios_base& (*__pf)(ios_base&)) + { + __pf(*this); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(bool& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(short& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + long __l; + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __l); +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + // 118. basic_istream uses nonexistent num_get member functions. + if (!(__err & ios_base::failbit) + && (numeric_limits<short>::min() <= __l + && __l <= numeric_limits<short>::max())) + __n = __l; + else + __err |= ios_base::failbit; +#endif + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(unsigned short& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(int& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + long __l; + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __l); +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + // 118. basic_istream uses nonexistent num_get member functions. + if (!(__err & ios_base::failbit) + && (numeric_limits<int>::min() <= __l + && __l <= numeric_limits<int>::max())) + __n = __l; + else + __err |= ios_base::failbit; +#endif + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(unsigned int& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(long& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(unsigned long& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + +#ifdef _GLIBCPP_USE_LONG_LONG + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(long long& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(unsigned long long& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } +#endif + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(float& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(double& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(long double& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(void*& __n) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + if (_M_check_facet(_M_fnumget)) + _M_fnumget->get(*this, 0, *this, __err, __n); + this->setstate(__err); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + operator>>(__streambuf_type* __sbout) + { + sentry __cerb(*this, false); + if (__cerb) + { + try + { + streamsize __xtrct = 0; + if (__sbout) + { + __streambuf_type* __sbin = this->rdbuf(); + __xtrct = __copy_streambufs(*this, __sbin, __sbout); + } + if (!__sbout || !__xtrct) + this->setstate(ios_base::failbit); + } + catch(exception& __fail) + { + // 27.6.2.5.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + typename basic_istream<_CharT, _Traits>::int_type + basic_istream<_CharT, _Traits>:: + get(void) + { + const int_type __eof = traits_type::eof(); + int_type __c = __eof; + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + __c = this->rdbuf()->sbumpc(); + // 27.6.1.1 paragraph 3 + if (__c != __eof) + _M_gcount = 1; + else + 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; + } + } + return __c; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + get(char_type& __c) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __eof = traits_type::eof(); + int_type __bufval = this->rdbuf()->sbumpc(); + // 27.6.1.1 paragraph 3 + if (__bufval != __eof) + { + _M_gcount = 1; + __c = traits_type::to_char_type(__bufval); + } + else + 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; + } + } + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + get(char_type* __s, streamsize __n, char_type __delim) + { + _M_gcount = 0; + sentry __cerb(*this, true); + 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->sgetc(); + + while (_M_gcount + 1 < __n && __c != __eof && __c != __idelim) + { + *__s++ = traits_type::to_char_type(__c); + __c = __sb->snextc(); + ++_M_gcount; + } + if (__c == __eof) + 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; + } + } + *__s = char_type(); + if (!_M_gcount) + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + get(__streambuf_type& __sb, char_type __delim) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __idelim = traits_type::to_int_type(__delim); + const int_type __eof = traits_type::eof(); + __streambuf_type* __this_sb = this->rdbuf(); + int_type __c = __this_sb->sgetc(); + + while (__c != __eof && __c != __idelim + && (__sb.sputc(traits_type::to_char_type(__c)) != __eof)) + { + ++_M_gcount; + __c = __this_sb->snextc(); + } + if (__c == __eof) + 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; + } + } + if (!_M_gcount) + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + getline(char_type* __s, streamsize __n, char_type __delim) + { + _M_gcount = 0; + sentry __cerb(*this, true); + 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->sgetc(); + + while (_M_gcount + 1 < __n && __c != __eof && __c != __idelim) + { + *__s++ = traits_type::to_char_type(__c); + __c = __sb->snextc(); + ++_M_gcount; + } + if (__c == __eof) + this->setstate(ios_base::eofbit); + else + { + if (__c == __idelim) + { + __sb->snextc(); + ++_M_gcount; + } + else + this->setstate(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; + } + } + *__s = char_type(); + if (!_M_gcount) + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + ignore(streamsize __n, int_type __delim) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __eof = traits_type::eof(); + __streambuf_type* __sb = this->rdbuf(); + int_type __c = __sb->sgetc(); + + __n = min(__n, numeric_limits<streamsize>::max()); + while (_M_gcount < __n && __c !=__eof && __c != __delim) + { + __c = __sb->snextc(); + ++_M_gcount; + } + if (__c == __eof) + this->setstate(ios_base::eofbit); + else if (__c == __delim) + { + __sb->snextc(); + ++_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; + } + } + return *this; + } + + template<typename _CharT, typename _Traits> + typename basic_istream<_CharT, _Traits>::int_type + basic_istream<_CharT, _Traits>:: + peek(void) + { + int_type __c = traits_type::eof(); + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { __c = this->rdbuf()->sgetc(); } + 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 __c; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + read(char_type* __s, streamsize __n) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + _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 + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + streamsize + basic_istream<_CharT, _Traits>:: + readsome(char_type* __s, streamsize __n) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __eof = traits_type::eof(); + streamsize __num = this->rdbuf()->in_avail(); + if (__num != static_cast<streamsize>(__eof)) + { + __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 + this->setstate(ios_base::failbit); + return _M_gcount; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + putback(char_type __c) + { + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __eof = traits_type::eof(); + __streambuf_type* __sb = this->rdbuf(); + if (!__sb || __sb->sputbackc(__c) == __eof) + this->setstate(ios_base::badbit); + } + 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 + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + unget(void) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + const int_type __eof = traits_type::eof(); + __streambuf_type* __sb = this->rdbuf(); + if (!__sb || __eof == __sb->sungetc()) + this->setstate(ios_base::badbit); + } + 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 + this->setstate(ios_base::failbit); + return *this; + } + + template<typename _CharT, typename _Traits> + int + basic_istream<_CharT, _Traits>:: + sync(void) + { + int __ret = traits_type::eof(); + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { + __streambuf_type* __sb = this->rdbuf(); + if (!__sb || __ret == __sb->pubsync()) + this->setstate(ios_base::badbit); + else + __ret = 0; + } + 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 __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_istream<_CharT, _Traits>::pos_type + basic_istream<_CharT, _Traits>:: + 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; + } + } + return __ret; + } + + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + seekg(pos_type __pos) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +// 136. seekp, seekg setting wrong streams? + 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); +#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; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>:: + seekg(off_type __off, ios_base::seekdir __dir) + { + _M_gcount = 0; + sentry __cerb(*this, true); + if (__cerb) + { + try + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +// 136. seekp, seekg setting wrong streams? + 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); +#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; + } + + // 27.6.1.2.3 Character extraction templates + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __in, _CharT& __c) + { + typedef basic_istream<_CharT, _Traits> __istream_type; + typename __istream_type::sentry __cerb(__in, false); + if (__cerb) + { + try + { __in.get(__c); } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __in.setstate(ios_base::badbit); + if ((__in.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + else + __in.setstate(ios_base::failbit); + return __in; + } + + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s) + { + typedef basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::__streambuf_type __streambuf_type; + typedef typename _Traits::int_type int_type; + typedef _CharT char_type; + typedef ctype<_CharT> __ctype_type; + streamsize __extracted = 0; + + typename __istream_type::sentry __cerb(__in, false); + if (__cerb) + { + try + { + // Figure out how many characters to extract. + streamsize __num = __in.width(); + if (__num == 0) + __num = numeric_limits<streamsize>::max(); + + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); + const int_type __eof = _Traits::eof(); + __streambuf_type* __sb = __in.rdbuf(); + int_type __c = __sb->sgetc(); + + while (__extracted < __num - 1 + && __c != __eof && !__ctype.is(ctype_base::space, __c)) + { + *__s++ = __c; + ++__extracted; + __c = __sb->snextc(); + } + if (__c == __eof) + __in.setstate(ios_base::eofbit); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//68. Extractors for char* should store null at end + *__s = char_type(); +#endif + __in.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __in.setstate(ios_base::badbit); + if ((__in.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + if (!__extracted) + __in.setstate(ios_base::failbit); + return __in; + } + + // 27.6.1.4 Standard basic_istream manipulators + template<typename _CharT, typename _Traits> + basic_istream<_CharT,_Traits>& + ws(basic_istream<_CharT,_Traits>& __in) + { + typedef basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::__streambuf_type __streambuf_type; + typedef typename __istream_type::__ctype_type __ctype_type; + typedef typename __istream_type::int_type __int_type; + + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); + const __int_type __eof = _Traits::eof(); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); + + while (__c != __eof && __ctype.is(ctype_base::space, __c)) + __c = __sb->snextc(); + if (__c == __eof) + __in.setstate(ios_base::eofbit); + + return __in; + } + + // 21.3.7.9 basic_string::getline and operators + template<typename _CharT, typename _Traits, typename _Alloc> + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __in, + basic_string<_CharT, _Traits, _Alloc>& __str) + { + typedef basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::int_type __int_type; + typedef typename __istream_type::__streambuf_type __streambuf_type; + typedef typename __istream_type::__ctype_type __ctype_type; + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + __size_type __extracted = 0; + + typename __istream_type::sentry __cerb(__in, false); + if (__cerb) + { + __str.erase(); + streamsize __w = __in.width(); + __size_type __n; + __n = __w > 0 ? static_cast<__size_type>(__w) : __str.max_size(); + + const __ctype_type& __ctype = use_facet<__ctype_type>(__in.getloc()); + const __int_type __eof = _Traits::eof(); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); + + while (__extracted < __n + && __c != __eof && !__ctype.is(ctype_base::space, __c)) + { + __str += _Traits::to_char_type(__c); + ++__extracted; + __c = __sb->snextc(); + } + if (__c == __eof) + __in.setstate(ios_base::eofbit); + __in.width(0); + } +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//211. operator>>(istream&, string&) doesn't set failbit + if (!__extracted) + __in.setstate (ios_base::failbit); +#endif + return __in; + } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_istream<_CharT, _Traits>& + getline(basic_istream<_CharT, _Traits>& __in, + basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim) + { + typedef basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::int_type __int_type; + typedef typename __istream_type::__streambuf_type __streambuf_type; + typedef typename __istream_type::__ctype_type __ctype_type; + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + + __size_type __extracted = 0; + bool __testdelim = false; + typename __istream_type::sentry __cerb(__in, true); + if (__cerb) + { + __str.erase(); + __size_type __n = __str.max_size(); + + __int_type __idelim = _Traits::to_int_type(__delim); + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sbumpc(); + const __int_type __eof = _Traits::eof(); + __testdelim = __c == __idelim; + + while (__extracted <= __n && __c != __eof && !__testdelim) + { + __str += _Traits::to_char_type(__c); + ++__extracted; + __c = __sb->sbumpc(); + __testdelim = __c == __idelim; + } + if (__c == __eof) + __in.setstate(ios_base::eofbit); + } + if (!__extracted && !__testdelim) + __in.setstate(ios_base::failbit); + return __in; + } + + template<class _CharT, class _Traits, class _Alloc> + inline basic_istream<_CharT,_Traits>& + getline(basic_istream<_CharT, _Traits>& __in, + basic_string<_CharT,_Traits,_Alloc>& __str) + { return getline(__in, __str, __in.widen('\n')); } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class basic_istream<char>; + extern template istream& ws(istream&); + extern template istream& operator>>(istream&, char&); + extern template istream& operator>>(istream&, char*); + extern template istream& operator>>(istream&, unsigned char&); + extern template istream& operator>>(istream&, signed char&); + extern template istream& operator>>(istream&, unsigned char*); + extern template istream& operator>>(istream&, signed char*); + + 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*); +} // namespace std diff --git a/contrib/libstdc++/include/bits/locale_facets.h b/contrib/libstdc++/include/bits/locale_facets.h new file mode 100644 index 0000000000000..d63eb5dd2d5f8 --- /dev/null +++ b/contrib/libstdc++/include/bits/locale_facets.h @@ -0,0 +1,1813 @@ +// Locale support -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 22.1 Locales +// + +/** @file locale_facets.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_LOCFACETS_H +#define _CPP_BITS_LOCFACETS_H 1 + +#pragma GCC system_header + +#include <ctime> // For struct tm +#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 + + // 22.2.1.1 Template class ctype + // Include host and configuration specific ctype enums for ctype_base. + #include <bits/ctype_base.h> + + // Common base for ctype<_CharT>. + template<typename _CharT> + class __ctype_abstract_base : public locale::facet, public ctype_base + { + public: + // Types: + typedef _CharT char_type; + + bool + is(mask __m, char_type __c) const + { return this->do_is(__m, __c); } + + const char_type* + is(const char_type *__lo, const char_type *__hi, mask *__vec) const + { return this->do_is(__lo, __hi, __vec); } + + const char_type* + scan_is(mask __m, const char_type* __lo, const char_type* __hi) const + { return this->do_scan_is(__m, __lo, __hi); } + + const char_type* + scan_not(mask __m, const char_type* __lo, const char_type* __hi) const + { return this->do_scan_not(__m, __lo, __hi); } + + char_type + toupper(char_type __c) const + { return this->do_toupper(__c); } + + const char_type* + toupper(char_type *__lo, const char_type* __hi) const + { return this->do_toupper(__lo, __hi); } + + char_type + tolower(char_type __c) const + { return this->do_tolower(__c); } + + const char_type* + tolower(char_type* __lo, const char_type* __hi) const + { return this->do_tolower(__lo, __hi); } + + char_type + widen(char __c) const + { return this->do_widen(__c); } + + const char* + widen(const char* __lo, const char* __hi, char_type* __to) const + { return this->do_widen(__lo, __hi, __to); } + + char + narrow(char_type __c, char __dfault) const + { return this->do_narrow(__c, __dfault); } + + const char_type* + narrow(const char_type* __lo, const char_type* __hi, + char __dfault, char *__to) const + { return this->do_narrow(__lo, __hi, __dfault, __to); } + + protected: + explicit + __ctype_abstract_base(size_t __refs = 0): locale::facet(__refs) { } + + virtual + ~__ctype_abstract_base() { } + + virtual bool + do_is(mask __m, char_type __c) const = 0; + + virtual const char_type* + do_is(const char_type* __lo, const char_type* __hi, + mask* __vec) const = 0; + + virtual const char_type* + do_scan_is(mask __m, const char_type* __lo, + const char_type* __hi) const = 0; + + virtual const char_type* + do_scan_not(mask __m, const char_type* __lo, + const char_type* __hi) const = 0; + + virtual char_type + do_toupper(char_type) const = 0; + + virtual const char_type* + do_toupper(char_type* __lo, const char_type* __hi) const = 0; + + virtual char_type + do_tolower(char_type) const = 0; + + virtual const char_type* + do_tolower(char_type* __lo, const char_type* __hi) const = 0; + + virtual char_type + do_widen(char) const = 0; + + virtual const char* + do_widen(const char* __lo, const char* __hi, + char_type* __dest) const = 0; + + virtual char + do_narrow(char_type, char __dfault) const = 0; + + virtual const char_type* + do_narrow(const char_type* __lo, const char_type* __hi, + char __dfault, char* __dest) const = 0; + }; + + // NB: Generic, mostly useless implementation. + template<typename _CharT> + class ctype : public __ctype_abstract_base<_CharT> + { + public: + // Types: + typedef _CharT char_type; + typedef typename ctype::mask mask; + + static locale::id id; + + explicit + ctype(size_t __refs = 0) : __ctype_abstract_base<_CharT>(__refs) { } + + protected: + virtual + ~ctype(); + + virtual bool + do_is(mask __m, char_type __c) const; + + virtual const char_type* + do_is(const char_type* __lo, const char_type* __hi, mask* __vec) const; + + virtual const char_type* + do_scan_is(mask __m, const char_type* __lo, const char_type* __hi) const; + + virtual const char_type* + do_scan_not(mask __m, const char_type* __lo, + const char_type* __hi) const; + + virtual char_type + do_toupper(char_type __c) const; + + virtual const char_type* + do_toupper(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_tolower(char_type __c) const; + + virtual const char_type* + do_tolower(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_widen(char __c) const; + + virtual const char* + do_widen(const char* __lo, const char* __hi, char_type* __dest) const; + + virtual char + do_narrow(char_type, char __dfault) const; + + virtual const char_type* + do_narrow(const char_type* __lo, const char_type* __hi, + char __dfault, char* __dest) const; + }; + + template<typename _CharT> + locale::id ctype<_CharT>::id; + + // 22.2.1.3 ctype<char> specialization. + template<> + class ctype<char> : public __ctype_abstract_base<char> + { + public: + // Types: + typedef char char_type; + + protected: + // Data Members: + __c_locale _M_c_locale_ctype; + bool _M_del; + __to_type _M_toupper; + __to_type _M_tolower; + const mask* _M_table; + + public: + static locale::id id; + static const size_t table_size = 1 + static_cast<unsigned char>(-1); + + explicit + ctype(const mask* __table = 0, bool __del = false, size_t __refs = 0); + + explicit + ctype(__c_locale __cloc, const mask* __table = 0, bool __del = false, + size_t __refs = 0); + + inline bool + is(mask __m, char __c) const; + + inline const char* + is(const char* __lo, const char* __hi, mask* __vec) const; + + inline const char* + scan_is(mask __m, const char* __lo, const char* __hi) const; + + inline const char* + scan_not(mask __m, const char* __lo, const char* __hi) const; + + protected: + const mask* + table() const throw() + { return _M_table; } + + static const mask* + classic_table() throw(); + + virtual + ~ctype(); + + virtual bool + do_is(mask __m, char_type __c) const; + + virtual const char_type* + do_is(const char_type* __lo, const char_type* __hi, mask* __vec) const; + + virtual const char_type* + do_scan_is(mask __m, const char_type* __lo, const char_type* __hi) const; + + virtual const char_type* + do_scan_not(mask __m, const char_type* __lo, + const char_type* __hi) const; + + virtual char_type + do_toupper(char_type) const; + + virtual const char_type* + do_toupper(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_tolower(char_type) const; + + virtual const char_type* + do_tolower(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_widen(char) const; + + virtual const char* + do_widen(const char* __lo, const char* __hi, char_type* __dest) const; + + virtual char + do_narrow(char_type, char __dfault) const; + + virtual const char_type* + do_narrow(const char_type* __lo, const char_type* __hi, + char __dfault, char* __dest) const; + }; + + template<> + const ctype<char>& + use_facet<ctype<char> >(const locale& __loc); + +#ifdef _GLIBCPP_USE_WCHAR_T + // 22.2.1.3 ctype<wchar_t> specialization + template<> + class ctype<wchar_t> : public __ctype_abstract_base<wchar_t> + { + public: + // Types: + typedef wchar_t char_type; + typedef wctype_t __wmask_type; + + protected: + __c_locale _M_c_locale_ctype; + + public: + // Data Members: + static locale::id id; + + explicit + ctype(size_t __refs = 0); + + explicit + ctype(__c_locale __cloc, size_t __refs = 0); + + protected: + __wmask_type + _M_convert_to_wmask(const mask __m) const; + + virtual + ~ctype(); + + virtual bool + do_is(mask __m, char_type __c) const; + + virtual const char_type* + do_is(const char_type* __lo, const char_type* __hi, mask* __vec) const; + + virtual const char_type* + do_scan_is(mask __m, const char_type* __lo, const char_type* __hi) const; + + virtual const char_type* + do_scan_not(mask __m, const char_type* __lo, + const char_type* __hi) const; + + virtual char_type + do_toupper(char_type) const; + + virtual const char_type* + do_toupper(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_tolower(char_type) const; + + virtual const char_type* + do_tolower(char_type* __lo, const char_type* __hi) const; + + virtual char_type + do_widen(char) const; + + virtual const char* + do_widen(const char* __lo, const char* __hi, char_type* __dest) const; + + virtual char + do_narrow(char_type, char __dfault) const; + + virtual const char_type* + do_narrow(const char_type* __lo, const char_type* __hi, + char __dfault, char* __dest) const; + + }; + + template<> + const ctype<wchar_t>& + use_facet<ctype<wchar_t> >(const locale& __loc); +#endif //_GLIBCPP_USE_WCHAR_T + + // Include host and configuration specific ctype inlines. + #include <bits/ctype_inline.h> + + // 22.2.1.2 Template class ctype_byname + template<typename _CharT> + class ctype_byname : public ctype<_CharT> + { + public: + typedef _CharT char_type; + + explicit + ctype_byname(const char* __s, size_t __refs = 0); + + protected: + virtual + ~ctype_byname() { }; + }; + + // 22.2.1.4 Class ctype_byname specializations. + template<> + ctype_byname<char>::ctype_byname(const char*, size_t refs); + + template<> + ctype_byname<wchar_t>::ctype_byname(const char*, size_t refs); + + // 22.2.1.5 Template class codecvt + #include <bits/codecvt.h> + + + // 22.2.2 The numeric category. + class __num_base + { + protected: + // String literal of acceptable (narrow) input, for num_get. + // "0123456789eEabcdfABCDF" + static const char _S_atoms[]; + + enum + { + _M_zero, + _M_e = _M_zero + 10, + _M_E = _M_zero + 11, + _M_size = 21 + 1 + }; + + // num_put + // Construct and return valid scanf format for floating point types. + static bool + _S_format_float(const ios_base& __io, char* __fptr, char __mod, + streamsize __prec); + + // Construct and return valid scanf format for integer types. + static void + _S_format_int(const ios_base& __io, char* __fptr, char __mod, char __modl); + }; + + + template<typename _CharT> + class numpunct : public locale::facet + { + public: + // Types: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + static locale::id id; + + private: + char_type _M_decimal_point; + char_type _M_thousands_sep; + const char* _M_grouping; + const char_type* _M_truename; + const char_type* _M_falsename; + + public: + explicit + numpunct(size_t __refs = 0) : locale::facet(__refs) + { _M_initialize_numpunct(); } + + explicit + numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) + { _M_initialize_numpunct(__cloc); } + + char_type + decimal_point() const + { return this->do_decimal_point(); } + + char_type + thousands_sep() const + { return this->do_thousands_sep(); } + + string + grouping() const + { return this->do_grouping(); } + + string_type + truename() const + { return this->do_truename(); } + + string_type + falsename() const + { return this->do_falsename(); } + + protected: + virtual + ~numpunct(); + + virtual char_type + do_decimal_point() const + { return _M_decimal_point; } + + virtual char_type + do_thousands_sep() const + { return _M_thousands_sep; } + + virtual string + do_grouping() const + { return _M_grouping; } + + virtual string_type + do_truename() const + { return _M_truename; } + + virtual string_type + do_falsename() const + { return _M_falsename; } + + // For use at construction time only. + void + _M_initialize_numpunct(__c_locale __cloc = _S_c_locale); + }; + + template<typename _CharT> + 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 + + template<typename _CharT> + class numpunct_byname : public numpunct<_CharT> + { + // Data Member. + __c_locale _M_c_locale_numpunct; + + public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + explicit + numpunct_byname(const char* __s, size_t __refs = 0) + : numpunct<_CharT>(__refs) + { + _S_create_c_locale(_M_c_locale_numpunct, __s); + _M_initialize_numpunct(_M_c_locale_numpunct); + } + + protected: + virtual + ~numpunct_byname() + { _S_destroy_c_locale(_M_c_locale_numpunct); } + }; + + template<typename _CharT, typename _InIter> + class num_get : public locale::facet, public __num_base + { + public: + // Types: + typedef _CharT char_type; + typedef _InIter iter_type; + + static locale::id id; + + explicit + num_get(size_t __refs = 0) : locale::facet(__refs) { } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, bool& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned short& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned int& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned long& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + +#ifdef _GLIBCPP_USE_LONG_LONG + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long long& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned long long& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } +#endif + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, float& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, double& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long double& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + iter_type + get(iter_type __in, iter_type __end, ios_base& __io, + ios_base::iostate& __err, void*& __v) const + { return this->do_get(__in, __end, __io, __err, __v); } + + protected: + virtual ~num_get() { } + + 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; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, long&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + unsigned short&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + unsigned int&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + unsigned long&) const; + +#ifdef _GLIBCPP_USE_LONG_LONG + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + long long&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + unsigned long long&) const; +#endif + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + float&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + double&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + long double&) const; + + virtual iter_type + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + void*&) const; + }; + + template<typename _CharT, typename _InIter> + locale::id num_get<_CharT, _InIter>::id; + + template<typename _CharT, typename _OutIter> + class num_put : public locale::facet, public __num_base + { + public: + // Types: + typedef _CharT char_type; + typedef _OutIter iter_type; + + static locale::id id; + + explicit + num_put(size_t __refs = 0) : locale::facet(__refs) { } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, bool __v) const + { return this->do_put(__s, __f, __fill, __v); } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, long __v) const + { return this->do_put(__s, __f, __fill, __v); } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, + unsigned long __v) const + { return this->do_put(__s, __f, __fill, __v); } + +#ifdef _GLIBCPP_USE_LONG_LONG + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, long long __v) const + { return this->do_put(__s, __f, __fill, __v); } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, + unsigned long long __v) const + { return this->do_put(__s, __f, __fill, __v); } +#endif + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, double __v) const + { return this->do_put(__s, __f, __fill, __v); } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, + long double __v) const + { return this->do_put(__s, __f, __fill, __v); } + + iter_type + put(iter_type __s, ios_base& __f, char_type __fill, + const void* __v) const + { return this->do_put(__s, __f, __fill, __v); } + + protected: + template<typename _ValueT> + iter_type + _M_convert_float(iter_type, ios_base& __io, char_type __fill, + char __mod, _ValueT __v) const; + + template<typename _ValueT> + iter_type + _M_convert_int(iter_type, ios_base& __io, char_type __fill, + char __mod, char __modl, _ValueT __v) const; + + iter_type + _M_widen_float(iter_type, ios_base& __io, char_type __fill, char* __cs, + int __len) const; + + iter_type + _M_widen_int(iter_type, ios_base& __io, char_type __fill, char* __cs, + int __len) const; + + iter_type + _M_insert(iter_type, ios_base& __io, char_type __fill, + const char_type* __ws, int __len) const; + + virtual + ~num_put() { }; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, bool __v) const; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, long __v) const; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, unsigned long) const; + +#ifdef _GLIBCPP_USE_LONG_LONG + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, long long __v) const; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, unsigned long long) const; +#endif + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, double __v) const; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, long double __v) const; + + virtual iter_type + do_put(iter_type, ios_base&, char_type __fill, const void* __v) const; + }; + + template <typename _CharT, typename _OutIter> + locale::id num_put<_CharT, _OutIter>::id; + + + template<typename _CharT> + class collate : public locale::facet + { + public: + // Types: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + protected: + // Underlying "C" library locale information saved from + // initialization, needed by collate_byname as well. + __c_locale _M_c_locale_collate; + + public: + static locale::id id; + + explicit + collate(size_t __refs = 0) + : locale::facet(__refs) + { _M_c_locale_collate = _S_c_locale; } + + // Non-standard. + explicit + collate(__c_locale __cloc, size_t __refs = 0) + : locale::facet(__refs) + { _M_c_locale_collate = _S_clone_c_locale(__cloc); } + + int + compare(const _CharT* __lo1, const _CharT* __hi1, + const _CharT* __lo2, const _CharT* __hi2) const + { return this->do_compare(__lo1, __hi1, __lo2, __hi2); } + + string_type + transform(const _CharT* __lo, const _CharT* __hi) const + { return this->do_transform(__lo, __hi); } + + long + hash(const _CharT* __lo, const _CharT* __hi) const + { return this->do_hash(__lo, __hi); } + + // Used to abstract out _CharT bits in virtual member functions, below. + int + _M_compare(const _CharT*, const _CharT*) const; + + size_t + _M_transform(_CharT*, const _CharT*, size_t) const; + + protected: + virtual + ~collate() + { + if (_M_c_locale_collate != _S_c_locale) + _S_destroy_c_locale(_M_c_locale_collate); + } + + virtual int + do_compare(const _CharT* __lo1, const _CharT* __hi1, + const _CharT* __lo2, const _CharT* __hi2) const; + + virtual string_type + do_transform(const _CharT* __lo, const _CharT* __hi) const; + + virtual long + do_hash(const _CharT* __lo, const _CharT* __hi) const; + }; + + template<typename _CharT> + locale::id collate<_CharT>::id; + + // Specializations. + template<> + int + collate<char>::_M_compare(const char*, const char*) const; + + template<> + size_t + collate<char>::_M_transform(char*, const char*, size_t) const; + +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + int + collate<wchar_t>::_M_compare(const wchar_t*, const wchar_t*) const; + + template<> + size_t + collate<wchar_t>::_M_transform(wchar_t*, const wchar_t*, size_t) const; +#endif + + template<typename _CharT> + class collate_byname : public collate<_CharT> + { + public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + explicit + collate_byname(const char* __s, size_t __refs = 0) + : collate<_CharT>(__refs) + { + if (_M_c_locale_collate != _S_c_locale) + _S_destroy_c_locale(_M_c_locale_collate); + _S_create_c_locale(_M_c_locale_collate, __s); + } + + protected: + virtual + ~collate_byname() { } + }; + + + class time_base + { + public: + enum dateorder { no_order, dmy, mdy, ymd, ydm }; + }; + + template<typename _CharT> + class __timepunct : public locale::facet + { + public: + // Types: + typedef _CharT __char_type; + typedef basic_string<_CharT> __string_type; + + static locale::id id; + + // List of all known timezones, with GMT first. + static const _CharT* _S_timezones[14]; + + protected: + __c_locale _M_c_locale_timepunct; + const char* _M_name_timepunct; + const _CharT* _M_date_format; + const _CharT* _M_date_era_format; + const _CharT* _M_time_format; + const _CharT* _M_time_era_format; + const _CharT* _M_date_time_format; + const _CharT* _M_date_time_era_format; + const _CharT* _M_am; + const _CharT* _M_pm; + const _CharT* _M_am_pm_format; + + // Day names, starting with "C"'s Sunday. + const _CharT* _M_day1; + const _CharT* _M_day2; + const _CharT* _M_day3; + const _CharT* _M_day4; + const _CharT* _M_day5; + const _CharT* _M_day6; + const _CharT* _M_day7; + + // Abbreviated day names, starting with "C"'s Sun. + const _CharT* _M_day_a1; + const _CharT* _M_day_a2; + const _CharT* _M_day_a3; + const _CharT* _M_day_a4; + const _CharT* _M_day_a5; + const _CharT* _M_day_a6; + const _CharT* _M_day_a7; + + // Month names, starting with "C"'s January. + const _CharT* _M_month01; + const _CharT* _M_month02; + const _CharT* _M_month03; + const _CharT* _M_month04; + const _CharT* _M_month05; + const _CharT* _M_month06; + const _CharT* _M_month07; + const _CharT* _M_month08; + const _CharT* _M_month09; + const _CharT* _M_month10; + const _CharT* _M_month11; + const _CharT* _M_month12; + + // Abbreviated month names, starting with "C"'s Jan. + const _CharT* _M_month_a01; + const _CharT* _M_month_a02; + const _CharT* _M_month_a03; + const _CharT* _M_month_a04; + const _CharT* _M_month_a05; + const _CharT* _M_month_a06; + const _CharT* _M_month_a07; + const _CharT* _M_month_a08; + const _CharT* _M_month_a09; + const _CharT* _M_month_a10; + const _CharT* _M_month_a11; + const _CharT* _M_month_a12; + + public: + explicit + __timepunct(size_t __refs = 0) + : locale::facet(__refs), _M_name_timepunct("C") + { _M_initialize_timepunct(); } + + explicit + __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0) + : locale::facet(__refs), _M_name_timepunct(__s) + { _M_initialize_timepunct(__cloc); } + + void + _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format, + const tm* __tm) const; + + void + _M_date_formats(const _CharT** __date) const + { + // Always have default first. + __date[0] = _M_date_format; + __date[1] = _M_date_era_format; + } + + void + _M_time_formats(const _CharT** __time) const + { + // Always have default first. + __time[0] = _M_time_format; + __time[1] = _M_time_era_format; + } + + void + _M_ampm(const _CharT** __ampm) const + { + __ampm[0] = _M_am; + __ampm[1] = _M_pm; + } + + void + _M_date_time_formats(const _CharT** __dt) const + { + // Always have default first. + __dt[0] = _M_date_time_format; + __dt[1] = _M_date_time_era_format; + } + + void + _M_days(const _CharT** __days) const + { + __days[0] = _M_day1; + __days[1] = _M_day2; + __days[2] = _M_day3; + __days[3] = _M_day4; + __days[4] = _M_day5; + __days[5] = _M_day6; + __days[6] = _M_day7; + } + + void + _M_days_abbreviated(const _CharT** __days) const + { + __days[0] = _M_day_a1; + __days[1] = _M_day_a2; + __days[2] = _M_day_a3; + __days[3] = _M_day_a4; + __days[4] = _M_day_a5; + __days[5] = _M_day_a6; + __days[6] = _M_day_a7; + } + + void + _M_months(const _CharT** __months) const + { + __months[0] = _M_month01; + __months[1] = _M_month02; + __months[2] = _M_month03; + __months[3] = _M_month04; + __months[4] = _M_month05; + __months[5] = _M_month06; + __months[6] = _M_month07; + __months[7] = _M_month08; + __months[8] = _M_month09; + __months[9] = _M_month10; + __months[10] = _M_month11; + __months[11] = _M_month12; + } + + void + _M_months_abbreviated(const _CharT** __months) const + { + __months[0] = _M_month_a01; + __months[1] = _M_month_a02; + __months[2] = _M_month_a03; + __months[3] = _M_month_a04; + __months[4] = _M_month_a05; + __months[5] = _M_month_a06; + __months[6] = _M_month_a07; + __months[7] = _M_month_a08; + __months[8] = _M_month_a09; + __months[9] = _M_month_a10; + __months[10] = _M_month_a11; + __months[11] = _M_month_a12; + } + + protected: + virtual + ~__timepunct(); + + // For use at construction time only. + void + _M_initialize_timepunct(__c_locale __cloc = _S_c_locale); + }; + + template<typename _CharT> + locale::id __timepunct<_CharT>::id; + + // Specializations. + template<> + __timepunct<char>::~__timepunct(); + + template<> + const char* + __timepunct<char>::_S_timezones[14]; + + template<> + void + __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc); + + template<> + void + __timepunct<char>::_M_put(char*, size_t, const char*, const tm*) const; + +#ifdef _GLIBCPP_USE_WCHAR_T + template<> + __timepunct<wchar_t>::~__timepunct(); + + template<> + const wchar_t* + __timepunct<wchar_t>::_S_timezones[14]; + + template<> + void + __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc); + + template<> + void + __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]; + + + template<typename _CharT, typename _InIter> + class time_get : public locale::facet, public time_base + { + public: + // Types: + typedef _CharT char_type; + typedef _InIter iter_type; + typedef basic_string<_CharT> __string_type; + + static locale::id id; + + explicit + time_get(size_t __refs = 0) + : locale::facet (__refs) { } + + dateorder + date_order() const + { return this->do_date_order(); } + + iter_type + get_time(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { return this->do_get_time(__beg, __end, __io, __err, __tm); } + + iter_type + get_date(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { return this->do_get_date(__beg, __end, __io, __err, __tm); } + + iter_type + get_weekday(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { return this->do_get_weekday(__beg, __end, __io, __err, __tm); } + + iter_type + get_monthname(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { return this->do_get_monthname(__beg, __end, __io, __err, __tm); } + + iter_type + get_year(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { return this->do_get_year(__beg, __end, __io, __err, __tm); } + + protected: + virtual + ~time_get() { } + + virtual dateorder + do_date_order() const; + + virtual iter_type + do_get_time(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const; + + virtual iter_type + do_get_date(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const; + + virtual iter_type + do_get_weekday(iter_type __beg, iter_type __end, ios_base&, + ios_base::iostate& __err, tm* __tm) const; + + virtual iter_type + do_get_monthname(iter_type __beg, iter_type __end, ios_base&, + ios_base::iostate& __err, tm* __tm) const; + + virtual iter_type + do_get_year(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const; + + // Extract numeric component of length __len. + void + _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, + int __min, int __max, size_t __len, + const ctype<_CharT>& __ctype, + ios_base::iostate& __err) const; + + // Extract day or month name, or any unique array of string + // literals in a const _CharT* array. + void + _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, + const _CharT** __names, size_t __indexlen, + ios_base::iostate& __err) const; + + // Extract on a component-by-component basis, via __format argument. + void + _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm, + const _CharT* __format) const; + }; + + template<typename _CharT, typename _InIter> + locale::id time_get<_CharT, _InIter>::id; + + template<typename _CharT, typename _InIter> + class time_get_byname : public time_get<_CharT, _InIter> + { + public: + // Types: + typedef _CharT char_type; + typedef _InIter iter_type; + + explicit + time_get_byname(const char*, size_t __refs = 0) + : time_get<_CharT, _InIter>(__refs) { } + + protected: + virtual + ~time_get_byname() { } + }; + + template<typename _CharT, typename _OutIter> + class time_put : public locale::facet, public time_base + { + public: + // Types: + typedef _CharT char_type; + typedef _OutIter iter_type; + + static locale::id id; + + explicit + time_put(size_t __refs = 0) + : locale::facet(__refs) { } + + iter_type + put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, + const _CharT* __beg, const _CharT* __end) const; + + iter_type + put(iter_type __s, ios_base& __io, char_type __fill, + const tm* __tm, char __format, char __mod = 0) const + { return this->do_put(__s, __io, __fill, __tm, __format, __mod); } + + protected: + virtual + ~time_put() + { } + + virtual iter_type + do_put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, + char __format, char __mod) const; + }; + + template<typename _CharT, typename _OutIter> + locale::id time_put<_CharT, _OutIter>::id; + + template<typename _CharT, typename _OutIter> + class time_put_byname : public time_put<_CharT, _OutIter> + { + public: + // Types: + typedef _CharT char_type; + typedef _OutIter iter_type; + + explicit + time_put_byname(const char* /*__s*/, size_t __refs = 0) + : time_put<_CharT, _OutIter>(__refs) + { }; + + protected: + virtual + ~time_put_byname() { } + }; + + + class money_base + { + public: + enum part { none, space, symbol, sign, value }; + struct pattern { char field[4]; }; + + static const pattern _S_default_pattern; + + // Construct and return valid pattern consisting of some combination of: + // space none symbol sign value + static pattern + _S_construct_pattern(char __precedes, char __space, char __posn); + }; + + template<typename _CharT, bool _Intl> + class moneypunct : public locale::facet, public money_base + { + public: + // Types: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + static const bool intl = _Intl; + static locale::id id; + + private: + 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 + moneypunct(size_t __refs = 0) : locale::facet(__refs) + { _M_initialize_moneypunct(); } + + explicit + moneypunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) + { _M_initialize_moneypunct(__cloc); } + + char_type + decimal_point() const + { return this->do_decimal_point(); } + + char_type + thousands_sep() const + { return this->do_thousands_sep(); } + + string + grouping() const + { return this->do_grouping(); } + + string_type + curr_symbol() const + { return this->do_curr_symbol(); } + + string_type + positive_sign() const + { return this->do_positive_sign(); } + + string_type + negative_sign() const + { return this->do_negative_sign(); } + + int + frac_digits() const + { return this->do_frac_digits(); } + + pattern + pos_format() const + { return this->do_pos_format(); } + + pattern + neg_format() const + { return this->do_neg_format(); } + + protected: + virtual + ~moneypunct(); + + virtual char_type + do_decimal_point() const + { return _M_decimal_point; } + + virtual char_type + do_thousands_sep() const + { return _M_thousands_sep; } + + virtual string + do_grouping() const + { return _M_grouping; } + + virtual string_type + do_curr_symbol() const + { return _M_curr_symbol; } + + virtual string_type + do_positive_sign() const + { return _M_positive_sign; } + + virtual string_type + do_negative_sign() const + { return _M_negative_sign; } + + virtual int + do_frac_digits() const + { return _M_frac_digits; } + + virtual pattern + do_pos_format() const + { return _M_pos_format; } + + virtual pattern + do_neg_format() const + { return _M_neg_format; } + + // For use at construction time only. + void + _M_initialize_moneypunct(__c_locale __cloc = _S_c_locale); + }; + + template<typename _CharT, bool _Intl> + locale::id moneypunct<_CharT, _Intl>::id; + + 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); + + template<> + void + moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc); + +#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); + + template<> + void + moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc); +#endif + + template<typename _CharT, bool _Intl> + class moneypunct_byname : public moneypunct<_CharT, _Intl> + { + __c_locale _M_c_locale_moneypunct; + + public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + static const bool intl = _Intl; + + explicit + moneypunct_byname(const char* __s, size_t __refs = 0) + : moneypunct<_CharT, _Intl>(__refs) + { + _S_create_c_locale(_M_c_locale_moneypunct, __s); + _M_initialize_moneypunct(_M_c_locale_moneypunct); + } + + protected: + virtual + ~moneypunct_byname() + { _S_destroy_c_locale(_M_c_locale_moneypunct); } + }; + + template<typename _CharT, bool _Intl> + const bool moneypunct_byname<_CharT, _Intl>::intl; + + template<typename _CharT, typename _InIter> + class money_get : public locale::facet + { + public: + // Types: + typedef _CharT char_type; + typedef _InIter iter_type; + typedef basic_string<_CharT> string_type; + + static locale::id id; + + explicit + money_get(size_t __refs = 0) : locale::facet(__refs) { } + + iter_type + get(iter_type __s, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, long double& __units) const + { return this->do_get(__s, __end, __intl, __io, __err, __units); } + + iter_type + get(iter_type __s, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, string_type& __digits) const + { return this->do_get(__s, __end, __intl, __io, __err, __digits); } + + protected: + virtual + ~money_get() { } + + virtual iter_type + do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, long double& __units) const; + + virtual iter_type + do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, string_type& __digits) const; + }; + + template<typename _CharT, typename _InIter> + locale::id money_get<_CharT, _InIter>::id; + + template<typename _CharT, typename _OutIter> + class money_put : public locale::facet + { + public: + typedef _CharT char_type; + typedef _OutIter iter_type; + typedef basic_string<_CharT> string_type; + + static locale::id id; + + explicit + money_put(size_t __refs = 0) : locale::facet(__refs) { } + + iter_type + put(iter_type __s, bool __intl, ios_base& __io, + char_type __fill, long double __units) const + { return this->do_put(__s, __intl, __io, __fill, __units); } + + iter_type + put(iter_type __s, bool __intl, ios_base& __io, + char_type __fill, const string_type& __digits) const + { return this->do_put(__s, __intl, __io, __fill, __digits); } + + protected: + virtual + ~money_put() { } + + virtual iter_type + do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, + long double __units) const; + + virtual iter_type + do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, + const string_type& __digits) const; + }; + + template<typename _CharT, typename _OutIter> + locale::id money_put<_CharT, _OutIter>::id; + + + struct messages_base + { + typedef int catalog; + }; + + template<typename _CharT> + class messages : public locale::facet, public messages_base + { + public: + // Types: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + protected: + // 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 + + public: + static locale::id id; + + explicit + messages(size_t __refs = 0) + : locale::facet(__refs), _M_name_messages("C") + { _M_c_locale_messages = _S_c_locale; } + + // 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); + } + + catalog + open(const basic_string<char>& __s, const locale& __loc) const + { return this->do_open(__s, __loc); } + + // Non-standard and unorthodox, yet effective. + catalog + open(const basic_string<char>&, const locale&, const char*) const; + + string_type + get(catalog __c, int __set, int __msgid, const string_type& __s) const + { return this->do_get(__c, __set, __msgid, __s); } + + void + close(catalog __c) const + { return this->do_close(__c); } + + protected: + virtual + ~messages() + { + if (_M_c_locale_messages != _S_c_locale) + _S_destroy_c_locale(_M_c_locale_messages); + } + + virtual catalog + do_open(const basic_string<char>&, const locale&) const; + + virtual string_type + do_get(catalog, int, int, const string_type& __dfault) const; + + virtual void + do_close(catalog) const; + + // Returns a locale and codeset-converted string, given a char* message. + char* + _M_convert_to_char(const string_type& __msg) const + { + // XXX + return reinterpret_cast<char*>(const_cast<_CharT*>(__msg.c_str())); + } + + // Returns a locale and codeset-converted string, given a char* message. + string_type + _M_convert_from_char(char* __msg) const + { + // Length of message string without terminating null. + size_t __len = char_traits<char>::length(__msg) - 1; + + // "everybody can easily convert the string using + // mbsrtowcs/wcsrtombs or with iconv()" +#if 0 + // Convert char* to _CharT in locale used to open catalog. + // XXX need additional template parameter on messages class for this.. + // typedef typename codecvt<char, _CharT, _StateT> __codecvt_type; + typedef typename codecvt<char, _CharT, mbstate_t> __codecvt_type; + + __codecvt_type::state_type __state; + // XXX may need to initialize state. + //initialize_state(__state._M_init()); + + char* __from_next; + // XXX what size for this string? + _CharT* __to = static_cast<_CharT*>(__builtin_alloca(__len + 1)); + const __codecvt_type& __cvt = use_facet<__codecvt_type>(_M_locale_conv); + __cvt.out(__state, __msg, __msg + __len, __from_next, + __to, __to + __len + 1, __to_next); + return string_type(__to); +#endif +#if 0 + typedef ctype<_CharT> __ctype_type; + // const __ctype_type& __cvt = use_facet<__ctype_type>(_M_locale_msg); + const __ctype_type& __cvt = use_facet<__ctype_type>(locale()); + // XXX Again, proper length of converted string an issue here. + // For now, assume the converted length is not larger. + _CharT* __dest = static_cast<_CharT*>(__builtin_alloca(__len + 1)); + __cvt.widen(__msg, __msg + __len, __dest); + return basic_string<_CharT>(__dest); +#endif + return string_type(); + } + }; + + template<typename _CharT> + locale::id messages<_CharT>::id; + + // Specializations for required instantiations. + template<> + string + messages<char>::do_get(catalog, int, int, const string&) const; + + // Include host and configuration specific messages virtual functions. + #include <bits/messages_members.h> + + template<typename _CharT> + class messages_byname : public messages<_CharT> + { + public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + explicit + messages_byname(const char* __s, size_t __refs = 0) + : messages<_CharT>(__refs) + { + _M_name_messages = __s; + if (_M_c_locale_messages != _S_c_locale) + _S_destroy_c_locale(_M_c_locale_messages); + _S_create_c_locale(_M_c_locale_messages, __s); + } + + protected: + virtual + ~messages_byname() + { } + }; + + + // Subclause convenience interfaces, inlines. + // NB: These are inline because, when used in a loop, some compilers + // can hoist the body out of the loop; then it's just as fast as the + // C is*() function. + template<typename _CharT> + inline bool + isspace(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c); } + + template<typename _CharT> + inline bool + isprint(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c); } + + template<typename _CharT> + inline bool + iscntrl(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c); } + + template<typename _CharT> + inline bool + isupper(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c); } + + template<typename _CharT> + inline bool islower(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c); } + + template<typename _CharT> + inline bool + isalpha(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c); } + + template<typename _CharT> + inline bool + isdigit(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c); } + + template<typename _CharT> + inline bool + ispunct(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c); } + + template<typename _CharT> + inline bool + isxdigit(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c); } + + template<typename _CharT> + inline bool + isalnum(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c); } + + template<typename _CharT> + inline bool + isgraph(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c); } + + template<typename _CharT> + inline _CharT + toupper(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).toupper(__c); } + + template<typename _CharT> + inline _CharT + tolower(_CharT __c, const locale& __loc) + { return use_facet<ctype<_CharT> >(__loc).tolower(__c); } +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/locale_facets.tcc b/contrib/libstdc++/include/bits/locale_facets.tcc new file mode 100644 index 0000000000000..d362c33f87fbc --- /dev/null +++ b/contrib/libstdc++/include/bits/locale_facets.tcc @@ -0,0 +1,2401 @@ +// Locale support -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Warning: this file is not meant for user inclusion. Use <locale>. + +#ifndef _CPP_BITS_LOCFACETS_TCC +#define _CPP_BITS_LOCFACETS_TCC 1 + +#pragma GCC system_header + +#include <cerrno> +#include <clocale> // For localeconv +#include <cstdlib> // For strof, strtold +#include <cmath> // For ceil +#include <cctype> // For isspace +#include <limits> // For numeric_limits +#include <bits/streambuf_iterator.h> +#include <typeinfo> // For bad_cast. + +namespace std +{ + template<typename _Facet> + locale + locale::combine(const locale& __other) const + { + _Impl* __tmp = new _Impl(*_M_impl, 1); + __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); + return locale(__tmp); + } + + template<typename _CharT, typename _Traits, typename _Alloc> + bool + locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, + const basic_string<_CharT, _Traits, _Alloc>& __s2) const + { + typedef std::collate<_CharT> __collate_type; + const __collate_type& __collate = use_facet<__collate_type>(*this); + return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), + __s2.data(), __s2.data() + __s2.length()) < 0); + } + + template<typename _Facet> + const _Facet& + use_facet(const locale& __loc) + { + 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&>(*__facets[__i]); + } + + template<typename _Facet> + bool + has_facet(const locale& __loc) throw() + { + 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]); + } + + + // Stage 1: Determine a conversion specifier. + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, string& __xtrc) const + { + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + + // First check for sign. + const char_type __plus = __ctype.widen('+'); + const char_type __minus = __ctype.widen('-'); + int __pos = 0; + char_type __c = *__beg; + if ((__c == __plus || __c == __minus) && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + + // Next, strip leading zeros. + const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); + bool __found_zero = false; + while (__c == __zero && __beg != __end) + { + __c = *(++__beg); + __found_zero = true; + } + if (__found_zero) + { + __xtrc += _S_atoms[_M_zero]; + ++__pos; + } + + // Only need acceptable digits for floating point numbers. + const size_t __len = _M_E - _M_zero + 1; + char_type __watoms[__len]; + __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); + bool __found_dec = false; + bool __found_sci = false; + const char_type __dec = __np.decimal_point(); + + string __found_grouping; + const string __grouping = __np.grouping(); + bool __check_grouping = __grouping.size(); + int __sep_pos = 0; + const char_type __sep = __np.thousands_sep(); + + 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) + { + // Try first for acceptable digit; record it if found. + ++__pos; + __xtrc += _S_atoms[__p - __watoms]; + ++__sep_pos; + __c = *(++__beg); + } + else if (__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. + if (__sep_pos) + { + __found_grouping += static_cast<char>(__sep_pos); + __sep_pos = 0; + __c = *(++__beg); + } + else + { + __err |= ios_base::failbit; + break; + } + } + else if (__c == __dec && !__found_dec) + { + // 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]) + && !__found_sci && __pos) + { + // Scientific notation. + ++__pos; + __xtrc += __ctype.narrow(__c, char()); + __c = *(++__beg); + + // Remove optional plus or minus sign, if they exist. + if (__c == __plus || __c == __minus) + { + ++__pos; + __xtrc += __ctype.narrow(__c, char()); + __c = *(++__beg); + } + __found_sci = true; + } + else + // Not a valid input item. + break; + } + + // Digit grouping is checked. If grouping and found_grouping don't + // match, then get very very upset, and set failbit. + if (__check_grouping && __found_grouping.size()) + { + // Add the ending grouping if a decimal wasn't found. + if (!__found_dec) + __found_grouping += static_cast<char>(__sep_pos); + if (!__verify_grouping(__grouping, __found_grouping)) + __err |= ios_base::failbit; + } + + // Finish up + __xtrc += char(); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + // Stage 1: Determine a conversion specifier. + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, string& __xtrc, int& __base) const + { + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + + // NB: Iff __basefield == 0, this can change based on contents. + ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; + if (__basefield == ios_base::oct) + __base = 8; + else if (__basefield == ios_base::hex) + __base = 16; + else + __base = 10; + + // First check for sign. + int __pos = 0; + char_type __c = *__beg; + if ((__c == __ctype.widen('+') || __c == __ctype.widen('-')) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + + // Next, strip leading zeros and check required digits for base formats. + const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); + const char_type __x = __ctype.widen('x'); + const char_type __X = __ctype.widen('X'); + if (__base == 10) + { + bool __found_zero = false; + while (__c == __zero && __beg != __end) + { + __c = *(++__beg); + __found_zero = true; + } + if (__found_zero) + { + __xtrc += _S_atoms[_M_zero]; + ++__pos; + if (__basefield == 0) + { + if ((__c == __x || __c == __X) && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + __base = 16; + } + else + __base = 8; + } + } + } + else if (__base == 16) + { + if (__c == __zero && __beg != __end) + { + __xtrc += _S_atoms[_M_zero]; + ++__pos; + __c = *(++__beg); + if ((__c == __x || __c == __X) && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + } + } + + // At this point, base is determined. If not hex, only allow + // base digits as valid input. + size_t __len; + if (__base == 16) + __len = _M_size; + else + __len = __base; + + // Extract. + char_type __watoms[_M_size]; + __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); + string __found_grouping; + const string __grouping = __np.grouping(); + 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) + { + // Try first for acceptable digit; record it if found. + __xtrc += _S_atoms[__p - __watoms]; + ++__pos; + ++__sep_pos; + __c = *(++__beg); + } + else if (__c == __sep && __check_grouping) + { + // NB: Thousands separator at the beginning of a string + // is a no-no, as is two consecutive thousands separators. + if (__sep_pos) + { + __found_grouping += static_cast<char>(__sep_pos); + __sep_pos = 0; + __c = *(++__beg); + } + else + { + __err |= ios_base::failbit; + break; + } + } + else + // Not a valid input item. + break; + } + + // Digit grouping is checked. If grouping and found_grouping don't + // match, then get very very upset, and set failbit. + if (__check_grouping && __found_grouping.size()) + { + // Add the ending grouping. + __found_grouping += static_cast<char>(__sep_pos); + if (!__verify_grouping(__grouping, __found_grouping)) + __err |= ios_base::failbit; + } + + // Finish up. + __xtrc += char(); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //17. Bad bool parsing + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, bool& __v) const + { + // Parse bool values as unsigned long + if (!(__io.flags() & ios_base::boolalpha)) + { + // NB: We can't just call do_get(long) here, as it might + // refer to a derived class. + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) && __ul <= 1) + __v = __ul; + else + __err |= ios_base::failbit; + } + + // Parse bool values as alphanumeric + else + { + typedef basic_string<_CharT> __string_type; + locale __loc = __io.getloc(); + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + 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 == __falses[__n] : false; + bool __testt = __n <= __truen ? __c == __trues[__n] : false; + if (!(__testf || __testt)) + { + __err |= ios_base::failbit; + break; + } + else if (__testf && __n == __falsen) + { + __v = 0; + break; + } + else if (__testt && __n == __truen) + { + __v = 1; + break; + } + } + if (__beg == __end) + __err |= ios_base::eofbit; + } + return __beg; + } +#endif + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned short& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) + && __ul <= numeric_limits<unsigned short>::max()) + __v = static_cast<unsigned short>(__ul); + else + __err |= ios_base::failbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned int& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit) + && __ul <= numeric_limits<unsigned int>::max()) + __v = static_cast<unsigned int>(__ul); + else + __err |= ios_base::failbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned long& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + return __beg; + } + +#ifdef _GLIBCPP_USE_LONG_LONG + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long long& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, unsigned long long& __v) const + { + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + return __beg; + } +#endif + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, float& __v) const + { + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, double& __v) const + { + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, long double& __v) const + { + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + num_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, void*& __v) const + { + // Prepare for hex formatted input + typedef ios_base::fmtflags fmtflags; + fmtflags __fmt = __io.flags(); + fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield + | ios_base::uppercase | ios_base::internal); + __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); + + string __xtrc; + int __base; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + + // Reset from hex formatted input + __io.flags(__fmt); + + unsigned long __ul; + __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); + if (!(__err & ios_base::failbit)) + __v = reinterpret_cast<void*>(__ul); + else + __err |= ios_base::failbit; + return __beg; + } + + // 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 + num_put<_CharT, _OutIter>:: + _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, + _ValueT __v) const + { + // Note: digits10 is rounded down. We need to add 1 to ensure + // we get the full available precision. + const int __max_digits = numeric_limits<_ValueT>::digits10 + 1; + streamsize __prec = __io.precision(); + + 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; + // ios_base::fixed outputs may need up to __max_exp+1 chars + // for the integer part + up to __max_digits chars for the + // fractional part + 3 chars for sign, decimal point, '\0'. On + // the other hand, for non-fixed outputs __max_digits*3 chars + // are largely sufficient. + const int __cs_size = __fixed ? __max_exp + __max_digits + 4 + : __max_digits * 3; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + + if (_S_format_float(__io, __fbuf, __mod, __prec)) + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); + else + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); +#endif + return _M_widen_float(__s, __io, __fill, __cs, __len); + } + + template<typename _CharT, typename _OutIter> + template<typename _ValueT> + _OutIter + num_put<_CharT, _OutIter>:: + _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, + char __modl, _ValueT __v) const + { + // [22.2.2.2.2] Stage 1, numeric conversion to character. + + // Long enough for the max format spec. + char __fbuf[16]; + _S_format_int(__io, __fbuf, __mod, __modl); +#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); + } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, + int __len) const + { + // [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(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + __ctype.widen(__cs, __cs + __len, __ws); + + // 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('.'))) + __ws[__p - __ws] = __np.decimal_point(); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + const string __grouping = __np.grouping(); + ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; + if (__grouping.size()) + { + _CharT* __p2; + int __declen = __p ? __p - __ws : __len; + __p2 = __add_grouping(__ws2, __np.thousands_sep(), + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __ws, __ws + __declen); + int __newlen = __p2 - __ws2; + + // Tack on decimal part. + if (__p) + { + char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; + } + + // Switch strings, establish correct new length. + __ws = __ws2; + __len = __newlen; + } +#endif + return _M_insert(__s, __io, __fill, __ws, __len); + } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, + int __len) const + { + // [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(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Add grouping, if necessary. + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + const string __grouping = __np.grouping(); + 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. + streamsize __off = 0; + if (__io.flags() & ios_base::showbase) + 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 + __off, __np.thousands_sep(), + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __ws + __off, __ws + __len); + __len = __p - __ws2; + // Switch strings. + __ws = __ws2; + } + return _M_insert(__s, __io, __fill, __ws, __len); + } + + // For use by integer and floating-point types after they have been + // converted into a char_type string. + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, + int __len) const + { + // [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); + __len = static_cast<int>(__w); + // Switch strings. + __ws = __ws2; + } + __io.width(0); + + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + for (int __j = 0; __j < __len; ++__j, ++__s) + *__s = __ws[__j]; + return __s; + } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const + { + ios_base::fmtflags __flags = __io.flags(); + if ((__flags & ios_base::boolalpha) == 0) + { + unsigned long __uv = __v; + __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv); + } + else + { + typedef basic_string<_CharT> __string_type; + locale __loc = __io.getloc(); + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + __string_type __name; + if (__v) + __name = __np.truename(); + else + __name = __np.falsename(); + __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); + } + return __s; + } + + template<typename _CharT, typename _OutIter> + _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); } + + 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); } + +#ifdef _GLIBCPP_USE_LONG_LONG + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const + { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, + unsigned long long __v) const + { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } +#endif + + template<typename _CharT, typename _OutIter> + _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); } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, + long double __v) const + { return _M_convert_float(__s, __io, __fill, 'L', __v); } + + template<typename _CharT, typename _OutIter> + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, + const void* __v) const + { + ios_base::fmtflags __flags = __io.flags(); + ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield + | ios_base::uppercase | ios_base::internal); + __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); + try + { + __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), + reinterpret_cast<unsigned long>(__v)); + __io.flags(__flags); + } + catch (...) + { + __io.flags(__flags); + __throw_exception_again; + } + return __s; + } + + + template<typename _CharT, typename _InIter> + _InIter + money_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, long double& __units) const + { + string_type __str; + __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(__n)); + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + const _CharT* __wcs = __str.c_str(); + __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); + __convert_to_v(__cs, __units, __err, _S_c_locale); + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + money_get<_CharT, _InIter>:: + do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, + ios_base::iostate& __err, string_type& __units) const + { + // These contortions are quite unfortunate. + typedef moneypunct<_CharT, true> __money_true; + typedef moneypunct<_CharT, false> __money_false; + typedef money_base::part part; + typedef typename string_type::size_type size_type; + + const locale __loc = __io.getloc(); + const __money_true& __mpt = use_facet<__money_true>(__loc); + const __money_false& __mpf = use_facet<__money_false>(__loc); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + + const money_base::pattern __p = __intl ? __mpt.neg_format() + : __mpf.neg_format(); + + const string_type __pos_sign =__intl ? __mpt.positive_sign() + : __mpf.positive_sign(); + const string_type __neg_sign =__intl ? __mpt.negative_sign() + : __mpf.negative_sign(); + const char_type __d = __intl ? __mpt.decimal_point() + : __mpf.decimal_point(); + const char_type __sep = __intl ? __mpt.thousands_sep() + : __mpf.thousands_sep(); + + const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); + + // Set to deduced positive or negative sign, depending. + string_type __sign; + // String of grouping info from thousands_sep plucked from __units. + string __grouping_tmp; + // Marker for thousands_sep position. + int __sep_pos = 0; + // If input iterator is in a valid state. + bool __testvalid = true; + // Flag marking when a decimal point is found. + bool __testdecfound = false; + + // The tentative returned string is stored here. + string_type __temp_units; + + char_type __c = *__beg; + char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); + for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) + { + part __which = static_cast<part>(__p.field[__i]); + switch (__which) + { + case money_base::symbol: + 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. + const string_type __symbol = __intl ? __mpt.curr_symbol() + : __mpf.curr_symbol(); + size_type __len = __symbol.size(); + size_type __j = 0; + while (__beg != __end + && __j < __len && __symbol[__j] == __c) + { + __c = *(++__beg); + ++__j; + } + // When (__io.flags() & ios_base::showbase) + // symbol is required. + if (__j != __len && (__io.flags() & ios_base::showbase)) + __testvalid = false; + } + break; + case money_base::sign: + // Sign might not exist, or be more than one character long. + if (__pos_sign.size() && __neg_sign.size()) + { + // Sign is mandatory. + if (__c == __pos_sign[0]) + { + __sign = __pos_sign; + __c = *(++__beg); + } + else if (__c == __neg_sign[0]) + { + __sign = __neg_sign; + __c = *(++__beg); + } + else + __testvalid = false; + } + else if (__pos_sign.size() && __c == __pos_sign[0]) + { + __sign = __pos_sign; + __c = *(++__beg); + } + else if (__neg_sign.size() && __c == __neg_sign[0]) + { + __sign = __neg_sign; + __c = *(++__beg); + } + break; + case money_base::value: + // Extract digits, remove and stash away the + // grouping of found thousands separators. + while (__beg != __end + && (__ctype.is(ctype_base::digit, __c) + || (__c == __d && !__testdecfound) + || __c == __sep)) + { + if (__c == __d) + { + __grouping_tmp += static_cast<char>(__sep_pos); + __sep_pos = 0; + __testdecfound = true; + } + else if (__c == __sep) + { + if (__grouping.size()) + { + // Mark position for later analysis. + __grouping_tmp += static_cast<char>(__sep_pos); + __sep_pos = 0; + } + else + { + __testvalid = false; + break; + } + } + else + { + __temp_units += __c; + ++__sep_pos; + } + __c = *(++__beg); + } + break; + case money_base::space: + case money_base::none: + // Only if not at the end of the pattern. + if (__i != 3) + while (__beg != __end + && __ctype.is(ctype_base::space, __c)) + __c = *(++__beg); + break; + } + } + + // Need to get the rest of the sign characters, if they exist. + if (__sign.size() > 1) + { + size_type __len = __sign.size(); + size_type __i = 1; + for (; __c != __eof && __i < __len; ++__i) + while (__beg != __end && __c != __sign[__i]) + __c = *(++__beg); + + if (__i != __len) + __testvalid = false; + } + + // Strip leading zeros. + while (__temp_units[0] == __ctype.widen('0')) + __temp_units.erase(__temp_units.begin()); + + if (__sign.size() && __sign == __neg_sign) + __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); + + // Test for grouping fidelity. + if (__grouping.size() && __grouping_tmp.size()) + { + if (!__verify_grouping(__grouping, __grouping_tmp)) + __testvalid = false; + } + + // Iff no more characters are available. + if (__c == __eof) + __err |= ios_base::eofbit; + + // Iff valid sequence is not recognized. + if (!__testvalid || !__temp_units.size()) + __err |= ios_base::failbit; + else + // Use the "swap trick" to copy __temp_units into __units. + __temp_units.swap(__units); + + return __beg; + } + + template<typename _CharT, typename _OutIter> + _OutIter + money_put<_CharT, _OutIter>:: + do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, + long double __units) const + { + const locale __loc = __io.getloc(); + 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); + } + + template<typename _CharT, typename _OutIter> + _OutIter + money_put<_CharT, _OutIter>:: + do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, + const string_type& __digits) const + { + typedef typename string_type::size_type size_type; + typedef money_base::part part; + + const locale __loc = __io.getloc(); + const size_type __width = static_cast<size_type>(__io.width()); + + // These contortions are quite unfortunate. + typedef moneypunct<_CharT, true> __money_true; + typedef moneypunct<_CharT, false> __money_false; + const __money_true& __mpt = use_facet<__money_true>(__loc); + const __money_false& __mpf = use_facet<__money_false>(__loc); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + + // Determine if negative or positive formats are to be used, and + // discard leading negative_sign if it is present. + const char_type* __beg = __digits.data(); + const char_type* __end = __beg + __digits.size(); + money_base::pattern __p; + string_type __sign; + if (*__beg != __ctype.widen('-')) + { + __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); + __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); + } + else + { + __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); + __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); + ++__beg; + } + + // Look for valid numbers in the current ctype facet within input digits. + __end = __ctype.scan_not(ctype_base::digit, __beg, __end); + if (__beg != __end) + { + // Assume valid input, and attempt to format. + // Break down input numbers into base components, as follows: + // final_value = grouped units + (decimal point) + (digits) + string_type __res; + string_type __value; + const string_type __symbol = __intl ? __mpt.curr_symbol() + : __mpf.curr_symbol(); + + // Deal with decimal point, decimal digits. + const int __frac = __intl ? __mpt.frac_digits() + : __mpf.frac_digits(); + if (__frac > 0) + { + const char_type __d = __intl ? __mpt.decimal_point() + : __mpf.decimal_point(); + if (__end - __beg >= __frac) + { + __value = string_type(__end - __frac, __end); + __value.insert(__value.begin(), __d); + __end -= __frac; + } + else + { + // Have to pad zeros in the decimal position. + __value = string_type(__beg, __end); + int __paddec = __frac - (__end - __beg); + char_type __zero = __ctype.widen('0'); + __value.insert(__value.begin(), __paddec, __zero); + __value.insert(__value.begin(), __d); + __beg = __end; + } + } + + // Add thousands separators to non-decimal digits, per + // grouping rules. + if (__beg != __end) + { + const string __grouping = __intl ? __mpt.grouping() + : __mpf.grouping(); + if (__grouping.size()) + { + const char_type __sep = __intl ? __mpt.thousands_sep() + : __mpf.thousands_sep(); + const char* __gbeg = __grouping.c_str(); + const char* __gend = __gbeg + __grouping.size(); + 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); + } + else + __value.insert(0, string_type(__beg, __end)); + } + + // Calculate length of resulting string. + ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; + size_type __len = __value.size() + __sign.size(); + __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; + bool __testipad = __f == ios_base::internal && __len < __width; + + // Fit formatted digits into the required pattern. + for (int __i = 0; __i < 4; ++__i) + { + part __which = static_cast<part>(__p.field[__i]); + switch (__which) + { + case money_base::symbol: + if (__io.flags() & ios_base::showbase) + __res += __symbol; + break; + case money_base::sign: + // Sign might not exist, or be more than one + // charater long. In that case, add in the rest + // below. + if (__sign.size()) + __res += __sign[0]; + break; + case money_base::value: + __res += __value; + break; + case money_base::space: + // At least one space is required, but if internal + // formatting is required, an arbitrary number of + // fill spaces will be necessary. + if (__testipad) + __res += string_type(__width - __len, __fill); + else + __res += __ctype.widen(__fill); + break; + case money_base::none: + if (__testipad) + __res += string_type(__width - __len, __fill); + break; + } + } + + // Special case of multi-part sign parts. + if (__sign.size() > 1) + __res += string_type(__sign.begin() + 1, __sign.end()); + + // Pad, if still necessary. + __len = __res.size(); + if (__width > __len) + { + if (__f == ios_base::left) + // After. + __res.append(__width - __len, __fill); + else + // Before. + __res.insert(0, string_type(__width - __len, __fill)); + __len = __width; + } + + // Write resulting, fully-formatted string to output iterator. + for (size_type __j = 0; __j < __len; ++__j, ++__s) + *__s = __res[__j]; + } + __io.width(0); + return __s; + } + + + // NB: Not especially useful. Without an ios_base object or some + // kind of locale reference, we are left clawing at the air where + // the side of the mountain used to be... + template<typename _CharT, typename _InIter> + time_base::dateorder + time_get<_CharT, _InIter>::do_date_order() const + { return time_base::no_order; } + + template<typename _CharT, typename _InIter> + void + time_get<_CharT, _InIter>:: + _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm, + const _CharT* __format) const + { + locale __loc = __io.getloc(); + __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + size_t __len = char_traits<_CharT>::length(__format); + + for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) + { + char __c = __format[__i]; + if (__c == '%') + { + // Verify valid formatting code, attempt to extract. + __c = __format[++__i]; + char __mod = 0; + int __mem = 0; + if (__c == 'E' || __c == 'O') + { + __mod = __c; + __c = __format[++__i]; + } + switch (__c) + { + const char* __cs; + _CharT __wcs[10]; + case 'a': + // Abbreviated weekday name [tm_wday] + const char_type* __days1[7]; + __tp._M_days_abbreviated(__days1); + _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, + __err); + break; + case 'A': + // Weekday name [tm_wday]. + const char_type* __days2[7]; + __tp._M_days(__days2); + _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, + __err); + break; + case 'h': + case 'b': + // Abbreviated month name [tm_mon] + const char_type* __months1[12]; + __tp._M_months_abbreviated(__months1); + _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, + __err); + break; + case 'B': + // Month name [tm_mon]. + const char_type* __months2[12]; + __tp._M_months(__months2); + _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, + __err); + break; + case 'c': + // Default time and date representation. + const char_type* __dt[2]; + __tp._M_date_time_formats(__dt); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __dt[0]); + break; + case 'd': + // Day [01, 31]. [tm_mday] + _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, + __ctype, __err); + break; + case 'D': + // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] + __cs = "%m/%d/%y"; + __ctype.widen(__cs, __cs + 9, __wcs); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __wcs); + break; + case 'H': + // Hour [00, 23]. [tm_hour] + _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, + __ctype, __err); + break; + case 'I': + // Hour [01, 12]. [tm_hour] + _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, + __ctype, __err); + break; + case 'm': + // Month [01, 12]. [tm_mon] + _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, + __err); + if (!__err) + __tm->tm_mon = __mem - 1; + break; + case 'M': + // Minute [00, 59]. [tm_min] + _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, + __ctype, __err); + break; + case 'n': + if (__ctype.narrow(*__beg, 0) == '\n') + ++__beg; + else + __err |= ios_base::failbit; + break; + case 'R': + // Equivalent to (%H:%M). + __cs = "%H:%M"; + __ctype.widen(__cs, __cs + 6, __wcs); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __wcs); + break; + case 'S': + // Seconds. + _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, + __ctype, __err); + break; + case 't': + if (__ctype.narrow(*__beg, 0) == '\t') + ++__beg; + else + __err |= ios_base::failbit; + break; + case 'T': + // Equivalent to (%H:%M:%S). + __cs = "%H:%M:%S"; + __ctype.widen(__cs, __cs + 9, __wcs); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __wcs); + break; + case 'x': + // Locale's date. + const char_type* __dates[2]; + __tp._M_date_formats(__dates); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __dates[0]); + break; + case 'X': + // Locale's time. + const char_type* __times[2]; + __tp._M_time_formats(__times); + _M_extract_via_format(__beg, __end, __io, __err, __tm, + __times[0]); + break; + case 'y': + // Two digit year. [tm_year] + _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, + __ctype, __err); + break; + case 'Y': + // Year [1900). [tm_year] + _M_extract_num(__beg, __end, __mem, 0, + numeric_limits<int>::max(), 4, + __ctype, __err); + if (!__err) + __tm->tm_year = __mem - 1900; + break; + case 'Z': + // Timezone info. + if (__ctype.is(ctype_base::upper, *__beg)) + { + int __tmp; + _M_extract_name(__beg, __end, __tmp, + __timepunct<_CharT>::_S_timezones, + 14, __err); + + // GMT requires special effort. + char_type __c = *__beg; + if (!__err && __tmp == 0 + && (__c == __ctype.widen('-') + || __c == __ctype.widen('+'))) + { + _M_extract_num(__beg, __end, __tmp, 0, 23, 2, + __ctype, __err); + _M_extract_num(__beg, __end, __tmp, 0, 59, 2, + __ctype, __err); + } + } + else + __err |= ios_base::failbit; + break; + default: + // Not recognized. + __err |= ios_base::failbit; + } + } + else + { + // Verify format and input match, extract and discard. + if (__c == __ctype.narrow(*__beg, 0)) + ++__beg; + else + __err |= ios_base::failbit; + } + } + } + + template<typename _CharT, typename _InIter> + void + time_get<_CharT, _InIter>:: + _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, + int __min, int __max, size_t __len, + const ctype<_CharT>& __ctype, + ios_base::iostate& __err) const + { + size_t __i = 0; + string __digits; + bool __testvalid = true; + char_type __c = *__beg; + while (__beg != __end && __i < __len + && __ctype.is(ctype_base::digit, __c)) + { + __digits += __ctype.narrow(__c, 0); + __c = *(++__beg); + ++__i; + } + if (__i == __len) + { + int __value = atoi(__digits.c_str()); + if (__min <= __value && __value <= __max) + __member = __value; + else + __testvalid = false; + } + else + __testvalid = false; + if (!__testvalid) + __err |= ios_base::failbit; + } + + // Assumptions: + // All elements in __names are unique. + template<typename _CharT, typename _InIter> + void + time_get<_CharT, _InIter>:: + _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, + const _CharT** __names, size_t __indexlen, + ios_base::iostate& __err) const + { + typedef char_traits<char_type> __traits_type; + int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); + size_t __nmatches = 0; + size_t __pos = 0; + bool __testvalid = true; + const char_type* __name; + + char_type __c = *__beg; + // Look for initial matches. + for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) + if (__c == __names[__i1][0]) + __matches[__nmatches++] = __i1; + + while(__nmatches > 1) + { + // Find smallest matching string. + size_t __minlen = 10; + for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) + __minlen = min(__minlen, + __traits_type::length(__names[__matches[__i2]])); + + if (__pos < __minlen && __beg != __end) + { + ++__pos; + __c = *(++__beg); + for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) + { + __name = __names[__matches[__i3]]; + if (__name[__pos] != __c) + __matches[__i3] = __matches[--__nmatches]; + } + } + else + break; + } + + if (__nmatches == 1) + { + // Make sure found name is completely extracted. + __name = __names[__matches[0]]; + const size_t __len = __traits_type::length(__name); + while (__pos < __len && __beg != __end && __name[__pos] == *__beg) + ++__beg, ++__pos; + + if (__len == __pos) + __member = __matches[0]; + else + __testvalid = false; + } + else + __testvalid = false; + if (!__testvalid) + __err |= ios_base::failbit; + } + + template<typename _CharT, typename _InIter> + _InIter + time_get<_CharT, _InIter>:: + do_get_time(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { + _CharT __wcs[3]; + const char* __cs = "%X"; + locale __loc = __io.getloc(); + ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); + __ctype.widen(__cs, __cs + 3, __wcs); + _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + time_get<_CharT, _InIter>:: + do_get_date(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { + _CharT __wcs[3]; + const char* __cs = "%x"; + locale __loc = __io.getloc(); + ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); + __ctype.widen(__cs, __cs + 3, __wcs); + _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + time_get<_CharT, _InIter>:: + 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; + locale __loc = __io.getloc(); + __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); + const char_type* __days[7]; + __tp._M_days_abbreviated(__days); + int __tmpwday; + _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); + + // Check to see if non-abbreviated name exists, and extract. + // NB: Assumes both _M_days and _M_days_abbreviated organized in + // exact same order, first to last, such that the resulting + // __days array with the same index points to a day, and that + // day's abbreviated form. + // NB: Also assumes that an abbreviated name is a subset of the name. + if (!__err) + { + size_t __pos = __traits_type::length(__days[__tmpwday]); + __tp._M_days(__days); + const char_type* __name = __days[__tmpwday]; + if (__name[__pos] == *__beg) + { + // Extract the rest of it. + const size_t __len = __traits_type::length(__name); + while (__pos < __len && __beg != __end + && __name[__pos] == *__beg) + ++__beg, ++__pos; + if (__len != __pos) + __err |= ios_base::failbit; + } + if (!__err) + __tm->tm_wday = __tmpwday; + } + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + time_get<_CharT, _InIter>:: + 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; + locale __loc = __io.getloc(); + __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); + const char_type* __months[12]; + __tp._M_months_abbreviated(__months); + int __tmpmon; + _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); + + // Check to see if non-abbreviated name exists, and extract. + // NB: Assumes both _M_months and _M_months_abbreviated organized in + // exact same order, first to last, such that the resulting + // __months array with the same index points to a month, and that + // month's abbreviated form. + // NB: Also assumes that an abbreviated name is a subset of the name. + if (!__err) + { + size_t __pos = __traits_type::length(__months[__tmpmon]); + __tp._M_months(__months); + const char_type* __name = __months[__tmpmon]; + if (__name[__pos] == *__beg) + { + // Extract the rest of it. + const size_t __len = __traits_type::length(__name); + while (__pos < __len && __beg != __end + && __name[__pos] == *__beg) + ++__beg, ++__pos; + if (__len != __pos) + __err |= ios_base::failbit; + } + if (!__err) + __tm->tm_mon = __tmpmon; + } + + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + template<typename _CharT, typename _InIter> + _InIter + time_get<_CharT, _InIter>:: + do_get_year(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const + { + locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + + char_type __c = *__beg; + size_t __i = 0; + string __digits; + while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) + { + __digits += __ctype.narrow(__c, 0); + __c = *(++__beg); + ++__i; + } + if (__i == 2 || __i == 4) + { + long __l; + __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); + if (!(__err & ios_base::failbit) && __l <= INT_MAX) + { + __l = __i == 2 ? __l : __l - 1900; + __tm->tm_year = static_cast<int>(__l); + } + } + else + __err |= ios_base::failbit; + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } + + template<typename _CharT, typename _OutIter> + _OutIter + time_put<_CharT, _OutIter>:: + put(iter_type __s, ios_base& __io, char_type, const tm* __tm, + const _CharT* __beg, const _CharT* __end) const + { + locale __loc = __io.getloc(); + ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); + while (__beg != __end) + { + char __c = __ctype.narrow(*__beg, 0); + ++__beg; + if (__c == '%') + { + char __format; + char __mod = 0; + size_t __len = 1; + __c = __ctype.narrow(*__beg, 0); + ++__beg; + if (__c == 'E' || __c == 'O') + { + __mod = __c; + __format = __ctype.narrow(*__beg, 0); + ++__beg; + } + else + __format = __c; + __s = this->do_put(__s, __io, char_type(), __tm, __format, + __mod); + } + else + { + *__s = __c; + ++__s; + } + } + return __s; + } + + template<typename _CharT, typename _OutIter> + _OutIter + time_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, + char __format, char __mod) const + { + locale __loc = __io.getloc(); + ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); + __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); + + // 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(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 + // character. Possibilities include 'E' or 'O' followed by a + // format character: if __mod is not the default argument, assume + // it's a valid modifier. + char_type __fmt[4]; + __fmt[0] = __ctype.widen('%'); + if (!__mod) + { + __fmt[1] = __format; + __fmt[2] = char_type(); + } + else + { + __fmt[1] = __mod; + __fmt[2] = __format; + __fmt[3] = char_type(); + } + + __tp._M_put(__res, __maxlen, __fmt, __tm); + + // Write resulting, fully-formatted string to output iterator. + size_t __len = char_traits<char_type>::length(__res); + for (size_t __i = 0; __i < __len; ++__i, ++__s) + *__s = __res[__i]; + return __s; + } + + + // Generic version does nothing. + template<typename _CharT> + int + collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const + { return 0; } + + // Generic version does nothing. + template<typename _CharT> + size_t + collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const + { return 0; } + + template<typename _CharT> + int + collate<_CharT>:: + do_compare(const _CharT* __lo1, const _CharT* __hi1, + const _CharT* __lo2, const _CharT* __hi2) const + { + const string_type __one(__lo1, __hi1); + const string_type __two(__lo2, __hi2); + return _M_compare(__one.c_str(), __two.c_str()); + } + + template<typename _CharT> + typename collate<_CharT>::string_type + collate<_CharT>:: + do_transform(const _CharT* __lo, const _CharT* __hi) const + { + 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) + { + __c = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); + _M_transform(__c, __lo, __res + 1); + } + return string_type(__c); + } + + template<typename _CharT> + long + collate<_CharT>:: + do_hash(const _CharT* __lo, const _CharT* __hi) const + { + unsigned long __val = 0; + for (; __lo < __hi; ++__lo) + __val = *__lo + ((__val << 7) | + (__val >> (numeric_limits<unsigned long>::digits - 7))); + return static_cast<long>(__val); + } + + // Convert string to numeric value of type _Tv and store results. + // NB: This is specialized for all required types, there is no + // generic definition. + template<typename _Tv> + void + __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, + 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. +#ifdef _GLIBCPP_USE_C99 + template<typename _Tv> + int + __convert_from_v(char* __out, const int __size, const char* __fmt, + _Tv __v, const __c_locale&, int __prec = -1) + { + int __ret; + const char* __old = setlocale(LC_ALL, "C"); + if (__prec >= 0) + __ret = snprintf(__out, __size, __fmt, __prec, __v); + else + __ret = snprintf(__out, __size, __fmt, __v); + setlocale(LC_ALL, __old); + return __ret; + } +#else + template<typename _Tv> + int + __convert_from_v(char* __out, const int, 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; + } +#endif + + // Construct correctly padded string, as per 22.2.2.2.2 + // Assumes + // __newlen > __oldlen + // __news is allocated for __newlen size + // Used by both num_put and ostream inserters: if __num, + // internal-adjusted objects are padded according to the rules below + // concerning 0[xX] and +-, otherwise, exactly as right-adjusted + // ones are. + 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) + { + 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); + + char_type* __beg; + char_type* __end; + size_t __mod = 0; + size_t __beglen; //either __plen or __oldlen + ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; + + if (__adjust == ios_base::left) + { + // Padding last. + __beg = const_cast<char_type*>(__olds); + __beglen = __oldlen; + __end = __pads; + } + else if (__adjust == ios_base::internal && __num) + { + // Pad after the sign, if there is one. + // Pad after 0[xX], if there is one. + // 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]); + if (__testhex) + { + __news[0] = __olds[0]; + __news[1] = __olds[1]; + __mod += 2; + __news += 2; + __beg = __pads; + __beglen = __plen; + __end = const_cast<char_type*>(__olds + __mod); + } + else if (__testsign) + { + __news[0] = __olds[0] == __plus ? __plus : __minus; + ++__mod; + ++__news; + __beg = __pads; + __beglen = __plen; + __end = const_cast<char_type*>(__olds + __mod); + } + else + { + // Padding first. + __beg = __pads; + __beglen = __plen; + __end = const_cast<char_type*>(__olds); + } + } + else + { + // Padding first. + __beg = __pads; + __beglen = __plen; + __end = const_cast<char_type*>(__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); + } + + // Used by both numeric and monetary facets. + // Check to make sure that the __grouping_tmp string constructed in + // money_get or num_get matches the canonical grouping for a given + // locale. + // __grouping_tmp is parsed L to R + // 1,222,444 == __grouping_tmp of "/1/3/3" + // __grouping is parsed R to L + // 1,222,444 == __grouping of "/3" == "/3/3/3" + template<typename _CharT> + bool + __verify_grouping(const basic_string<_CharT>& __grouping, + basic_string<_CharT>& __grouping_tmp) + { + int __i = 0; + int __j = 0; + const int __len = __grouping.size(); + const int __n = __grouping_tmp.size(); + bool __test = true; + + // Parsed number groupings have to match the + // numpunct::grouping string exactly, starting at the + // right-most point of the parsed sequence of elements ... + while (__test && __i < __n - 1) + for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) + __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; + // ... but the last parsed grouping can be <= numpunct + // grouping. + __j == __len ? __j = 0 : __j; + __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; + return __test; + } + + // Used by both numeric and monetary facets. + // Inserts "group separator" characters into an array of characters. + // It's recursive, one iteration per group. It moves the characters + // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this + // only with __gbeg != __gend. + template<typename _CharT> + _CharT* + __add_grouping(_CharT* __s, _CharT __sep, + const char* __gbeg, const char* __gend, + const _CharT* __first, const _CharT* __last) + { + if (__last - __first > *__gbeg) + { + __s = __add_grouping(__s, __sep, + (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), + __gend, __first, __last - *__gbeg); + __first = __last - *__gbeg; + *__s++ = __sep; + } + do + *__s++ = *__first++; + while (__first != __last); + return __s; + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class moneypunct<char, false>; + 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>; + extern template class money_put<char>; + 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>; + extern template class money_put<wchar_t>; + 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 numpunct<wchar_t>; + extern template class numpunct_byname<wchar_t>; + extern template class num_get<wchar_t>; + extern template class num_put<wchar_t>; + 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 __timepunct<wchar_t>; + 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<char>; + extern template class messages_byname<char>; + 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>; + + 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 + 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<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&); + + 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&); +} // namespace std + +#endif + + diff --git a/contrib/libstdc++/include/bits/localefwd.h b/contrib/libstdc++/include/bits/localefwd.h new file mode 100644 index 0000000000000..028c4126b85e1 --- /dev/null +++ b/contrib/libstdc++/include/bits/localefwd.h @@ -0,0 +1,476 @@ +// Locale support -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 22.1 Locales +// + +/** @file localefwd.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_LOCCORE_H +#define _CPP_BITS_LOCCORE_H 1 + +#pragma GCC system_header + +#include <bits/c++config.h> +#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 <bits/functexcept.h> +#include <bits/atomicity.h> + +namespace std +{ + // 22.1.1 Locale + class locale; + + // 22.1.3 Convenience interfaces + template<typename _CharT> + inline bool + isspace(_CharT, const locale&); + + template<typename _CharT> + inline bool + isprint(_CharT, const locale&); + + template<typename _CharT> + inline bool + iscntrl(_CharT, const locale&); + + template<typename _CharT> + inline bool + isupper(_CharT, const locale&); + + template<typename _CharT> + inline bool + islower(_CharT, const locale&); + + template<typename _CharT> + inline bool + isalpha(_CharT, const locale&); + + template<typename _CharT> + inline bool + isdigit(_CharT, const locale&); + + template<typename _CharT> + inline bool + ispunct(_CharT, const locale&); + + template<typename _CharT> + inline bool + isxdigit(_CharT, const locale&); + + template<typename _CharT> + inline bool + isalnum(_CharT, const locale&); + + template<typename _CharT> + inline bool + isgraph(_CharT, const locale&); + + template<typename _CharT> + inline _CharT + toupper(_CharT, const locale&); + + template<typename _CharT> + inline _CharT + tolower(_CharT, const locale&); + + + // 22.2.1 and 22.2.1.3 ctype + class ctype_base; + template<typename _CharT> + class ctype; + template<> class ctype<char>; +#ifdef _GLIBCPP_USE_WCHAR_T + template<> class ctype<wchar_t>; +#endif + template<typename _CharT> + class ctype_byname; + // NB: Specialized for char and wchar_t in locale_facets.h. + + class codecvt_base; + class __enc_traits; + template<typename _InternT, typename _ExternT, typename _StateT> + class codecvt; + template<> class codecvt<char, char, mbstate_t>; +#ifdef _GLIBCPP_USE_WCHAR_T + template<> class codecvt<wchar_t, char, mbstate_t>; +#endif + template<typename _InternT, typename _ExternT, typename _StateT> + class codecvt_byname; + + // 22.2.2 and 22.2.3 numeric + template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > + class num_get; + template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > + class num_put; + template<typename _CharT> class numpunct; + template<typename _CharT> class numpunct_byname; + + // 22.2.4 collation + template<typename _CharT> + class collate; + template<typename _CharT> class + collate_byname; + + // 22.2.5 date and time + class time_base; + template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > + class time_get; + template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > + class time_get_byname; + template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > + class time_put; + template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > + class time_put_byname; + + // 22.2.6 money + class money_base; + template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> > + class money_get; + template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> > + class money_put; + template<typename _CharT, bool _Intl = false> + class moneypunct; + template<typename _CharT, bool _Intl = false> + class moneypunct_byname; + + // 22.2.7 message retrieval + class messages_base; + template<typename _CharT> + class messages; + template<typename _CharT> + class messages_byname; + + // 22.1.1 Class locale + class locale + { + public: + // Types: + typedef unsigned int category; + + // Forward decls and friends: + class facet; + class id; + class _Impl; + + friend class facet; + friend class _Impl; + + template<typename _Facet> + friend const _Facet& + use_facet(const locale&); + + template<typename _Facet> + friend bool + has_facet(const locale&) throw(); + + // Category values: + // NB: Order must match _S_facet_categories definition in locale.cc + static const category none = 0; + static const category ctype = 1L << 0; + static const category numeric = 1L << 1; + static const category collate = 1L << 2; + 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); + + // Construct/copy/destroy: + locale() throw(); + + locale(const locale& __other) throw(); + + explicit + locale(const char* __s); + + locale(const locale& __base, const char* __s, category __cat); + + locale(const locale& __base, const locale& __add, category __cat); + + template<typename _Facet> + locale(const locale& __other, _Facet* __f); + + ~locale() throw(); + + const locale& + operator=(const locale& __other) throw(); + + template<typename _Facet> + locale + combine(const locale& __other) const; + + // Locale operations: + string + name() const; + + bool + operator==(const locale& __other) const throw (); + + inline bool + operator!=(const locale& __other) const throw () + { return !(this->operator==(__other)); } + + template<typename _Char, typename _Traits, typename _Alloc> + bool + operator()(const basic_string<_Char, _Traits, _Alloc>& __s1, + const basic_string<_Char, _Traits, _Alloc>& __s2) const; + + // Global locale objects: + static locale + global(const locale&); + + static const locale& + classic(); + + private: + // The (shared) implementation + _Impl* _M_impl; + + // The "C" reference locale + static _Impl* _S_classic; + + // Current global reference locale + static _Impl* _S_global; + + static const size_t _S_num_categories = 6; + + explicit + locale(_Impl*) throw(); + + static inline void + _S_initialize() + { + if (!_S_classic) + classic(); + } + + static category + _S_normalize_category(category); + + void + _M_coalesce(const locale& __base, const locale& __add, category __cat); + }; + + + // Implementation object for locale + class locale::_Impl + { + public: + // Friends. + friend class locale; + friend class locale::facet; + + template<typename _Facet> + friend const _Facet& + use_facet(const locale&); + + template<typename _Facet> + friend bool + has_facet(const locale&) throw(); + + private: + // Data Members. + _Atomic_word _M_references; + facet** _M_facets; + size_t _M_facets_size; + const char* _M_names[_S_num_categories]; + static const locale::id* const _S_id_ctype[]; + static const locale::id* const _S_id_numeric[]; + static const locale::id* const _S_id_collate[]; + static const locale::id* const _S_id_time[]; + static const locale::id* const _S_id_monetary[]; + static const locale::id* const _S_id_messages[]; + static const locale::id* const* const _S_facet_categories[]; + + inline void + _M_add_reference() throw() + { __atomic_add(&_M_references, 1); } + + inline void + _M_remove_reference() throw() + { + if (__exchange_and_add(&_M_references, -1) == 1) + { + try + { delete this; } + catch(...) + { } + } + } + + _Impl(const _Impl&, 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; __ret && i < _S_num_categories - 1; ++i) + __ret &= (strcmp(_M_names[i], _M_names[i + 1]) == 0); + return __ret; + } + + void + _M_replace_categories(const _Impl*, category); + + void + _M_replace_category(const _Impl*, const locale::id* const*); + + void + _M_replace_facet(const _Impl*, const locale::id*); + + void + _M_install_facet(const locale::id*, facet*); + + template<typename _Facet> + inline void + _M_init_facet(_Facet* __facet) + { _M_install_facet(&_Facet::id, __facet); } + }; + + template<typename _Facet> + locale::locale(const locale& __other, _Facet* __f) + { + _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] = "*"; + } + + // 22.1.1.1.2 Class locale::facet + class locale::facet + { + private: + friend class locale; + friend class locale::_Impl; + + _Atomic_word _M_references; + + protected: + // Contains data from the underlying "C" library for default "C" + // or "POSIX" locale. + static __c_locale _S_c_locale; + + explicit + facet(size_t __refs = 0) throw(); + + virtual + ~facet(); + + static void + _S_create_c_locale(__c_locale& __cloc, const char* __s, + __c_locale __old = 0); + + static __c_locale + _S_clone_c_locale(__c_locale& __cloc); + + static void + _S_destroy_c_locale(__c_locale& __cloc); + + private: + void + _M_add_reference() throw(); + + void + _M_remove_reference() throw(); + + facet(const facet&); // Not defined. + + void + operator=(const facet&); // Not defined. + }; + + + // 22.1.1.1.3 Class locale::id + class locale::id + { + private: + friend class locale; + friend class locale::_Impl; + template<typename _Facet> + friend const _Facet& + use_facet(const locale&); + template<typename _Facet> + friend bool + has_facet(const locale&) throw (); + + // NB: There is no accessor for _M_index because it may be used + // before the constructor is run; the effect of calling a member + // function (even an inline) would be undefined. + mutable size_t _M_index; + + // Last id number assigned. + static _Atomic_word _S_highwater; + + void + operator=(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> + const _Facet& + use_facet(const locale& __loc); + + template<typename _Facet> + bool + has_facet(const locale& __loc) throw(); +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/mask_array.h b/contrib/libstdc++/include/bits/mask_array.h new file mode 100644 index 0000000000000..13c01d3cc226e --- /dev/null +++ b/contrib/libstdc++/include/bits/mask_array.h @@ -0,0 +1,167 @@ +// The template and inlines for the -*- C++ -*- mask_array class. + +// Copyright (C) 1997-2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file mask_array.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_MASK_ARRAY_H +#define _CPP_BITS_MASK_ARRAY_H 1 + +#pragma GCC system_header + +namespace std { + + template <class _Tp> class mask_array + { + public: + typedef _Tp value_type; + + void operator= (const valarray<_Tp>&) const; + void operator*= (const valarray<_Tp>&) const; + void operator/= (const valarray<_Tp>&) const; + void operator%= (const valarray<_Tp>&) const; + void operator+= (const valarray<_Tp>&) const; + void operator-= (const valarray<_Tp>&) const; + void operator^= (const valarray<_Tp>&) const; + void operator&= (const valarray<_Tp>&) const; + void operator|= (const valarray<_Tp>&) const; + void operator<<=(const valarray<_Tp>&) const; + void operator>>=(const valarray<_Tp>&) const; + void operator= (const _Tp&); + + // ~mask_array (); + + template<class _Dom> + void operator= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator*= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator/= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator%= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator+= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator-= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator^= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator&= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator|= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator<<=(const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator>>=(const _Expr<_Dom,_Tp>&) const; + + private: + mask_array (_Array<_Tp>, size_t, _Array<bool>); + friend class valarray<_Tp>; + + const size_t _M_sz; + const _Array<bool> _M_mask; + const _Array<_Tp> _M_array; + + mask_array (const mask_array&); + + // not implemented + mask_array (); + mask_array& operator= (const mask_array&); + }; + + + template<typename _Tp> + inline mask_array<_Tp>::mask_array (const mask_array<_Tp>& a) + : _M_sz (a._M_sz), _M_mask (a._M_mask), _M_array (a._M_array) {} + + template<typename _Tp> + inline + mask_array<_Tp>::mask_array (_Array<_Tp> __a, size_t __s, _Array<bool> __m) + : _M_sz (__s), _M_mask (__m), _M_array (__a) {} + + // template<typename _Tp> + // inline mask_array<_Tp>::~mask_array () {} + + template<typename _Tp> + inline void + mask_array<_Tp>::operator= (const _Tp& __t) + { __valarray_fill (_M_array, _M_sz, _M_mask, __t); } + + template<typename _Tp> + inline void + mask_array<_Tp>::operator= (const valarray<_Tp>& __v) const + { __valarray_copy (_Array<_Tp> (__v), __v.size (), _M_array, _M_mask); } + + template<typename _Tp> + template<class E> + inline void + mask_array<_Tp>::operator= (const _Expr<E, _Tp>& __e) const + { __valarray_copy (__e, __e.size (), _M_array, _M_mask); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(op, name) \ +template<typename _Tp> \ +inline void \ +mask_array<_Tp>::operator op##= (const valarray<_Tp>& __v) const \ +{ \ + _Array_augmented_##name (_M_array, _M_mask, \ + _Array<_Tp> (__v), __v.size ()); \ +} \ + \ +template<typename _Tp> template<class E> \ +inline void \ +mask_array<_Tp>::operator op##= (const _Expr<E, _Tp>& __e) const \ +{ \ + _Array_augmented_##name (_M_array, _M_mask, __e, __e.size ()); \ +} + +_DEFINE_VALARRAY_OPERATOR(*, multiplies) +_DEFINE_VALARRAY_OPERATOR(/, divides) +_DEFINE_VALARRAY_OPERATOR(%, modulus) +_DEFINE_VALARRAY_OPERATOR(+, plus) +_DEFINE_VALARRAY_OPERATOR(-, minus) +_DEFINE_VALARRAY_OPERATOR(^, xor) +_DEFINE_VALARRAY_OPERATOR(&, and) +_DEFINE_VALARRAY_OPERATOR(|, or) +_DEFINE_VALARRAY_OPERATOR(<<, shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + +} // std:: + +#endif /* _CPP_BITS_MASK_ARRAY_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/ostream.tcc b/contrib/libstdc++/include/bits/ostream.tcc new file mode 100644 index 0000000000000..d15b9f2afa3c0 --- /dev/null +++ b/contrib/libstdc++/include/bits/ostream.tcc @@ -0,0 +1,704 @@ +// ostream classes -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.6.2 Output streams +// + +#pragma GCC system_header + +#include <locale> + +namespace std +{ + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>::sentry:: + sentry(basic_ostream<_CharT,_Traits>& __os) + : _M_ok(__os.good()), _M_os(__os) + { + // XXX MT + if (_M_ok && __os.tie()) + __os.tie()->flush(); + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>:: + operator<<(__ostream_type& (*__pf)(__ostream_type&)) + { + sentry __cerb(*this); + if (__cerb) + { + try + { __pf(*this); } + catch(exception& __fail) + { + // 27.6.2.5.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>:: + operator<<(__ios_type& (*__pf)(__ios_type&)) + { + sentry __cerb(*this); + if (__cerb) + { + try + { __pf(*this); } + catch(exception& __fail) + { + // 27.6.2.5.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>:: + operator<<(ios_base& (*__pf)(ios_base&)) + { + sentry __cerb(*this); + if (__cerb) + { + try + { __pf(*this); } + catch(exception& __fail) + { + // 27.6.2.5.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(__streambuf_type* __sbin) + { + sentry __cerb(*this); + if (__cerb) + { + 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) + this->setstate(ios_base::failbit); + } + catch(exception& __fail) + { + // 27.6.2.5.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(bool __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(long __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + char_type __c = this->fill(); + ios_base::fmtflags __fmt = this->flags() & ios_base::basefield; + if (_M_check_facet(_M_fnumput)) + { + bool __b = false; + 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(); + } + else + __b = _M_fnumput->put(*this, *this, __c, __n).failed(); + if (__b) + this->setstate(ios_base::badbit); + } + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + +#ifdef _GLIBCPP_USE_LONG_LONG + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(long long __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + char_type __c = this->fill(); + ios_base::fmtflags __fmt = this->flags() & ios_base::basefield; + if (_M_check_facet(_M_fnumput)) + { + bool __b = false; + if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) + { + unsigned long long __l; + __l = static_cast<unsigned long long>(__n); + __b = _M_fnumput->put(*this, *this, __c, __l).failed(); + } + else + __b = _M_fnumput->put(*this, *this, __c, __n).failed(); + if (__b) + this->setstate(ios_base::badbit); + } + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } +#endif + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(double __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(long double __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::operator<<(const void* __n) + { + sentry __cerb(*this); + if (__cerb) + { + try + { + if (_M_check_facet(_M_fnumput)) + if (_M_fnumput->put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // 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; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::put(char_type __c) + { + sentry __cerb(*this); + if (__cerb) + { + int_type __put = rdbuf()->sputc(__c); + if (traits_type::eq_int_type(__put, traits_type::eof())) + this->setstate(ios_base::badbit); + } + return *this; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::write(const _CharT* __s, streamsize __n) + { + sentry __cerb(*this); + if (__cerb) + { + streamsize __put = this->rdbuf()->sputn(__s, __n); + if ( __put != __n) + this->setstate(ios_base::badbit); + } + return *this; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::flush() + { + sentry __cerb(*this); + if (__cerb) + { + if (this->rdbuf() && this->rdbuf()->pubsync() == -1) + this->setstate(ios_base::badbit); + } + return *this; + } + + template<typename _CharT, typename _Traits> + typename basic_ostream<_CharT, _Traits>::pos_type + basic_ostream<_CharT, _Traits>::tellp() + { + pos_type __ret = pos_type(-1); + if (!this->fail()) + __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out); + return __ret; + } + + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>::seekp(pos_type __pos) + { + if (!this->fail()) + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +// 136. seekp, seekg setting wrong streams? + pos_type __err = this->rdbuf()->pubseekpos(__pos, ios_base::out); + +// 129. Need error indication from seekp() and seekg() + if (__err == pos_type(off_type(-1))) + this->setstate(ios_base::failbit); +#endif + } + return *this; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + basic_ostream<_CharT, _Traits>:: + seekp(off_type __off, ios_base::seekdir __d) + { + if (!this->fail()) + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +// 136. seekp, seekg setting wrong streams? + pos_type __err = this->rdbuf()->pubseekoff(__off, __d, + ios_base::out); + +// 129. Need error indication from seekp() and seekg() + if (__err == pos_type(off_type(-1))) + this->setstate(ios_base::failbit); +#endif + } + return *this; + } + + // 27.6.2.5.4 Character inserters. + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c) + { + typedef basic_ostream<_CharT, _Traits> __ostream_type; + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + try + { + streamsize __w = __out.width(); + _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); + __len = __w; + } + __out.write(__pads, __len); + __out.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __out.setstate(ios_base::badbit); + if ((__out.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + return __out; + } + + // Specializations. + template <class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>& __out, char __c) + { + typedef basic_ostream<char, _Traits> __ostream_type; + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + try + { + streamsize __w = __out.width(); + char* __pads = static_cast<char*>(__builtin_alloca(__w + 1)); + __pads[0] = __c; + streamsize __len = 1; + if (__w > __len) + { + __pad(__out, __out.fill(), __pads, &__c, __w, __len, false); + __len = __w; + } + __out.write(__pads, __len); + __out.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __out.setstate(ios_base::badbit); + if ((__out.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + return __out; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s) + { + typedef basic_ostream<_CharT, _Traits> __ostream_type; + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + try + { + streamsize __w = __out.width(); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); + streamsize __len = static_cast<streamsize>(_Traits::length(__s)); + if (__w > __len) + { + __pad(__out, __out.fill(), __pads, __s, __w, __len, false); + __s = __pads; + __len = __w; + } + __out.write(__s, __len); + __out.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __out.setstate(ios_base::badbit); + if ((__out.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + return __out; + } + + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s) + { + typedef basic_ostream<_CharT, _Traits> __ostream_type; +#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; +#endif + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + size_t __clen = __ctraits_type::length(__s); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__clen + 1))); + for (size_t __i = 0; __i <= __clen; ++__i) + __ws[__i] = __out.widen(__s[__i]); + _CharT* __str = __ws; + + try + { + streamsize __len = static_cast<streamsize>(__clen); + streamsize __w = __out.width(); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); + + if (__w > __len) + { + __pad(__out, __out.fill(), __pads, __ws, __w, __len, false); + __str = __pads; + __len = __w; + } + __out.write(__str, __len); + __out.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __out.setstate(ios_base::badbit); + if ((__out.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + return __out; + } + + // Partial specializations. + template<class _Traits> + basic_ostream<char, _Traits>& + operator<<(basic_ostream<char, _Traits>& __out, const char* __s) + { + typedef basic_ostream<char, _Traits> __ostream_type; + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + 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); + __s = __pads; + __len = __w; + } + __out.write(__s, __len); + __out.width(0); + } + catch(exception& __fail) + { + // 27.6.1.2.1 Common requirements. + // Turn this on without causing an ios::failure to be thrown. + __out.setstate(ios_base::badbit); + if ((__out.exceptions() & ios_base::badbit) != 0) + __throw_exception_again; + } + } + return __out; + } + + // 21.3.7.9 basic_string::operator<< + template<typename _CharT, typename _Traits, typename _Alloc> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __out, + const basic_string<_CharT, _Traits, _Alloc>& __str) + { + typedef basic_ostream<_CharT, _Traits> __ostream_type; + typename __ostream_type::sentry __cerb(__out); + if (__cerb) + { + const _CharT* __s = __str.data(); + streamsize __w = __out.width(); + _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); + streamsize __len = static_cast<streamsize>(__str.size()); +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + // 25. String operator<< uses width() value wrong +#endif + if (__w > __len) + { + __pad(__out, __out.fill(), __pads, __s, __w, __len, false); + __s = __pads; + __len = __w; + } + streamsize __res = __out.rdbuf()->sputn(__s, __len); + __out.width(0); + if (__res != __len) + __out.setstate(ios_base::failbit); + } + return __out; + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class basic_ostream<char>; + extern template ostream& endl(ostream&); + extern template ostream& ends(ostream&); + extern template ostream& flush(ostream&); + extern template ostream& operator<<(ostream&, char); + extern template ostream& operator<<(ostream&, unsigned char); + extern template ostream& operator<<(ostream&, signed char); + extern template ostream& operator<<(ostream&, const char*); + extern template ostream& operator<<(ostream&, const unsigned char*); + extern template ostream& operator<<(ostream&, const signed char*); + + extern template class basic_ostream<wchar_t>; + extern template wostream& endl(wostream&); + extern template wostream& ends(wostream&); + extern template wostream& flush(wostream&); + extern template wostream& operator<<(wostream&, wchar_t); + extern template wostream& operator<<(wostream&, char); + extern template wostream& operator<<(wostream&, const wchar_t*); + extern template wostream& operator<<(wostream&, const char*); +} // namespace std diff --git a/contrib/libstdc++/include/bits/pthread_allocimpl.h b/contrib/libstdc++/include/bits/pthread_allocimpl.h new file mode 100644 index 0000000000000..050b2060fc459 --- /dev/null +++ b/contrib/libstdc++/include/bits/pthread_allocimpl.h @@ -0,0 +1,525 @@ +// POSIX thread-related memory allocation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file pthread_allocimpl.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_PTHREAD_ALLOCIMPL_H +#define _CPP_BITS_PTHREAD_ALLOCIMPL_H 1 + +// Pthread-specific node allocator. +// This is similar to the default allocator, except that free-list +// information is kept separately for each thread, avoiding locking. +// This should be reasonably fast even in the presence of threads. +// The down side is that storage may not be well-utilized. +// It is not an error to allocate memory in thread A and deallocate +// it in thread B. But this effectively transfers ownership of the memory, +// so that it can only be reallocated by thread B. Thus this can effectively +// result in a storage leak if it's done on a regular basis. +// It can also result in frequent sharing of +// cache lines among processors, with potentially serious performance +// consequences. + +#include <bits/c++config.h> +#include <cerrno> +#include <bits/stl_alloc.h> +#ifndef __RESTRICT +# define __RESTRICT +#endif + +#include <new> + +namespace std +{ + +#define __STL_DATA_ALIGNMENT 8 + +union _Pthread_alloc_obj { + union _Pthread_alloc_obj * __free_list_link; + char __client_data[__STL_DATA_ALIGNMENT]; /* The client sees this. */ +}; + +// Pthread allocators don't appear to the client to have meaningful +// instances. We do in fact need to associate some state with each +// thread. That state is represented by +// _Pthread_alloc_per_thread_state<_Max_size>. + +template<size_t _Max_size> +struct _Pthread_alloc_per_thread_state { + typedef _Pthread_alloc_obj __obj; + enum { _S_NFREELISTS = _Max_size/__STL_DATA_ALIGNMENT }; + _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS]; + _Pthread_alloc_per_thread_state<_Max_size> * __next; + // Free list link for list of available per thread structures. + // When one of these becomes available for reuse due to thread + // termination, any objects in its free list remain associated + // with it. The whole structure may then be used by a newly + // created thread. + _Pthread_alloc_per_thread_state() : __next(0) + { + memset((void *)__free_list, 0, (size_t) _S_NFREELISTS * sizeof(__obj *)); + } + // Returns an object of size __n, and possibly adds to size n free list. + void *_M_refill(size_t __n); +}; + +// Pthread-specific allocator. +// The argument specifies the largest object size allocated from per-thread +// free lists. Larger objects are allocated using malloc_alloc. +// Max_size must be a power of 2. +template <size_t _Max_size = 128> +class _Pthread_alloc_template { + +public: // but only for internal use: + + typedef _Pthread_alloc_obj __obj; + + // 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); + + enum {_S_ALIGN = __STL_DATA_ALIGNMENT}; + + static size_t _S_round_up(size_t __bytes) { + return (((__bytes) + (int) _S_ALIGN-1) & ~((int) _S_ALIGN - 1)); + } + static size_t _S_freelist_index(size_t __bytes) { + return (((__bytes) + (int) _S_ALIGN-1)/(int)_S_ALIGN - 1); + } + +private: + // Chunk allocation state. And other shared state. + // Protected by _S_chunk_allocator_lock. + static pthread_mutex_t _S_chunk_allocator_lock; + static char *_S_start_free; + static char *_S_end_free; + static size_t _S_heap_size; + static _Pthread_alloc_per_thread_state<_Max_size>* _S_free_per_thread_states; + static pthread_key_t _S_key; + static bool _S_key_initialized; + // Pthread key under which per thread state is stored. + // Allocator instances that are currently unclaimed by any thread. + static void _S_destructor(void *instance); + // Function to be called on thread exit to reclaim per thread + // state. + static _Pthread_alloc_per_thread_state<_Max_size> *_S_new_per_thread_state(); + // Return a recycled or new per thread state. + static _Pthread_alloc_per_thread_state<_Max_size> *_S_get_per_thread_state(); + // ensure that the current thread has an associated + // per thread state. + class _M_lock; + friend class _M_lock; + class _M_lock { + public: + _M_lock () { pthread_mutex_lock(&_S_chunk_allocator_lock); } + ~_M_lock () { pthread_mutex_unlock(&_S_chunk_allocator_lock); } + }; + +public: + + /* n must be > 0 */ + static void * allocate(size_t __n) + { + __obj * volatile * __my_free_list; + __obj * __RESTRICT __result; + _Pthread_alloc_per_thread_state<_Max_size>* __a; + + if (__n > _Max_size) { + return(malloc_alloc::allocate(__n)); + } + if (!_S_key_initialized || + !(__a = (_Pthread_alloc_per_thread_state<_Max_size>*) + pthread_getspecific(_S_key))) { + __a = _S_get_per_thread_state(); + } + __my_free_list = __a -> __free_list + _S_freelist_index(__n); + __result = *__my_free_list; + if (__result == 0) { + void *__r = __a -> _M_refill(_S_round_up(__n)); + return __r; + } + *__my_free_list = __result -> __free_list_link; + return (__result); + }; + + /* p may not be 0 */ + static void deallocate(void *__p, size_t __n) + { + __obj *__q = (__obj *)__p; + __obj * volatile * __my_free_list; + _Pthread_alloc_per_thread_state<_Max_size>* __a; + + if (__n > _Max_size) { + malloc_alloc::deallocate(__p, __n); + return; + } + if (!_S_key_initialized || + !(__a = (_Pthread_alloc_per_thread_state<_Max_size> *) + pthread_getspecific(_S_key))) { + __a = _S_get_per_thread_state(); + } + __my_free_list = __a->__free_list + _S_freelist_index(__n); + __q -> __free_list_link = *__my_free_list; + *__my_free_list = __q; + } + + static void * reallocate(void *__p, size_t __old_sz, size_t __new_sz); + +} ; + +typedef _Pthread_alloc_template<> pthread_alloc; + + +template <size_t _Max_size> +void _Pthread_alloc_template<_Max_size>::_S_destructor(void * __instance) +{ + _M_lock __lock_instance; // Need to acquire lock here. + _Pthread_alloc_per_thread_state<_Max_size>* __s = + (_Pthread_alloc_per_thread_state<_Max_size> *)__instance; + __s -> __next = _S_free_per_thread_states; + _S_free_per_thread_states = __s; +} + +template <size_t _Max_size> +_Pthread_alloc_per_thread_state<_Max_size> * +_Pthread_alloc_template<_Max_size>::_S_new_per_thread_state() +{ + /* lock already held here. */ + if (0 != _S_free_per_thread_states) { + _Pthread_alloc_per_thread_state<_Max_size> *__result = + _S_free_per_thread_states; + _S_free_per_thread_states = _S_free_per_thread_states -> __next; + return __result; + } else { + return new _Pthread_alloc_per_thread_state<_Max_size>; + } +} + +template <size_t _Max_size> +_Pthread_alloc_per_thread_state<_Max_size> * +_Pthread_alloc_template<_Max_size>::_S_get_per_thread_state() +{ + /*REFERENCED*/ + _M_lock __lock_instance; // Need to acquire lock here. + int __ret_code; + _Pthread_alloc_per_thread_state<_Max_size> * __result; + if (!_S_key_initialized) { + if (pthread_key_create(&_S_key, _S_destructor)) { + std::__throw_bad_alloc(); // defined in funcexcept.h + } + _S_key_initialized = true; + } + __result = _S_new_per_thread_state(); + __ret_code = pthread_setspecific(_S_key, __result); + if (__ret_code) { + if (__ret_code == ENOMEM) { + std::__throw_bad_alloc(); + } else { + // EINVAL + abort(); + } + } + return __result; +} + +/* We allocate memory in large chunks in order to avoid fragmenting */ +/* the malloc heap too much. */ +/* We assume that size is properly aligned. */ +template <size_t _Max_size> +char *_Pthread_alloc_template<_Max_size> +::_S_chunk_alloc(size_t __size, int &__nobjs) +{ + { + char * __result; + size_t __total_bytes; + size_t __bytes_left; + /*REFERENCED*/ + _M_lock __lock_instance; // Acquire lock for this routine + + __total_bytes = __size * __nobjs; + __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 = __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) { + _Pthread_alloc_per_thread_state<_Max_size>* __a = + (_Pthread_alloc_per_thread_state<_Max_size>*) + pthread_getspecific(_S_key); + __obj * volatile * __my_free_list = + __a->__free_list + _S_freelist_index(__bytes_left); + + ((__obj *)_S_start_free) -> __free_list_link = *__my_free_list; + *__my_free_list = (__obj *)_S_start_free; + } +# ifdef _SGI_SOURCE + // Try to get memory that's aligned on something like a + // cache line boundary, so as to avoid parceling out + // parts of the same line to different threads and thus + // possibly different processors. + { + const int __cache_line_size = 128; // probable upper bound + __bytes_to_get &= ~(__cache_line_size-1); + _S_start_free = (char *)memalign(__cache_line_size, __bytes_to_get); + if (0 == _S_start_free) { + _S_start_free = (char *)malloc_alloc::allocate(__bytes_to_get); + } + } +# else /* !SGI_SOURCE */ + _S_start_free = (char *)malloc_alloc::allocate(__bytes_to_get); +# endif + _S_heap_size += __bytes_to_get; + _S_end_free = _S_start_free + __bytes_to_get; + } + } + // lock is released here + return(_S_chunk_alloc(__size, __nobjs)); +} + + +/* Returns an object of size n, and optionally adds to size n free list.*/ +/* We assume that n is properly aligned. */ +/* We hold the allocation lock. */ +template <size_t _Max_size> +void *_Pthread_alloc_per_thread_state<_Max_size> +::_M_refill(size_t __n) +{ + int __nobjs = 128; + char * __chunk = + _Pthread_alloc_template<_Max_size>::_S_chunk_alloc(__n, __nobjs); + __obj * volatile * __my_free_list; + __obj * __result; + __obj * __current_obj, * __next_obj; + int __i; + + if (1 == __nobjs) { + return(__chunk); + } + __my_free_list = __free_list + + _Pthread_alloc_template<_Max_size>::_S_freelist_index(__n); + + /* 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 -> __free_list_link = 0; + break; + } else { + __current_obj -> __free_list_link = __next_obj; + } + } + return(__result); +} + +template <size_t _Max_size> +void *_Pthread_alloc_template<_Max_size> +::reallocate(void *__p, size_t __old_sz, size_t __new_sz) +{ + void * __result; + size_t __copy_sz; + + if (__old_sz > _Max_size + && __new_sz > _Max_size) { + return(realloc(__p, __new_sz)); + } + 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); +} + +template <size_t _Max_size> +_Pthread_alloc_per_thread_state<_Max_size> * +_Pthread_alloc_template<_Max_size>::_S_free_per_thread_states = 0; + +template <size_t _Max_size> +pthread_key_t _Pthread_alloc_template<_Max_size>::_S_key; + +template <size_t _Max_size> +bool _Pthread_alloc_template<_Max_size>::_S_key_initialized = false; + +template <size_t _Max_size> +pthread_mutex_t _Pthread_alloc_template<_Max_size>::_S_chunk_allocator_lock += PTHREAD_MUTEX_INITIALIZER; + +template <size_t _Max_size> +char *_Pthread_alloc_template<_Max_size> +::_S_start_free = 0; + +template <size_t _Max_size> +char *_Pthread_alloc_template<_Max_size> +::_S_end_free = 0; + +template <size_t _Max_size> +size_t _Pthread_alloc_template<_Max_size> +::_S_heap_size = 0; + + +template <class _Tp> +class pthread_allocator { + typedef pthread_alloc _S_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 _NewType> struct rebind { + typedef pthread_allocator<_NewType> other; + }; + + pthread_allocator() throw() {} + pthread_allocator(const pthread_allocator& a) throw() {} + template <class _OtherType> + pthread_allocator(const pthread_allocator<_OtherType>&) + throw() {} + ~pthread_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*>(_S_Alloc::allocate(__n * sizeof(_Tp))) + : 0; + } + + // p is not permitted to be a null pointer. + void deallocate(pointer __p, size_type __n) + { _S_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 pthread_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 _NewType> struct rebind { + typedef pthread_allocator<_NewType> other; + }; +}; + +template <size_t _Max_size> +inline bool operator==(const _Pthread_alloc_template<_Max_size>&, + const _Pthread_alloc_template<_Max_size>&) +{ + return true; +} + +template <class _T1, class _T2> +inline bool operator==(const pthread_allocator<_T1>&, + const pthread_allocator<_T2>& a2) +{ + return true; +} + +template <class _T1, class _T2> +inline bool operator!=(const pthread_allocator<_T1>&, + const pthread_allocator<_T2>&) +{ + return false; +} + +template <class _Tp, size_t _Max_size> +struct _Alloc_traits<_Tp, _Pthread_alloc_template<_Max_size> > +{ + static const bool _S_instanceless = true; + typedef simple_alloc<_Tp, _Pthread_alloc_template<_Max_size> > _Alloc_type; + typedef __allocator<_Tp, _Pthread_alloc_template<_Max_size> > + allocator_type; +}; + +template <class _Tp, class _Atype, size_t _Max> +struct _Alloc_traits<_Tp, __allocator<_Atype, _Pthread_alloc_template<_Max> > > +{ + static const bool _S_instanceless = true; + typedef simple_alloc<_Tp, _Pthread_alloc_template<_Max> > _Alloc_type; + typedef __allocator<_Tp, _Pthread_alloc_template<_Max> > allocator_type; +}; + +template <class _Tp, class _Atype> +struct _Alloc_traits<_Tp, pthread_allocator<_Atype> > +{ + static const bool _S_instanceless = true; + typedef simple_alloc<_Tp, _Pthread_alloc_template<> > _Alloc_type; + typedef pthread_allocator<_Tp> allocator_type; +}; + + +} // namespace std + +#endif /* _CPP_BITS_PTHREAD_ALLOCIMPL_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/slice.h b/contrib/libstdc++/include/bits/slice.h new file mode 100644 index 0000000000000..d3da664f8d1aa --- /dev/null +++ b/contrib/libstdc++/include/bits/slice.h @@ -0,0 +1,85 @@ +// The template and inlines for the -*- C++ -*- slice class. + +// Copyright (C) 1997-1999, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file slice.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_SLICE_H +#define _CPP_BITS_SLICE_H 1 + +#pragma GCC system_header + +namespace std +{ + +class slice +{ +public: + slice (); + slice (size_t, size_t, size_t); + + size_t start () const; + size_t size () const; + size_t stride () const; + +private: + size_t _M_off; // offset + size_t _M_sz; // size + size_t _M_st; // stride unit +}; + +inline slice::slice () {} + +inline slice::slice (size_t __o, size_t __d, size_t __s) + : _M_off (__o), _M_sz (__d), _M_st (__s) {} + +inline size_t +slice::start () const + { return _M_off; } + +inline size_t +slice::size () const + { return _M_sz; } + +inline size_t +slice::stride () const + { return _M_st; } + +} // std:: + + +#endif /* _CPP_BITS_SLICE_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/slice_array.h b/contrib/libstdc++/include/bits/slice_array.h new file mode 100644 index 0000000000000..c8908f8bb53bb --- /dev/null +++ b/contrib/libstdc++/include/bits/slice_array.h @@ -0,0 +1,180 @@ +// The template and inlines for the -*- C++ -*- slice_array class. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file slice_array.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_SLICE_ARRAY_H +#define _CPP_BITS_SLICE_ARRAY_H 1 + +#pragma GCC system_header + +namespace std +{ + + template<typename _Tp> + class slice_array + { + public: + typedef _Tp value_type; + + // This constructor is implemented since we need to return a value. + slice_array (const slice_array&); + + // This operator must be public. See DR-253. + slice_array& operator= (const slice_array&); + + void operator= (const valarray<_Tp>&) const; + void operator*= (const valarray<_Tp>&) const; + void operator/= (const valarray<_Tp>&) const; + void operator%= (const valarray<_Tp>&) const; + void operator+= (const valarray<_Tp>&) const; + void operator-= (const valarray<_Tp>&) const; + void operator^= (const valarray<_Tp>&) const; + void operator&= (const valarray<_Tp>&) const; + void operator|= (const valarray<_Tp>&) const; + void operator<<= (const valarray<_Tp>&) const; + void operator>>= (const valarray<_Tp>&) const; + void operator= (const _Tp &); + // ~slice_array (); + + template<class _Dom> + void operator= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator*= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator/= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator%= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator+= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator-= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator^= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator&= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator|= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator<<= (const _Expr<_Dom,_Tp>&) const; + template<class _Dom> + void operator>>= (const _Expr<_Dom,_Tp>&) const; + + private: + friend class valarray<_Tp>; + slice_array(_Array<_Tp>, const slice&); + + const size_t _M_sz; + const size_t _M_stride; + const _Array<_Tp> _M_array; + + // not implemented + slice_array (); + }; + + template<typename _Tp> + inline slice_array<_Tp>::slice_array (_Array<_Tp> __a, const slice& __s) + : _M_sz (__s.size ()), _M_stride (__s.stride ()), + _M_array (__a.begin () + __s.start ()) {} + + + template<typename _Tp> + inline slice_array<_Tp>::slice_array(const slice_array<_Tp>& a) + : _M_sz(a._M_sz), _M_stride(a._M_stride), _M_array(a._M_array) {} + + // template<typename _Tp> + // inline slice_array<_Tp>::~slice_array () {} + + template<typename _Tp> + 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); + return *this; + } + + + template<typename _Tp> + inline void + slice_array<_Tp>::operator= (const _Tp& __t) + { __valarray_fill (_M_array, _M_sz, _M_stride, __t); } + + template<typename _Tp> + inline void + slice_array<_Tp>::operator= (const valarray<_Tp>& __v) const + { __valarray_copy (_Array<_Tp> (__v), _M_array, _M_sz, _M_stride); } + + template<typename _Tp> + template<class _Dom> + inline void + slice_array<_Tp>::operator= (const _Expr<_Dom,_Tp>& __e) const + { __valarray_copy (__e, _M_sz, _M_array, _M_stride); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(op, name) \ +template<typename _Tp> \ +inline void \ +slice_array<_Tp>::operator op##= (const valarray<_Tp>& __v) const \ +{ \ + _Array_augmented_##name (_M_array, _M_sz, _M_stride, _Array<_Tp> (__v));\ +} \ + \ +template<typename _Tp> template<class _Dom> \ +inline void \ +slice_array<_Tp>::operator op##= (const _Expr<_Dom,_Tp>& __e) const \ +{ \ + _Array_augmented_##name (_M_array, _M_stride, __e, _M_sz); \ +} + + +_DEFINE_VALARRAY_OPERATOR(*, multiplies) +_DEFINE_VALARRAY_OPERATOR(/, divides) +_DEFINE_VALARRAY_OPERATOR(%, modulus) +_DEFINE_VALARRAY_OPERATOR(+, plus) +_DEFINE_VALARRAY_OPERATOR(-, minus) +_DEFINE_VALARRAY_OPERATOR(^, xor) +_DEFINE_VALARRAY_OPERATOR(&, and) +_DEFINE_VALARRAY_OPERATOR(|, or) +_DEFINE_VALARRAY_OPERATOR(<<, shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + +} // std:: + +#endif /* _CPP_BITS_SLICE_ARRAY_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/sstream.tcc b/contrib/libstdc++/include/bits/sstream.tcc new file mode 100644 index 0000000000000..e7419504d3e54 --- /dev/null +++ b/contrib/libstdc++/include/bits/sstream.tcc @@ -0,0 +1,238 @@ +// String based streams -*- C++ -*- + +// Copyright (C) 1997, 1998, 1999, 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.7 String-based streams +// + +#ifndef _CPP_BITS_SSTREAM_TCC +#define _CPP_BITS_SSTREAM_TCC 1 + +#pragma GCC system_header + +#include <sstream> + +namespace std +{ + template <class _CharT, class _Traits, class _Alloc> + typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type + basic_stringbuf<_CharT, _Traits, _Alloc>:: + pbackfail(int_type __c) + { + int_type __ret = traits_type::eof(); + bool __testeof = traits_type::eq_int_type(__c, traits_type::eof()); + bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur; + + // Try to put back __c into input sequence in one of three ways. + // Order these tests done in is unspecified by the standard. + if (__testpos) + { + if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) + && !__testeof) + { + --_M_in_cur; + __ret = __c; + } + else if (!__testeof) + { + --_M_in_cur; + *_M_in_cur = traits_type::to_char_type(__c); + __ret = __c; + } + else if (__testeof) + { + --_M_in_cur; + __ret = traits_type::not_eof(__c); + } + } + return __ret; + } + + template <class _CharT, class _Traits, class _Alloc> + typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type + basic_stringbuf<_CharT, _Traits, _Alloc>:: + overflow(int_type __c) + { + int_type __ret = traits_type::eof(); + bool __testeof = traits_type::eq_int_type(__c, __ret); + bool __testwrite = _M_out_cur < _M_buf + _M_buf_size; + bool __testout = _M_mode & ios_base::out; + + // Try to append __c into output sequence in one of two ways. + // Order these tests done in is unspecified by the standard. + if (__testout) + { + if (!__testeof) + { + __size_type __len = max(_M_buf_size, _M_buf_size_opt); + __len *= 2; + + if (__testwrite) + __ret = this->sputc(__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_really_sync(_M_in_cur - _M_in_beg, + _M_out_cur - _M_out_beg); + *_M_out_cur = traits_type::to_char_type(__c); + _M_out_cur_move(1); + __ret = __c; + } + } + else + __ret = traits_type::not_eof(__c); + } + return __ret; + } + + template <class _CharT, class _Traits, class _Alloc> + typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type + basic_stringbuf<_CharT, _Traits, _Alloc>:: + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) + { + pos_type __ret = pos_type(off_type(-1)); + 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; + __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; + char_type* __curo = NULL; + char_type* __endi = NULL; + char_type* __endo = NULL; + + if (__testin || __testboth) + { + __curi = this->gptr(); + __endi = this->egptr(); + } + if (__testout || __testboth) + { + __curo = this->pptr(); + __endo = this->epptr(); + } + + off_type __newoffi = 0; + off_type __newoffo = 0; + if (__way == ios_base::cur) + { + __newoffi = __curi - __beg; + __newoffo = __curo - __beg; + } + else if (__way == ios_base::end) + { + __newoffi = __endi - __beg; + __newoffo = __endo - __beg; + } + + if ((__testin || __testboth) + && __newoffi + __off >= 0 && __endi - __beg >= __newoffi + __off) + { + _M_in_cur = __beg + __newoffi + __off; + __ret = pos_type(__newoffi); + } + if ((__testout || __testboth) + && __newoffo + __off >= 0 && __endo - __beg >= __newoffo + __off) + { + _M_out_cur_move(__newoffo + __off - (_M_out_cur - __beg)); + __ret = pos_type(__newoffo); + } + } + return __ret; + } + + template <class _CharT, class _Traits, class _Alloc> + typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type + basic_stringbuf<_CharT, _Traits, _Alloc>:: + seekpos(pos_type __sp, ios_base::openmode __mode) + { + pos_type __ret = pos_type(off_type(-1)); + + if (_M_buf_size) + { + off_type __pos = __sp._M_position(); + 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; + } + + // Inhibit implicit instantiations for required instantiations, + // 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>; + extern template class basic_stringstream<wchar_t>; +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/stl_algo.h b/contrib/libstdc++/include/bits/stl_algo.h new file mode 100644 index 0000000000000..009c409b6fb17 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_algo.h @@ -0,0 +1,4351 @@ +// Algorithm implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_algo.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_ALGO_H +#define __GLIBCPP_INTERNAL_ALGO_H + +#include <bits/stl_heap.h> +#include <bits/stl_tempbuf.h> // for _Temporary_buffer + +// See concept_check.h for the __glibcpp_*_requires macros. + +namespace std +{ + + /** + * @brief Find the median of three values. + * @param a A value. + * @param b A value. + * @param c A value. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @c l<=m<=n + * then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template<typename _Tp> + inline const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c) + { + // concept requirements + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + if (__a < __b) + if (__b < __c) + return __b; + else if (__a < __c) + return __c; + else + return __a; + else if (__a < __c) + return __a; + else if (__b < __c) + return __c; + else + return __b; + } + + /** + * @brief Find the median of three values using a predicate for comparison. + * @param a A value. + * @param b A value. + * @param c A value. + * @param comp A binary predicate. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @p comp(l,m) + * and @p comp(m,n) are both true then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template<typename _Tp, typename _Compare> + inline const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_BinaryFunctionConcept<_Compare,bool,_Tp,_Tp>) + if (__comp(__a, __b)) + if (__comp(__b, __c)) + return __b; + else if (__comp(__a, __c)) + return __c; + else + return __a; + else if (__comp(__a, __c)) + return __a; + else if (__comp(__b, __c)) + return __c; + else + return __b; + } + + /** + * @brief Apply a function to every element of a sequence. + * @param first An input iterator. + * @param last An input iterator. + * @param f A unary function object. + * @return @p f. + * + * Applies the function object @p f to each element in the range + * @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> + _Function + for_each(_InputIter __first, _InputIter __last, _Function __f) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + for ( ; __first != __last; ++__first) + __f(*__first); + return __f; + } + + /** + * @if maint + * This is an overload used by find() for the Input Iterator case. + * @endif + */ + template<typename _InputIter, typename _Tp> + inline _InputIter + find(_InputIter __first, _InputIter __last, + const _Tp& __val, + input_iterator_tag) + { + while (__first != __last && !(*__first == __val)) + ++__first; + return __first; + } + + /** + * @if maint + * This is an overload used by find_if() for the Input Iterator case. + * @endif + */ + template<typename _InputIter, typename _Predicate> + inline _InputIter + find_if(_InputIter __first, _InputIter __last, + _Predicate __pred, + input_iterator_tag) + { + while (__first != __last && !__pred(*__first)) + ++__first; + return __first; + } + + /** + * @if maint + * This is an overload used by find() for the RAI case. + * @endif + */ + template<typename _RandomAccessIter, typename _Tp> + _RandomAccessIter + find(_RandomAccessIter __first, _RandomAccessIter __last, + const _Tp& __val, + random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIter>::difference_type __trip_count + = (__last - __first) >> 2; + + for ( ; __trip_count > 0 ; --__trip_count) { + if (*__first == __val) return __first; + ++__first; + + if (*__first == __val) return __first; + ++__first; + + if (*__first == __val) return __first; + ++__first; + + if (*__first == __val) return __first; + ++__first; + } + + switch(__last - __first) { + case 3: + if (*__first == __val) return __first; + ++__first; + case 2: + if (*__first == __val) return __first; + ++__first; + case 1: + if (*__first == __val) return __first; + ++__first; + case 0: + default: + return __last; + } + } + + /** + * @if maint + * This is an overload used by find_if() for the RAI case. + * @endif + */ + template<typename _RandomAccessIter, typename _Predicate> + _RandomAccessIter + find_if(_RandomAccessIter __first, _RandomAccessIter __last, + _Predicate __pred, + random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIter>::difference_type __trip_count + = (__last - __first) >> 2; + + for ( ; __trip_count > 0 ; --__trip_count) { + if (__pred(*__first)) return __first; + ++__first; + + if (__pred(*__first)) return __first; + ++__first; + + if (__pred(*__first)) return __first; + ++__first; + + if (__pred(*__first)) return __first; + ++__first; + } + + switch(__last - __first) { + case 3: + if (__pred(*__first)) return __first; + ++__first; + case 2: + if (__pred(*__first)) return __first; + ++__first; + case 1: + if (__pred(*__first)) return __first; + ++__first; + case 0: + default: + return __last; + } + } + + /** + * @brief Find the first occurrence of a value in a sequence. + * @param first An input iterator. + * @param last An input iterator. + * @param val The value to find. + * @return The first iterator @c i in the range @p [first,last) + * such that @c *i == @p val, or @p last if no such iterator exists. + */ + template<typename _InputIter, typename _Tp> + inline _InputIter + find(_InputIter __first, _InputIter __last, + const _Tp& __val) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter>::value_type, _Tp>) + return find(__first, __last, __val, __iterator_category(__first)); + } + + /** + * @brief Find the first element in a sequence for which a predicate is true. + * @param first An input iterator. + * @param last An input iterator. + * @param pred A predicate. + * @return The first iterator @c i in the range @p [first,last) + * such that @p pred(*i) is true, or @p last if no such iterator exists. + */ + template<typename _InputIter, typename _Predicate> + inline _InputIter + find_if(_InputIter __first, _InputIter __last, + _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIter>::value_type>) + return find_if(__first, __last, __pred, __iterator_category(__first)); + } + + /** + * @brief Find two adjacent values in a sequence that are equal. + * @param first A forward iterator. + * @param last A forward iterator. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [first,last) and such that @c *i == @c *(i+1), + * or @p last if no such iterator exists. + */ + template<typename _ForwardIter> + _ForwardIter + adjacent_find(_ForwardIter __first, _ForwardIter __last) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIter>::value_type>) + if (__first == __last) + return __last; + _ForwardIter __next = __first; + while(++__next != __last) { + if (*__first == *__next) + return __first; + __first = __next; + } + return __last; + } + + /** + * @brief Find two adjacent values in a sequence using a predicate. + * @param first A forward iterator. + * @param last A forward iterator. + * @param binary_pred A binary predicate. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [first,last) and such that + * @p binary_pred(*i,*(i+1)) is true, or @p last if no such iterator + * exists. + */ + template<typename _ForwardIter, typename _BinaryPredicate> + _ForwardIter + adjacent_find(_ForwardIter __first, _ForwardIter __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + if (__first == __last) + return __last; + _ForwardIter __next = __first; + while(++__next != __last) { + if (__binary_pred(*__first, *__next)) + return __first; + __first = __next; + } + return __last; + } + + /** + * @brief Count the number of copies of a value in a sequence. + * @param first An input iterator. + * @param last An input iterator. + * @param value The value to be counted. + * @return The number of iterators @c i in the range @p [first,last) + * for which @c *i == @p value + */ + template<typename _InputIter, typename _Tp> + typename iterator_traits<_InputIter>::difference_type + count(_InputIter __first, _InputIter __last, const _Tp& __value) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIter>::value_type >) + __glibcpp_function_requires(_EqualityComparableConcept<_Tp>) + typename iterator_traits<_InputIter>::difference_type __n = 0; + for ( ; __first != __last; ++__first) + if (*__first == __value) + ++__n; + return __n; + } + + /** + * @brief Count the elements of a sequence for which a predicate is true. + * @param first An input iterator. + * @param last An input iterator. + * @param pred A predicate. + * @return The number of iterators @c i in the range @p [first,last) + * for which @p pred(*i) is true. + */ + template<typename _InputIter, typename _Predicate> + typename iterator_traits<_InputIter>::difference_type + count_if(_InputIter __first, _InputIter __last, _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIter>::value_type>) + typename iterator_traits<_InputIter>::difference_type __n = 0; + for ( ; __first != __last; ++__first) + if (__pred(*__first)) + ++__n; + return __n; + } + + + /** + * @brief Search a sequence for a matching sub-sequence. + * @param first1 A forward iterator. + * @param last1 A forward iterator. + * @param first2 A forward iterator. + * @param last2 A forward iterator. + * @return The first iterator @c i in the range + * @p [first1,last1-(last2-first2)) such that @c *(i+N) == @p *(first2+N) + * for each @c N in the range @p [0,last2-first2), or @p last1 if no + * such iterator exists. + * + * Searches the range @p [first1,last1) for a sub-sequence that compares + * equal value-by-value with the sequence given by @p [first2,last2) and + * returns an iterator to the first element of the sub-sequence, or + * @p last1 if the sub-sequence is not found. + * + * Because the sub-sequence must lie completely within the range + * @p [first1,last1) it must start at a position less than + * @p last1-(last2-first2) where @p last2-first2 is the length of the + * sub-sequence. + * This means that the returned iterator @c i will be in the range + * @p [first1,last1-(last2-first2)) + */ + template<typename _ForwardIter1, typename _ForwardIter2> + _ForwardIter1 + search(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIter1>::value_type, + typename iterator_traits<_ForwardIter2>::value_type>) + + // Test for empty ranges + if (__first1 == __last1 || __first2 == __last2) + return __first1; + + // Test for a pattern of length 1. + _ForwardIter2 __tmp(__first2); + ++__tmp; + if (__tmp == __last2) + return find(__first1, __last1, *__first2); + + // General case. + + _ForwardIter2 __p1, __p; + + __p1 = __first2; ++__p1; + + _ForwardIter1 __current = __first1; + + while (__first1 != __last1) { + __first1 = find(__first1, __last1, *__first2); + if (__first1 == __last1) + return __last1; + + __p = __p1; + __current = __first1; + if (++__current == __last1) + return __last1; + + while (*__current == *__p) { + if (++__p == __last2) + return __first1; + if (++__current == __last1) + return __last1; + } + + ++__first1; + } + return __first1; + } + + /** + * @brief Search a sequence for a matching sub-sequence using a predicate. + * @param first1 A forward iterator. + * @param last1 A forward iterator. + * @param first2 A forward iterator. + * @param last2 A forward iterator. + * @param predicate A binary predicate. + * @return The first iterator @c i in the range + * @p [first1,last1-(last2-first2)) such that + * @p predicate(*(i+N),*(first2+N)) is true for each @c N in the range + * @p [0,last2-first2), or @p last1 if no such iterator exists. + * + * Searches the range @p [first1,last1) for a sub-sequence that compares + * equal value-by-value with the sequence given by @p [first2,last2), + * using @p predicate to determine equality, and returns an iterator + * to the first element of the sub-sequence, or @p last1 if no such + * iterator exists. + * + * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2) + */ + template<typename _ForwardIter1, typename _ForwardIter2, typename _BinaryPred> + _ForwardIter1 + search(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2, + _BinaryPred __predicate) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPred, + typename iterator_traits<_ForwardIter1>::value_type, + typename iterator_traits<_ForwardIter2>::value_type>) + + // Test for empty ranges + if (__first1 == __last1 || __first2 == __last2) + return __first1; + + // Test for a pattern of length 1. + _ForwardIter2 __tmp(__first2); + ++__tmp; + if (__tmp == __last2) { + while (__first1 != __last1 && !__predicate(*__first1, *__first2)) + ++__first1; + return __first1; + } + + // General case. + + _ForwardIter2 __p1, __p; + + __p1 = __first2; ++__p1; + + _ForwardIter1 __current = __first1; + + while (__first1 != __last1) { + while (__first1 != __last1) { + if (__predicate(*__first1, *__first2)) + break; + ++__first1; + } + while (__first1 != __last1 && !__predicate(*__first1, *__first2)) + ++__first1; + if (__first1 == __last1) + return __last1; + + __p = __p1; + __current = __first1; + if (++__current == __last1) return __last1; + + while (__predicate(*__current, *__p)) { + if (++__p == __last2) + return __first1; + if (++__current == __last1) + return __last1; + } + + ++__first1; + } + return __first1; + } + + /** + * @brief Search a sequence for a number of consecutive values. + * @param first A forward iterator. + * @param last A forward iterator. + * @param count The number of consecutive values. + * @param val The value to find. + * @return The first iterator @c i in the range @p [first,last-count) + * such that @c *(i+N) == @p val for each @c N in the range @p [0,count), + * or @p last if no such iterator exists. + * + * Searches the range @p [first,last) for @p count consecutive elements + * equal to @p val. + */ + template<typename _ForwardIter, typename _Integer, typename _Tp> + _ForwardIter + search_n(_ForwardIter __first, _ForwardIter __last, + _Integer __count, const _Tp& __val) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIter>::value_type>) + __glibcpp_function_requires(_EqualityComparableConcept<_Tp>) + + if (__count <= 0) + return __first; + else { + __first = find(__first, __last, __val); + while (__first != __last) { + _Integer __n = __count - 1; + _ForwardIter __i = __first; + ++__i; + while (__i != __last && __n != 0 && *__i == __val) { + ++__i; + --__n; + } + if (__n == 0) + return __first; + else + __first = find(__i, __last, __val); + } + return __last; + } + } + + /** + * @brief Search a sequence for a number of consecutive values using a + * predicate. + * @param first A forward iterator. + * @param last A forward iterator. + * @param count The number of consecutive values. + * @param val The value to find. + * @param binary_pred A binary predicate. + * @return The first iterator @c i in the range @p [first,last-count) + * such that @p binary_pred(*(i+N),val) is true for each @c N in the + * range @p [0,count), or @p last if no such iterator exists. + * + * Searches the range @p [first,last) for @p count consecutive elements + * for which the predicate returns true. + */ + template<typename _ForwardIter, typename _Integer, typename _Tp, + typename _BinaryPred> + _ForwardIter + search_n(_ForwardIter __first, _ForwardIter __last, + _Integer __count, const _Tp& __val, + _BinaryPred __binary_pred) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPred, + typename iterator_traits<_ForwardIter>::value_type, _Tp>) + + if (__count <= 0) + return __first; + else { + while (__first != __last) { + if (__binary_pred(*__first, __val)) + break; + ++__first; + } + while (__first != __last) { + _Integer __n = __count - 1; + _ForwardIter __i = __first; + ++__i; + while (__i != __last && __n != 0 && __binary_pred(*__i, __val)) { + ++__i; + --__n; + } + if (__n == 0) + return __first; + else { + while (__i != __last) { + if (__binary_pred(*__i, __val)) + break; + ++__i; + } + __first = __i; + } + } + return __last; + } + } + + /** + * @brief Swap the elements of two sequences. + * @param first1 A forward iterator. + * @param last1 A forward iterator. + * @param first2 A forward iterator. + * @return An iterator equal to @p first2+(last1-first1). + * + * Swaps each element in the range @p [first1,last1) with the + * corresponding element in the range @p [first2,(last1-first1)). + * The ranges must not overlap. + */ + template<typename _ForwardIter1, typename _ForwardIter2> + _ForwardIter2 + swap_ranges(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_ConvertibleConcept< + typename iterator_traits<_ForwardIter1>::value_type, + typename iterator_traits<_ForwardIter2>::value_type>) + __glibcpp_function_requires(_ConvertibleConcept< + typename iterator_traits<_ForwardIter2>::value_type, + typename iterator_traits<_ForwardIter1>::value_type>) + + for ( ; __first1 != __last1; ++__first1, ++__first2) + iter_swap(__first1, __first2); + return __first2; + } + + /** + * @brief Perform an operation on a sequence. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param unary_op A unary operator. + * @return An output iterator equal to @p result+(last-first). + * + * Applies the operator to each element in the input range and assigns + * the results to successive elements of the output sequence. + * Evaluates @p *(result+N)=unary_op(*(first+N)) for each @c N in the + * range @p [0,last-first). + * + * @p unary_op must not alter its argument. + */ + template<typename _InputIter, typename _OutputIter, typename _UnaryOperation> + _OutputIter + transform(_InputIter __first, _InputIter __last, + _OutputIter __result, _UnaryOperation __unary_op) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + // "the type returned by a _UnaryOperation" + __typeof__(__unary_op(*__first))>) + + for ( ; __first != __last; ++__first, ++__result) + *__result = __unary_op(*__first); + return __result; + } + + /** + * @brief Perform an operation on corresponding elements of two sequences. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @param result An output iterator. + * @param binary_op A binary operator. + * @return An output iterator equal to @p result+(last-first). + * + * Applies the operator to the corresponding elements in the two + * input ranges and assigns the results to successive elements of the + * output sequence. + * Evaluates @p *(result+N)=binary_op(*(first1+N),*(first2+N)) for each + * @c N in the range @p [0,last1-first1). + * + * @p binary_op must not alter either of its arguments. + */ + template<typename _InputIter1, typename _InputIter2, typename _OutputIter, + typename _BinaryOperation> + _OutputIter + transform(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _OutputIter __result, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + // "the type returned by a _BinaryOperation" + __typeof__(__binary_op(*__first1,*__first2))>) + + for ( ; __first1 != __last1; ++__first1, ++__first2, ++__result) + *__result = __binary_op(*__first1, *__first2); + return __result; + } + + /** + * @brief Replace each occurrence of one value in a sequence with another + * value. + * @param first A forward iterator. + * @param last A forward iterator. + * @param old_value The value to be replaced. + * @param new_value The replacement value. + * @return replace() returns no value. + * + * For each iterator @c i in the range @p [first,last) if @c *i == + * @p old_value then the assignment @c *i = @p new_value is performed. + */ + template<typename _ForwardIter, typename _Tp> + void + replace(_ForwardIter __first, _ForwardIter __last, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIter>::value_type, _Tp>) + __glibcpp_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIter>::value_type>) + + for ( ; __first != __last; ++__first) + if (*__first == __old_value) + *__first = __new_value; + } + + /** + * @brief Replace each value in a sequence for which a predicate returns + * true with another value. + * @param first A forward iterator. + * @param last A forward iterator. + * @param pred A predicate. + * @param new_value The replacement value. + * @return replace_if() returns no value. + * + * For each iterator @c i in the range @p [first,last) if @p pred(*i) + * is true then the assignment @c *i = @p new_value is performed. + */ + template<typename _ForwardIter, typename _Predicate, typename _Tp> + void + replace_if(_ForwardIter __first, _ForwardIter __last, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIter>::value_type>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIter>::value_type>) + + for ( ; __first != __last; ++__first) + if (__pred(*__first)) + *__first = __new_value; + } + + /** + * @brief Copy a sequence, replacing each element of one value with another + * value. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param old_value The value to be replaced. + * @param new_value The replacement value. + * @return The end of the output sequence, @p result+(last-first). + * + * Copies each element in the input range @p [first,last) to the + * output range @p [result,result+(last-first)) replacing elements + * equal to @p old_value with @p new_value. + */ + template<typename _InputIter, typename _OutputIter, typename _Tp> + _OutputIter + replace_copy(_InputIter __first, _InputIter __last, + _OutputIter __result, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter>::value_type, _Tp>) + + for ( ; __first != __last; ++__first, ++__result) + *__result = *__first == __old_value ? __new_value : *__first; + return __result; + } + + /** + * @brief Copy a sequence, replacing each value for which a predicate + * returns true with another value. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param pred A predicate. + * @param new_value The replacement value. + * @return The end of the output sequence, @p result+(last-first). + * + * Copies each element in the range @p [first,last) to the range + * @p [result,result+(last-first)) replacing elements for which + * @p pred returns true with @p new_value. + */ + template<typename _InputIter, typename _OutputIter, typename _Predicate, + typename _Tp> + _OutputIter + replace_copy_if(_InputIter __first, _InputIter __last, + _OutputIter __result, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIter>::value_type>) + + for ( ; __first != __last; ++__first, ++__result) + *__result = __pred(*__first) ? __new_value : *__first; + return __result; + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @param first A forward iterator. + * @param last A forward iterator. + * @param gen A function object taking no arguments. + * @return generate() returns no value. + * + * Performs the assignment @c *i = @p gen() for each @c i in the range + * @p [first,last). + */ + template<typename _ForwardIter, typename _Generator> + void + generate(_ForwardIter __first, _ForwardIter __last, _Generator __gen) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_GeneratorConcept<_Generator, + typename iterator_traits<_ForwardIter>::value_type>) + + for ( ; __first != __last; ++__first) + *__first = __gen(); + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @param first A forward iterator. + * @param n The length of the sequence. + * @param gen A function object taking no arguments. + * @return The end of the sequence, @p first+n + * + * Performs the assignment @c *i = @p gen() for each @c i in the range + * @p [first,first+n). + */ + template<typename _OutputIter, typename _Size, typename _Generator> + _OutputIter + generate_n(_OutputIter __first, _Size __n, _Generator __gen) + { + // concept requirements + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + // "the type returned by a _Generator" + __typeof__(gen())>) + + for ( ; __n > 0; --__n, ++__first) + *__first = __gen(); + return __first; + } + + /** + * @brief Copy a sequence, removing elements of a given value. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [first,last) not equal to @p value + * to the range beginning at @p result. + * remove_copy() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template<typename _InputIter, typename _OutputIter, typename _Tp> + _OutputIter + remove_copy(_InputIter __first, _InputIter __last, + _OutputIter __result, const _Tp& __value) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter>::value_type, _Tp>) + + for ( ; __first != __last; ++__first) + if (!(*__first == __value)) { + *__result = *__first; + ++__result; + } + return __result; + } + + /** + * @brief Copy a sequence, removing elements for which a predicate is true. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [first,last) for which + * @p pred returns true to the range beginning at @p result. + * + * remove_copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template<typename _InputIter, typename _OutputIter, typename _Predicate> + _OutputIter + remove_copy_if(_InputIter __first, _InputIter __last, + _OutputIter __result, _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIter>::value_type>) + + for ( ; __first != __last; ++__first) + if (!__pred(*__first)) { + *__result = *__first; + ++__result; + } + return __result; + } + + /** + * @brief Remove elements from a sequence. + * @param first An input iterator. + * @param last An input iterator. + * @param value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * All elements equal to @p value are removed from the range + * @p [first,last). + * + * remove() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p last + * are still present, but their value is unspecified. + */ + template<typename _ForwardIter, typename _Tp> + _ForwardIter + remove(_ForwardIter __first, _ForwardIter __last, + const _Tp& __value) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIter>::value_type>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIter>::value_type, _Tp>) + + __first = find(__first, __last, __value); + _ForwardIter __i = __first; + return __first == __last ? __first + : remove_copy(++__i, __last, __first, __value); + } + + /** + * @brief Remove elements from a sequence using a predicate. + * @param first A forward iterator. + * @param last A forward iterator. + * @param pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * All elements for which @p pred returns true are removed from the range + * @p [first,last). + * + * remove_if() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p last + * are still present, but their value is unspecified. + */ + template<typename _ForwardIter, typename _Predicate> + _ForwardIter + remove_if(_ForwardIter __first, _ForwardIter __last, + _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIter>::value_type>) + + __first = find_if(__first, __last, __pred); + _ForwardIter __i = __first; + return __first == __last ? __first + : remove_copy_if(++__i, __last, __first, __pred); + } + + /** + * @if maint + * This is an uglified unique_copy(_InputIter, _InputIter, _OutputIter) + * overloaded for output iterators. + * @endif + */ + template<typename _InputIter, typename _OutputIter> + _OutputIter + __unique_copy(_InputIter __first, _InputIter __last, + _OutputIter __result, + output_iterator_tag) + { + // concept requirements -- taken care of in dispatching function + typename iterator_traits<_InputIter>::value_type __value = *__first; + *__result = __value; + while (++__first != __last) + if (!(__value == *__first)) { + __value = *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * @if maint + * This is an uglified unique_copy(_InputIter, _InputIter, _OutputIter) + * overloaded for forward iterators. + * @endif + */ + template<typename _InputIter, typename _ForwardIter> + _ForwardIter + __unique_copy(_InputIter __first, _InputIter __last, + _ForwardIter __result, + forward_iterator_tag) + { + // concept requirements -- taken care of in dispatching function + *__result = *__first; + while (++__first != __last) + if (!(*__result == *__first)) + *++__result = *__first; + return ++__result; + } + + /** + * @brief Copy a sequence, removing consecutive duplicate values. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * 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 + unique_copy(_InputIter __first, _InputIter __last, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIter>::value_type>) + + typedef typename iterator_traits<_OutputIter>::iterator_category _IterType; + + if (__first == __last) return __result; + return __unique_copy(__first, __last, __result, _IterType()); + } + + /** + * @if maint + * This is an uglified + * unique_copy(_InputIter, _InputIter, _OutputIter, _BinaryPredicate) + * overloaded for output iterators. + * @endif + */ + template<typename _InputIter, typename _OutputIter, typename _BinaryPredicate> + _OutputIter + __unique_copy(_InputIter __first, _InputIter __last, + _OutputIter __result, + _BinaryPredicate __binary_pred, + output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIter>::value_type, + typename iterator_traits<_InputIter>::value_type>) + + typename iterator_traits<_InputIter>::value_type __value = *__first; + *__result = __value; + while (++__first != __last) + if (!__binary_pred(__value, *__first)) { + __value = *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * @if maint + * This is an uglified + * unique_copy(_InputIter, _InputIter, _OutputIter, _BinaryPredicate) + * overloaded for forward iterators. + * @endif + */ + template<typename _InputIter, typename _ForwardIter, typename _BinaryPredicate> + _ForwardIter + __unique_copy(_InputIter __first, _InputIter __last, + _ForwardIter __result, + _BinaryPredicate __binary_pred, + forward_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIter>::value_type, + typename iterator_traits<_InputIter>::value_type>) + + *__result = *__first; + while (++__first != __last) + if (!__binary_pred(*__result, *__first)) *++__result = *__first; + return ++__result; + } + + /** + * @brief Copy a sequence, removing consecutive values using a predicate. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @param binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * 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 for which @p binary_pred returns + * true. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template<typename _InputIter, typename _OutputIter, typename _BinaryPredicate> + inline _OutputIter + unique_copy(_InputIter __first, _InputIter __last, + _OutputIter __result, + _BinaryPredicate __binary_pred) + { + // concept requirements -- predicates checked later + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + + typedef typename iterator_traits<_OutputIter>::iterator_category _IterType; + + if (__first == __last) return __result; + return __unique_copy(__first, __last, +__result, __binary_pred, _IterType()); + } + + /** + * @brief Remove consecutive duplicate values from a sequence. + * @param first A forward iterator. + * @param last A forward iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values that compare equal. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p last + * are still present, but their value is unspecified. + */ + template<typename _ForwardIter> + _ForwardIter + unique(_ForwardIter __first, _ForwardIter __last) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIter>::value_type>) + + __first = adjacent_find(__first, __last); + return unique_copy(__first, __last, __first); + } + + /** + * @brief Remove consecutive values from a sequence using a predicate. + * @param first A forward iterator. + * @param last A forward iterator. + * @param binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values for which @p binary_pred returns true. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p last + * are still present, but their value is unspecified. + */ + template<typename _ForwardIter, typename _BinaryPredicate> + _ForwardIter + unique(_ForwardIter __first, _ForwardIter __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + + __first = adjacent_find(__first, __last, __binary_pred); + return unique_copy(__first, __last, __first, __binary_pred); + } + + /** + * @if maint + * This is an uglified reverse(_BidirectionalIter, _BidirectionalIter) + * overloaded for bidirectional iterators. + * @endif + */ + template<typename _BidirectionalIter> + void + __reverse(_BidirectionalIter __first, _BidirectionalIter __last, + bidirectional_iterator_tag) + { + while (true) + if (__first == __last || __first == --__last) + return; + else + iter_swap(__first++, __last); + } + + /** + * @if maint + * This is an uglified reverse(_BidirectionalIter, _BidirectionalIter) + * overloaded for bidirectional iterators. + * @endif + */ + template<typename _RandomAccessIter> + void + __reverse(_RandomAccessIter __first, _RandomAccessIter __last, + random_access_iterator_tag) + { + while (__first < __last) + iter_swap(__first++, --__last); + } + + /** + * @brief Reverse a sequence. + * @param first A bidirectional iterator. + * @param last A bidirectional iterator. + * @return reverse() returns no value. + * + * Reverses the order of the elements in the range @p [first,last), + * so that the first element becomes the last etc. + * For every @c i such that @p 0<=i<=(last-first)/2), @p reverse() + * swaps @p *(first+i) and @p *(last-(i+1)) + */ + template<typename _BidirectionalIter> + inline void + reverse(_BidirectionalIter __first, _BidirectionalIter __last) + { + // concept requirements + __glibcpp_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIter>) + __reverse(__first, __last, __iterator_category(__first)); + } + + /** + * @brief Copy a sequence, reversing its elements. + * @param first A bidirectional iterator. + * @param last A bidirectional iterator. + * @param result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements in the range @p [first,last) to the range + * @p [result,result+(last-first)) such that the order of the + * elements is reversed. + * For every @c i such that @p 0<=i<=(last-first), @p reverse_copy() + * performs the assignment @p *(result+(last-first)-i) = *(first+i). + * The ranges @p [first,last) and @p [result,result+(last-first)) + * must not overlap. + */ + template<typename _BidirectionalIter, typename _OutputIter> + _OutputIter + reverse_copy(_BidirectionalIter __first, _BidirectionalIter __last, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_BidirectionalIter>::value_type>) + + while (__first != __last) { + --__last; + *__result = *__last; + ++__result; + } + return __result; + } + + + /** + * @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) + { + while (__n != 0) { + _EuclideanRingElement __t = __m % __n; + __m = __n; + __n = __t; + } + return __m; + } + + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ + template<typename _ForwardIter> + void + __rotate(_ForwardIter __first, + _ForwardIter __middle, + _ForwardIter __last, + forward_iterator_tag) + { + if ((__first == __middle) || (__last == __middle)) + return; + + _ForwardIter __first2 = __middle; + do { + swap(*__first++, *__first2++); + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + __first2 = __middle; + + while (__first2 != __last) { + swap(*__first++, *__first2++); + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + } + + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ + template<typename _BidirectionalIter> + void + __rotate(_BidirectionalIter __first, + _BidirectionalIter __middle, + _BidirectionalIter __last, + bidirectional_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIter>) + + if ((__first == __middle) || (__last == __middle)) + return; + + __reverse(__first, __middle, bidirectional_iterator_tag()); + __reverse(__middle, __last, bidirectional_iterator_tag()); + + while (__first != __middle && __middle != __last) + swap (*__first++, *--__last); + + if (__first == __middle) { + __reverse(__middle, __last, bidirectional_iterator_tag()); + } + else { + __reverse(__first, __middle, bidirectional_iterator_tag()); + } + } + + /** + * @if maint + * This is a helper function for the rotate algorithm. + * @endif + */ + template<typename _RandomAccessIter> + void + __rotate(_RandomAccessIter __first, + _RandomAccessIter __middle, + _RandomAccessIter __last, + random_access_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + + if ((__first == __middle) || (__last == __middle)) + return; + + typedef typename iterator_traits<_RandomAccessIter>::difference_type _Distance; + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + _Distance __n = __last - __first; + _Distance __k = __middle - __first; + _Distance __l = __n - __k; + + if (__k == __l) { + swap_ranges(__first, __middle, __middle); + return; + } + + _Distance __d = __gcd(__n, __k); + + for (_Distance __i = 0; __i < __d; __i++) { + _ValueType __tmp = *__first; + _RandomAccessIter __p = __first; + + if (__k < __l) { + for (_Distance __j = 0; __j < __l/__d; __j++) { + if (__p > __first + __l) { + *__p = *(__p - __l); + __p -= __l; + } + + *__p = *(__p + __k); + __p += __k; + } + } + + else { + for (_Distance __j = 0; __j < __k/__d - 1; __j ++) { + if (__p < __last - __k) { + *__p = *(__p + __k); + __p += __k; + } + + *__p = * (__p - __l); + __p -= __l; + } + } + + *__p = __tmp; + ++__first; + } + } + + /** + * @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) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + + typedef typename iterator_traits<_ForwardIter>::iterator_category _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, + _ForwardIter __last, _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_ForwardIter>::value_type>) + + return copy(__first, __middle, copy(__middle, __last, __result)); + } + + + /** + * @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) + { + #ifdef _GLIBCPP_HAVE_DRAND48 + return lrand48() % __n; + #else + return rand() % __n; + #endif + } + + + /** + * @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) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + + if (__first == __last) return; + for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) + 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, + _RandomNumberGenerator& __rand) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + + if (__first == __last) return; + for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) + iter_swap(__i, __first + __rand((__i - __first) + 1)); + } + + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _ForwardIter, typename _Predicate> + _ForwardIter + __partition(_ForwardIter __first, _ForwardIter __last, + _Predicate __pred, + forward_iterator_tag) + { + if (__first == __last) return __first; + + while (__pred(*__first)) + if (++__first == __last) return __first; + + _ForwardIter __next = __first; + + while (++__next != __last) + if (__pred(*__next)) { + swap(*__first, *__next); + ++__first; + } + + return __first; + } + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _BidirectionalIter, typename _Predicate> + _BidirectionalIter + __partition(_BidirectionalIter __first, _BidirectionalIter __last, + _Predicate __pred, + bidirectional_iterator_tag) + { + while (true) { + while (true) + if (__first == __last) + return __first; + else if (__pred(*__first)) + ++__first; + else + break; + --__last; + while (true) + if (__first == __last) + return __first; + else if (!__pred(*__last)) + --__last; + else + break; + iter_swap(__first, __last); + ++__first; + } + } + + /** + * @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, + _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIter>::value_type>) + + return __partition(__first, __last, __pred, __iterator_category(__first)); + } + + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _ForwardIter, typename _Predicate, typename _Distance> + _ForwardIter + __inplace_stable_partition(_ForwardIter __first, _ForwardIter __last, + _Predicate __pred, _Distance __len) + { + if (__len == 1) + return __pred(*__first) ? __last : __first; + _ForwardIter __middle = __first; + advance(__middle, __len / 2); + _ForwardIter __begin = __inplace_stable_partition(__first, __middle, + __pred, + __len / 2); + _ForwardIter __end = __inplace_stable_partition(__middle, __last, + __pred, + __len - __len / 2); + rotate(__begin, __middle, __end); + advance(__begin, distance(__middle, __end)); + return __begin; + } + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _ForwardIter, typename _Pointer, typename _Predicate, + typename _Distance> + _ForwardIter + __stable_partition_adaptive(_ForwardIter __first, _ForwardIter __last, + _Predicate __pred, _Distance __len, + _Pointer __buffer, + _Distance __buffer_size) + { + if (__len <= __buffer_size) { + _ForwardIter __result1 = __first; + _Pointer __result2 = __buffer; + for ( ; __first != __last ; ++__first) + if (__pred(*__first)) { + *__result1 = *__first; + ++__result1; + } + else { + *__result2 = *__first; + ++__result2; + } + copy(__buffer, __result2, __result1); + return __result1; + } + else { + _ForwardIter __middle = __first; + advance(__middle, __len / 2); + _ForwardIter __begin = __stable_partition_adaptive(__first, __middle, + __pred, + __len / 2, + __buffer, __buffer_size); + _ForwardIter __end = __stable_partition_adaptive( __middle, __last, + __pred, + __len - __len / 2, + __buffer, __buffer_size); + rotate(__begin, __middle, __end); + advance(__begin, distance(__middle, __end)); + return __begin; + } + } + + /** + * @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, + _Predicate __pred) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIter>::value_type>) + + if (__first == __last) + return __first; + else + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + _Temporary_buffer<_ForwardIter, _ValueType> __buf(__first, __last); + if (__buf.size() > 0) + return __stable_partition_adaptive(__first, __last, __pred, + _DistanceType(__buf.requested_size()), + __buf.begin(), __buf.size()); + else + return __inplace_stable_partition(__first, __last, __pred, + _DistanceType(__buf.requested_size())); + } + } + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _RandomAccessIter, typename _Tp> + _RandomAccessIter + __unguarded_partition(_RandomAccessIter __first, _RandomAccessIter __last, + _Tp __pivot) + { + while (true) { + while (*__first < __pivot) + ++__first; + --__last; + while (__pivot < *__last) + --__last; + if (!(__first < __last)) + return __first; + iter_swap(__first, __last); + ++__first; + } + } + + /** + * @if maint + * This is a helper function... + * @endif + */ + template<typename _RandomAccessIter, typename _Tp, typename _Compare> + _RandomAccessIter + __unguarded_partition(_RandomAccessIter __first, _RandomAccessIter __last, + _Tp __pivot, _Compare __comp) + { + while (true) { + while (__comp(*__first, __pivot)) + ++__first; + --__last; + while (__comp(__pivot, *__last)) + --__last; + if (!(__first < __last)) + return __first; + iter_swap(__first, __last); + ++__first; + } + } + + + /** + * @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) + { + _RandomAccessIter __next = __last; + --__next; + while (__val < *__next) { + *__last = *__next; + __last = __next; + --__next; + } + *__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) + { + _RandomAccessIter __next = __last; + --__next; + while (__comp(__val, *__next)) { + *__last = *__next; + __last = __next; + --__next; + } + *__last = __val; + } + + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ + template<typename _RandomAccessIter> + void + __insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) + { + if (__first == __last) return; + + for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) + { + typename iterator_traits<_RandomAccessIter>::value_type __val = *__i; + if (__val < *__first) { + copy_backward(__first, __i, __i + 1); + *__first = __val; + } + else + __unguarded_linear_insert(__i, __val); + } + } + + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ + template<typename _RandomAccessIter, typename _Compare> + void + __insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, + _Compare __comp) + { + if (__first == __last) return; + + for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) + { + typename iterator_traits<_RandomAccessIter>::value_type __val = *__i; + if (__comp(__val, *__first)) { + copy_backward(__first, __i, __i + 1); + *__first = __val; + } + else + __unguarded_linear_insert(__i, __val, __comp); + } + } + + /** + * @if maint + * This is a helper function for the sort routine. + * @endif + */ + template<typename _RandomAccessIter> + inline void + __unguarded_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + for (_RandomAccessIter __i = __first; __i != __last; ++__i) + __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, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + for (_RandomAccessIter __i = __first; __i != __last; ++__i) + __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 > _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 > _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) + { + _Size __k; + for (__k = 0; __n != 1; __n >>= 1) ++__k; + 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, + _Size __depth_limit) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + while (__last - __first > _M_threshold) { + if (__depth_limit == 0) { + partial_sort(__first, __last, __last); + return; + } + --__depth_limit; + _RandomAccessIter __cut = + __unguarded_partition(__first, __last, + _ValueType(__median(*__first, + *(__first + (__last - __first)/2), + *(__last - 1)))); + __introsort_loop(__cut, __last, __depth_limit); + __last = __cut; + } + } + + /** + * @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, + _Size __depth_limit, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + while (__last - __first > _M_threshold) { + if (__depth_limit == 0) { + partial_sort(__first, __last, __last, __comp); + return; + } + --__depth_limit; + _RandomAccessIter __cut = + __unguarded_partition(__first, __last, + _ValueType(__median(*__first, + *(__first + (__last - __first)/2), + *(__last - 1), __comp)), + __comp); + __introsort_loop(__cut, __last, __depth_limit, __comp); + __last = __cut; + } + } + + /** + * @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) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + if (__first != __last) { + __introsort_loop(__first, __last, __lg(__last - __first) * 2); + __final_insertion_sort(__first, __last); + } + } + + /** + * @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) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _ValueType, _ValueType>) + + if (__first != __last) { + __introsort_loop(__first, __last, __lg(__last - __first) * 2, __comp); + __final_insertion_sort(__first, __last, __comp); + } + } + + + /** + * @if maint + * This is a helper function for the stable sorting routines. + * @endif + */ + template<typename _RandomAccessIter> + void + __inplace_stable_sort(_RandomAccessIter __first, _RandomAccessIter __last) + { + if (__last - __first < 15) { + __insertion_sort(__first, __last); + return; + } + _RandomAccessIter __middle = __first + (__last - __first) / 2; + __inplace_stable_sort(__first, __middle); + __inplace_stable_sort(__middle, __last); + __merge_without_buffer(__first, __middle, __last, + __middle - __first, + __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, + _Compare __comp) + { + if (__last - __first < 15) { + __insertion_sort(__first, __last, __comp); + return; + } + _RandomAccessIter __middle = __first + (__last - __first) / 2; + __inplace_stable_sort(__first, __middle, __comp); + __inplace_stable_sort(__middle, __last, __comp); + __merge_without_buffer(__first, __middle, __last, + __middle - __first, + __last - __middle, + __comp); + } + + template<typename _RandomAccessIter1, typename _RandomAccessIter2, + typename _Distance> + void + __merge_sort_loop(_RandomAccessIter1 __first, _RandomAccessIter1 __last, + _RandomAccessIter2 __result, _Distance __step_size) + { + _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) { + __result = merge(__first, __first + __step_size, + __first + __step_size, __first + __two_step, + __result); + __first += __two_step; + } + + __step_size = min(_Distance(__last - __first), __step_size); + merge(__first, __first + __step_size, __first + __step_size, __last, + __result); + } + + template<typename _RandomAccessIter1, typename _RandomAccessIter2, + typename _Distance, typename _Compare> + void + __merge_sort_loop(_RandomAccessIter1 __first, _RandomAccessIter1 __last, + _RandomAccessIter2 __result, _Distance __step_size, + _Compare __comp) + { + _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) { + __result = merge(__first, __first + __step_size, + __first + __step_size, __first + __two_step, + __result, + __comp); + __first += __two_step; + } + __step_size = min(_Distance(__last - __first), __step_size); + + merge(__first, __first + __step_size, + __first + __step_size, __last, + __result, + __comp); + } + + enum { _M_chunk_size = 7 }; + + template<typename _RandomAccessIter, typename _Distance> + void + __chunk_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, + _Distance __chunk_size) + { + while (__last - __first >= __chunk_size) { + __insertion_sort(__first, __first + __chunk_size); + __first += __chunk_size; + } + __insertion_sort(__first, __last); + } + + template<typename _RandomAccessIter, typename _Distance, typename _Compare> + void + __chunk_insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last, + _Distance __chunk_size, _Compare __comp) + { + while (__last - __first >= __chunk_size) { + __insertion_sort(__first, __first + __chunk_size, __comp); + __first += __chunk_size; + } + __insertion_sort(__first, __last, __comp); + } + + template<typename _RandomAccessIter, typename _Pointer> + void + __merge_sort_with_buffer(_RandomAccessIter __first, _RandomAccessIter __last, + _Pointer __buffer) + { + typedef typename iterator_traits<_RandomAccessIter>::difference_type _Distance; + + _Distance __len = __last - __first; + _Pointer __buffer_last = __buffer + __len; + + _Distance __step_size = _M_chunk_size; + __chunk_insertion_sort(__first, __last, __step_size); + + while (__step_size < __len) { + __merge_sort_loop(__first, __last, __buffer, __step_size); + __step_size *= 2; + __merge_sort_loop(__buffer, __buffer_last, __first, __step_size); + __step_size *= 2; + } + } + + template<typename _RandomAccessIter, typename _Pointer, typename _Compare> + void + __merge_sort_with_buffer(_RandomAccessIter __first, _RandomAccessIter __last, + _Pointer __buffer, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIter>::difference_type _Distance; + + _Distance __len = __last - __first; + _Pointer __buffer_last = __buffer + __len; + + _Distance __step_size = _M_chunk_size; + __chunk_insertion_sort(__first, __last, __step_size, __comp); + + while (__step_size < __len) { + __merge_sort_loop(__first, __last, __buffer, __step_size, __comp); + __step_size *= 2; + __merge_sort_loop(__buffer, __buffer_last, __first, __step_size, __comp); + __step_size *= 2; + } + } + + template<typename _RandomAccessIter, typename _Pointer, typename _Distance> + void + __stable_sort_adaptive(_RandomAccessIter __first, _RandomAccessIter __last, + _Pointer __buffer, _Distance __buffer_size) + { + _Distance __len = (__last - __first + 1) / 2; + _RandomAccessIter __middle = __first + __len; + if (__len > __buffer_size) { + __stable_sort_adaptive(__first, __middle, __buffer, __buffer_size); + __stable_sort_adaptive(__middle, __last, __buffer, __buffer_size); + } + else { + __merge_sort_with_buffer(__first, __middle, __buffer); + __merge_sort_with_buffer(__middle, __last, __buffer); + } + __merge_adaptive(__first, __middle, __last, _Distance(__middle - __first), + _Distance(__last - __middle), __buffer, __buffer_size); + } + + template<typename _RandomAccessIter, typename _Pointer, typename _Distance, + typename _Compare> + void + __stable_sort_adaptive(_RandomAccessIter __first, _RandomAccessIter __last, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + _Distance __len = (__last - __first + 1) / 2; + _RandomAccessIter __middle = __first + __len; + if (__len > __buffer_size) { + __stable_sort_adaptive(__first, __middle, __buffer, __buffer_size, + __comp); + __stable_sort_adaptive(__middle, __last, __buffer, __buffer_size, + __comp); + } + else { + __merge_sort_with_buffer(__first, __middle, __buffer, __comp); + __merge_sort_with_buffer(__middle, __last, __buffer, __comp); + } + __merge_adaptive(__first, __middle, __last, _Distance(__middle - __first), + _Distance(__last - __middle), __buffer, __buffer_size, + __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) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + typedef typename iterator_traits<_RandomAccessIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + _Temporary_buffer<_RandomAccessIter, _ValueType> buf(__first, __last); + if (buf.begin() == 0) + __inplace_stable_sort(__first, __last); + else + __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) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + typedef typename iterator_traits<_RandomAccessIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + _ValueType, _ValueType>) + + _Temporary_buffer<_RandomAccessIter, _ValueType> buf(__first, __last); + if (buf.begin() == 0) + __inplace_stable_sort(__first, __last, __comp); + else + __stable_sort_adaptive(__first, __last, buf.begin(), _DistanceType(buf.size()), + __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, + _RandomAccessIter __middle, + _RandomAccessIter __last) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + make_heap(__first, __middle); + for (_RandomAccessIter __i = __middle; __i < __last; ++__i) + if (*__i < *__first) + __pop_heap(__first, __middle, __i, _ValueType(*__i)); + 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, + _RandomAccessIter __middle, + _RandomAccessIter __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + _ValueType, _ValueType>) + + make_heap(__first, __middle, __comp); + for (_RandomAccessIter __i = __middle; __i < __last; ++__i) + if (__comp(*__i, *__first)) + __pop_heap(__first, __middle, __i, _ValueType(*__i), __comp); + 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, + _RandomAccessIter __result_first, + _RandomAccessIter __result_last) + { + typedef typename iterator_traits<_InputIter>::value_type _InputValueType; + typedef typename iterator_traits<_RandomAccessIter>::value_type _OutputValueType; + typedef typename iterator_traits<_RandomAccessIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_ConvertibleConcept<_InputValueType, _OutputValueType>) + __glibcpp_function_requires(_LessThanComparableConcept<_OutputValueType>) + __glibcpp_function_requires(_LessThanComparableConcept<_InputValueType>) + + if (__result_first == __result_last) return __result_last; + _RandomAccessIter __result_real_last = __result_first; + while(__first != __last && __result_real_last != __result_last) { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + make_heap(__result_first, __result_real_last); + while (__first != __last) { + if (*__first < *__result_first) + __adjust_heap(__result_first, _DistanceType(0), + _DistanceType(__result_real_last - __result_first), + _InputValueType(*__first)); + ++__first; + } + sort_heap(__result_first, __result_real_last); + 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, + _RandomAccessIter __result_first, + _RandomAccessIter __result_last, + _Compare __comp) + { + typedef typename iterator_traits<_InputIter>::value_type _InputValueType; + typedef typename iterator_traits<_RandomAccessIter>::value_type _OutputValueType; + typedef typename iterator_traits<_RandomAccessIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept<_RandomAccessIter>) + __glibcpp_function_requires(_ConvertibleConcept<_InputValueType, _OutputValueType>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + _OutputValueType, _OutputValueType>) + + if (__result_first == __result_last) return __result_last; + _RandomAccessIter __result_real_last = __result_first; + while(__first != __last && __result_real_last != __result_last) { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + make_heap(__result_first, __result_real_last, __comp); + while (__first != __last) { + if (__comp(*__first, *__result_first)) + __adjust_heap(__result_first, _DistanceType(0), + _DistanceType(__result_real_last - __result_first), + _InputValueType(*__first), + __comp); + ++__first; + } + sort_heap(__result_first, __result_real_last, __comp); + 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, + _RandomAccessIter __nth, + _RandomAccessIter __last) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept<_RandomAccessIter>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + while (__last - __first > 3) { + _RandomAccessIter __cut = + __unguarded_partition(__first, __last, + _ValueType(__median(*__first, + *(__first + (__last - __first)/2), + *(__last - 1)))); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + __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, + _RandomAccessIter __nth, + _RandomAccessIter __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept<_RandomAccessIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + _ValueType, _ValueType>) + + while (__last - __first > 3) { + _RandomAccessIter __cut = + __unguarded_partition(__first, __last, + _ValueType(__median(*__first, + *(__first + (__last - __first)/2), + *(__last - 1), + __comp)), + __comp); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + __insertion_sort(__first, __last, __comp); + } + + + /** + * @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) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + // Note that these are slightly stricter than those of the 4-argument + // version, defined next. The difference is in the strictness of the + // comparison operations... so for looser checking, define your own + // comparison function, as was intended. + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_SameTypeConcept<_Tp, _ValueType>) + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (*__middle < __val) { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + 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, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _ValueType, _Tp>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (__comp(*__middle, __val)) { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + 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) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + // See comments on lower_bound. + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_SameTypeConcept<_Tp, _ValueType>) + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (__val < *__middle) + __len = __half; + else { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + 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, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _Tp, _ValueType>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (__comp(__val, *__middle)) + __len = __half; + else { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + 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) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + // See comments on lower_bound. + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_SameTypeConcept<_Tp, _ValueType>) + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle, __left, __right; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (*__middle < __val) { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (__val < *__middle) + __len = __half; + else { + __left = lower_bound(__first, __middle, __val); + advance(__first, __len); + __right = upper_bound(++__middle, __first, __val); + return pair<_ForwardIter, _ForwardIter>(__left, __right); + } + } + 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, + _Compare __comp) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIter>::difference_type _DistanceType; + + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _ValueType, _Tp>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _Tp, _ValueType>) + + _DistanceType __len = distance(__first, __last); + _DistanceType __half; + _ForwardIter __middle, __left, __right; + + while (__len > 0) { + __half = __len >> 1; + __middle = __first; + advance(__middle, __half); + if (__comp(*__middle, __val)) { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (__comp(__val, *__middle)) + __len = __half; + else { + __left = lower_bound(__first, __middle, __val, __comp); + advance(__first, __len); + __right = upper_bound(++__middle, __first, __val, __comp); + return pair<_ForwardIter, _ForwardIter>(__left, __right); + } + } + 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, + const _Tp& __val) + { + // concept requirements + // See comments on lower_bound. + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_SameTypeConcept<_Tp, + typename iterator_traits<_ForwardIter>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + + _ForwardIter __i = lower_bound(__first, __last, __val); + 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, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIter>::value_type, _Tp>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, _Tp, + typename iterator_traits<_ForwardIter>::value_type>) + + _ForwardIter __i = lower_bound(__first, __last, __val, __comp); + return __i != __last && !__comp(__val, *__i); + } + + /** + * @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, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) { + if (*__first2 < *__first1) { + *__result = *__first2; + ++__first2; + } + else { + *__result = *__first1; + ++__first1; + } + ++__result; + } + 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 + merge(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) { + if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__first2; + } + else { + *__result = *__first1; + ++__first1; + } + ++__result; + } + return copy(__first2, __last2, copy(__first1, __last1, __result)); + } + + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ + template<typename _BidirectionalIter, typename _Distance> + void + __merge_without_buffer(_BidirectionalIter __first, + _BidirectionalIter __middle, + _BidirectionalIter __last, + _Distance __len1, _Distance __len2) + { + if (__len1 == 0 || __len2 == 0) + return; + if (__len1 + __len2 == 2) { + if (*__middle < *__first) + iter_swap(__first, __middle); + return; + } + _BidirectionalIter __first_cut = __first; + _BidirectionalIter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) { + __len11 = __len1 / 2; + advance(__first_cut, __len11); + __second_cut = lower_bound(__middle, __last, *__first_cut); + __len22 = distance(__middle, __second_cut); + } + else { + __len22 = __len2 / 2; + advance(__second_cut, __len22); + __first_cut = upper_bound(__first, __middle, *__second_cut); + __len11 = distance(__first, __first_cut); + } + rotate(__first_cut, __middle, __second_cut); + _BidirectionalIter __new_middle = __first_cut; + advance(__new_middle, distance(__middle, __second_cut)); + __merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22); + __merge_without_buffer(__new_middle, __second_cut, __last, + __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, + _BidirectionalIter __middle, + _BidirectionalIter __last, + _Distance __len1, _Distance __len2, + _Compare __comp) + { + if (__len1 == 0 || __len2 == 0) + return; + if (__len1 + __len2 == 2) { + if (__comp(*__middle, *__first)) + iter_swap(__first, __middle); + return; + } + _BidirectionalIter __first_cut = __first; + _BidirectionalIter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) { + __len11 = __len1 / 2; + advance(__first_cut, __len11); + __second_cut = lower_bound(__middle, __last, *__first_cut, __comp); + __len22 = distance(__middle, __second_cut); + } + else { + __len22 = __len2 / 2; + advance(__second_cut, __len22); + __first_cut = upper_bound(__first, __middle, *__second_cut, __comp); + __len11 = distance(__first, __first_cut); + } + rotate(__first_cut, __middle, __second_cut); + _BidirectionalIter __new_middle = __first_cut; + advance(__new_middle, distance(__middle, __second_cut)); + __merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22, __comp); + __merge_without_buffer(__new_middle, __second_cut, __last, + __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 + __rotate_adaptive(_BidirectionalIter1 __first, + _BidirectionalIter1 __middle, + _BidirectionalIter1 __last, + _Distance __len1, _Distance __len2, + _BidirectionalIter2 __buffer, + _Distance __buffer_size) + { + _BidirectionalIter2 __buffer_end; + if (__len1 > __len2 && __len2 <= __buffer_size) { + __buffer_end = copy(__middle, __last, __buffer); + copy_backward(__first, __middle, __last); + return copy(__buffer, __buffer_end, __first); + } + else if (__len1 <= __buffer_size) { + __buffer_end = copy(__first, __middle, __buffer); + copy(__middle, __last, __first); + return copy_backward(__buffer, __buffer_end, __last); + } + else { + rotate(__first, __middle, __last); + advance(__first, distance(__middle, __last)); + return __first; + } + } + + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ + template<typename _BidirectionalIter1, typename _BidirectionalIter2, + typename _BidirectionalIter3> + _BidirectionalIter3 + __merge_backward(_BidirectionalIter1 __first1, _BidirectionalIter1 __last1, + _BidirectionalIter2 __first2, _BidirectionalIter2 __last2, + _BidirectionalIter3 __result) + { + if (__first1 == __last1) + return copy_backward(__first2, __last2, __result); + if (__first2 == __last2) + return copy_backward(__first1, __last1, __result); + --__last1; + --__last2; + while (true) { + if (*__last2 < *__last1) { + *--__result = *__last1; + if (__first1 == __last1) + return copy_backward(__first2, ++__last2, __result); + --__last1; + } + else { + *--__result = *__last2; + if (__first2 == __last2) + return copy_backward(__first1, ++__last1, __result); + --__last2; + } + } + } + + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ + template<typename _BidirectionalIter1, typename _BidirectionalIter2, + typename _BidirectionalIter3, typename _Compare> + _BidirectionalIter3 + __merge_backward(_BidirectionalIter1 __first1, _BidirectionalIter1 __last1, + _BidirectionalIter2 __first2, _BidirectionalIter2 __last2, + _BidirectionalIter3 __result, + _Compare __comp) + { + if (__first1 == __last1) + return copy_backward(__first2, __last2, __result); + if (__first2 == __last2) + return copy_backward(__first1, __last1, __result); + --__last1; + --__last2; + while (true) { + if (__comp(*__last2, *__last1)) { + *--__result = *__last1; + if (__first1 == __last1) + return copy_backward(__first2, ++__last2, __result); + --__last1; + } + else { + *--__result = *__last2; + if (__first2 == __last2) + return copy_backward(__first1, ++__last1, __result); + --__last2; + } + } + } + + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ + template<typename _BidirectionalIter, typename _Distance, typename _Pointer> + void + __merge_adaptive(_BidirectionalIter __first, + _BidirectionalIter __middle, + _BidirectionalIter __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size) + { + if (__len1 <= __len2 && __len1 <= __buffer_size) { + _Pointer __buffer_end = copy(__first, __middle, __buffer); + merge(__buffer, __buffer_end, __middle, __last, __first); + } + else if (__len2 <= __buffer_size) { + _Pointer __buffer_end = copy(__middle, __last, __buffer); + __merge_backward(__first, __middle, __buffer, __buffer_end, __last); + } + else { + _BidirectionalIter __first_cut = __first; + _BidirectionalIter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) { + __len11 = __len1 / 2; + advance(__first_cut, __len11); + __second_cut = lower_bound(__middle, __last, *__first_cut); + __len22 = distance(__middle, __second_cut); + } + else { + __len22 = __len2 / 2; + advance(__second_cut, __len22); + __first_cut = upper_bound(__first, __middle, *__second_cut); + __len11 = distance(__first, __first_cut); + } + _BidirectionalIter __new_middle = + __rotate_adaptive(__first_cut, __middle, __second_cut, + __len1 - __len11, __len22, __buffer, + __buffer_size); + __merge_adaptive(__first, __first_cut, __new_middle, __len11, + __len22, __buffer, __buffer_size); + __merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11, + __len2 - __len22, __buffer, __buffer_size); + } + } + + /** + * @if maint + * This is a helper function for the merge routines. + * @endif + */ + template<typename _BidirectionalIter, typename _Distance, typename _Pointer, + typename _Compare> + void + __merge_adaptive(_BidirectionalIter __first, + _BidirectionalIter __middle, + _BidirectionalIter __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + if (__len1 <= __len2 && __len1 <= __buffer_size) { + _Pointer __buffer_end = copy(__first, __middle, __buffer); + merge(__buffer, __buffer_end, __middle, __last, __first, __comp); + } + else if (__len2 <= __buffer_size) { + _Pointer __buffer_end = copy(__middle, __last, __buffer); + __merge_backward(__first, __middle, __buffer, __buffer_end, __last, + __comp); + } + else { + _BidirectionalIter __first_cut = __first; + _BidirectionalIter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) { + __len11 = __len1 / 2; + advance(__first_cut, __len11); + __second_cut = lower_bound(__middle, __last, *__first_cut, __comp); + __len22 = distance(__middle, __second_cut); + } + else { + __len22 = __len2 / 2; + advance(__second_cut, __len22); + __first_cut = upper_bound(__first, __middle, *__second_cut, __comp); + __len11 = distance(__first, __first_cut); + } + _BidirectionalIter __new_middle = + __rotate_adaptive(__first_cut, __middle, __second_cut, + __len1 - __len11, __len22, __buffer, + __buffer_size); + __merge_adaptive(__first, __first_cut, __new_middle, __len11, + __len22, __buffer, __buffer_size, __comp); + __merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11, + __len2 - __len22, __buffer, __buffer_size, __comp); + } + } + + /** + * @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, + _BidirectionalIter __middle, + _BidirectionalIter __last) + { + typedef typename iterator_traits<_BidirectionalIter>::value_type + _ValueType; + typedef typename iterator_traits<_BidirectionalIter>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIter>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + if (__first == __middle || __middle == __last) + return; + + _DistanceType __len1 = distance(__first, __middle); + _DistanceType __len2 = distance(__middle, __last); + + _Temporary_buffer<_BidirectionalIter, _ValueType> __buf(__first, __last); + if (__buf.begin() == 0) + __merge_without_buffer(__first, __middle, __last, __len1, __len2); + else + __merge_adaptive(__first, __middle, __last, __len1, __len2, + __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, + _BidirectionalIter __middle, + _BidirectionalIter __last, + _Compare __comp) + { + typedef typename iterator_traits<_BidirectionalIter>::value_type + _ValueType; + typedef typename iterator_traits<_BidirectionalIter>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + _ValueType, _ValueType>) + + if (__first == __middle || __middle == __last) + return; + + _DistanceType __len1 = distance(__first, __middle); + _DistanceType __len2 = distance(__middle, __last); + + _Temporary_buffer<_BidirectionalIter, _ValueType> __buf(__first, __last); + if (__buf.begin() == 0) + __merge_without_buffer(__first, __middle, __last, __len1, __len2, __comp); + else + __merge_adaptive(__first, __middle, __last, __len1, __len2, + __buf.begin(), _DistanceType(__buf.size()), + __comp); + } + + // Set algorithms: includes, set_union, set_intersection, set_difference, + // set_symmetric_difference. All of these algorithms have the precondition + // that their input ranges are sorted and the postcondition that their output + // ranges are sorted. + + template<typename _InputIter1, typename _InputIter2> + bool + includes(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) + return false; + else if(*__first1 < *__first2) + ++__first1; + else + ++__first1, ++__first2; + + return __first2 == __last2; + } + + template<typename _InputIter1, typename _InputIter2, typename _Compare> + bool + includes(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) + return false; + else if(__comp(*__first1, *__first2)) + ++__first1; + else + ++__first1, ++__first2; + + return __first2 == __last2; + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter> + _OutputIter + set_union(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) { + if (*__first1 < *__first2) { + *__result = *__first1; + ++__first1; + } + else if (*__first2 < *__first1) { + *__result = *__first2; + ++__first2; + } + else { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + return copy(__first2, __last2, copy(__first1, __last1, __result)); + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter, + typename _Compare> + _OutputIter + set_union(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) { + if (__comp(*__first1, *__first2)) { + *__result = *__first1; + ++__first1; + } + else if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__first2; + } + else { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + return copy(__first2, __last2, copy(__first1, __last1, __result)); + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter> + _OutputIter + set_intersection(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (*__first1 < *__first2) + ++__first1; + else if (*__first2 < *__first1) + ++__first2; + else { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + return __result; + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter, + typename _Compare> + _OutputIter + set_intersection(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first1, *__first2)) + ++__first1; + else if (__comp(*__first2, *__first1)) + ++__first2; + else { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + return __result; + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter> + _OutputIter + set_difference(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (*__first1 < *__first2) { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (*__first2 < *__first1) + ++__first2; + else { + ++__first1; + ++__first2; + } + return copy(__first1, __last1, __result); + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter, + typename _Compare> + _OutputIter + set_difference(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first1, *__first2)) { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(*__first2, *__first1)) + ++__first2; + else { + ++__first1; + ++__first2; + } + return copy(__first1, __last1, __result); + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter> + _OutputIter + set_symmetric_difference(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (*__first1 < *__first2) { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (*__first2 < *__first1) { + *__result = *__first2; + ++__first2; + ++__result; + } + else { + ++__first1; + ++__first2; + } + return copy(__first2, __last2, copy(__first1, __last1, __result)); + } + + template<typename _InputIter1, typename _InputIter2, typename _OutputIter, + typename _Compare> + _OutputIter + set_symmetric_difference(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _OutputIter __result, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_SameTypeConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first1, *__first2)) { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(*__first2, *__first1)) { + *__result = *__first2; + ++__first2; + ++__result; + } + else { + ++__first1; + ++__first2; + } + return copy(__first2, __last2, copy(__first1, __last1, __result)); + } + + // min_element and max_element, with and without an explicitly supplied + // comparison function. + + template<typename _ForwardIter> + _ForwardIter + max_element(_ForwardIter __first, _ForwardIter __last) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIter>::value_type>) + + if (__first == __last) return __first; + _ForwardIter __result = __first; + while (++__first != __last) + if (*__result < *__first) + __result = __first; + return __result; + } + + template<typename _ForwardIter, typename _Compare> + _ForwardIter + max_element(_ForwardIter __first, _ForwardIter __last, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + + if (__first == __last) return __first; + _ForwardIter __result = __first; + while (++__first != __last) + if (__comp(*__result, *__first)) __result = __first; + return __result; + } + + template<typename _ForwardIter> + _ForwardIter + min_element(_ForwardIter __first, _ForwardIter __last) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIter>::value_type>) + + if (__first == __last) return __first; + _ForwardIter __result = __first; + while (++__first != __last) + if (*__first < *__result) + __result = __first; + return __result; + } + + template<typename _ForwardIter, typename _Compare> + _ForwardIter + min_element(_ForwardIter __first, _ForwardIter __last, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + + if (__first == __last) return __first; + _ForwardIter __result = __first; + while (++__first != __last) + if (__comp(*__first, *__result)) + __result = __first; + return __result; + } + + // next_permutation and prev_permutation, with and without an explicitly + // supplied comparison function. + + template<typename _BidirectionalIter> + bool + next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIter>::value_type>) + + if (__first == __last) + return false; + _BidirectionalIter __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) { + _BidirectionalIter __ii = __i; + --__i; + if (*__i < *__ii) { + _BidirectionalIter __j = __last; + while (!(*__i < *--__j)) + {} + iter_swap(__i, __j); + reverse(__ii, __last); + return true; + } + if (__i == __first) { + reverse(__first, __last); + return false; + } + } + } + + template<typename _BidirectionalIter, typename _Compare> + bool + next_permutation(_BidirectionalIter __first, _BidirectionalIter __last, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIter>::value_type, + typename iterator_traits<_BidirectionalIter>::value_type>) + + if (__first == __last) + return false; + _BidirectionalIter __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) { + _BidirectionalIter __ii = __i; + --__i; + if (__comp(*__i, *__ii)) { + _BidirectionalIter __j = __last; + while (!__comp(*__i, *--__j)) + {} + iter_swap(__i, __j); + reverse(__ii, __last); + return true; + } + if (__i == __first) { + reverse(__first, __last); + return false; + } + } + } + + template<typename _BidirectionalIter> + bool + prev_permutation(_BidirectionalIter __first, _BidirectionalIter __last) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIter>::value_type>) + + if (__first == __last) + return false; + _BidirectionalIter __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) { + _BidirectionalIter __ii = __i; + --__i; + if (*__ii < *__i) { + _BidirectionalIter __j = __last; + while (!(*--__j < *__i)) + {} + iter_swap(__i, __j); + reverse(__ii, __last); + return true; + } + if (__i == __first) { + reverse(__first, __last); + return false; + } + } + } + + template<typename _BidirectionalIter, typename _Compare> + bool + prev_permutation(_BidirectionalIter __first, _BidirectionalIter __last, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter>) + __glibcpp_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIter>::value_type, + typename iterator_traits<_BidirectionalIter>::value_type>) + + if (__first == __last) + return false; + _BidirectionalIter __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) { + _BidirectionalIter __ii = __i; + --__i; + if (__comp(*__ii, *__i)) { + _BidirectionalIter __j = __last; + while (!__comp(*--__j, *__i)) + {} + iter_swap(__i, __j); + reverse(__ii, __last); + return true; + } + if (__i == __first) { + reverse(__first, __last); + return false; + } + } + } + + // find_first_of, with and without an explicitly supplied comparison function. + + template<typename _InputIter, typename _ForwardIter> + _InputIter + find_first_of(_InputIter __first1, _InputIter __last1, + _ForwardIter __first2, _ForwardIter __last2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + + for ( ; __first1 != __last1; ++__first1) + for (_ForwardIter __iter = __first2; __iter != __last2; ++__iter) + if (*__first1 == *__iter) + return __first1; + return __last1; + } + + template<typename _InputIter, typename _ForwardIter, typename _BinaryPredicate> + _InputIter + find_first_of(_InputIter __first1, _InputIter __last1, + _ForwardIter __first2, _ForwardIter __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIter>::value_type, + typename iterator_traits<_ForwardIter>::value_type>) + + for ( ; __first1 != __last1; ++__first1) + for (_ForwardIter __iter = __first2; __iter != __last2; ++__iter) + if (__comp(*__first1, *__iter)) + return __first1; + return __last1; + } + + + // find_end, with and without an explicitly supplied comparison function. + // Search [first2, last2) as a subsequence in [first1, last1), and return + // the *last* possible match. Note that find_end for bidirectional iterators + // is much faster than for forward iterators. + + // find_end for forward iterators. + template<typename _ForwardIter1, typename _ForwardIter2> + _ForwardIter1 + __find_end(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2, + forward_iterator_tag, forward_iterator_tag) + { + if (__first2 == __last2) + return __last1; + else { + _ForwardIter1 __result = __last1; + while (1) { + _ForwardIter1 __new_result + = search(__first1, __last1, __first2, __last2); + if (__new_result == __last1) + return __result; + else { + __result = __new_result; + __first1 = __new_result; + ++__first1; + } + } + } + } + + template<typename _ForwardIter1, typename _ForwardIter2, + typename _BinaryPredicate> + _ForwardIter1 + __find_end(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2, + forward_iterator_tag, forward_iterator_tag, + _BinaryPredicate __comp) + { + if (__first2 == __last2) + return __last1; + else { + _ForwardIter1 __result = __last1; + while (1) { + _ForwardIter1 __new_result + = search(__first1, __last1, __first2, __last2, __comp); + if (__new_result == __last1) + return __result; + else { + __result = __new_result; + __first1 = __new_result; + ++__first1; + } + } + } + } + + // find_end for bidirectional iterators. Requires partial specialization. + template<typename _BidirectionalIter1, typename _BidirectionalIter2> + _BidirectionalIter1 + __find_end(_BidirectionalIter1 __first1, _BidirectionalIter1 __last1, + _BidirectionalIter2 __first2, _BidirectionalIter2 __last2, + bidirectional_iterator_tag, bidirectional_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter1>) + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter2>) + + typedef reverse_iterator<_BidirectionalIter1> _RevIter1; + typedef reverse_iterator<_BidirectionalIter2> _RevIter2; + + _RevIter1 __rlast1(__first1); + _RevIter2 __rlast2(__first2); + _RevIter1 __rresult = search(_RevIter1(__last1), __rlast1, + _RevIter2(__last2), __rlast2); + + if (__rresult == __rlast1) + return __last1; + else { + _BidirectionalIter1 __result = __rresult.base(); + advance(__result, -distance(__first2, __last2)); + return __result; + } + } + + template<typename _BidirectionalIter1, typename _BidirectionalIter2, + typename _BinaryPredicate> + _BidirectionalIter1 + __find_end(_BidirectionalIter1 __first1, _BidirectionalIter1 __last1, + _BidirectionalIter2 __first2, _BidirectionalIter2 __last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, + _BinaryPredicate __comp) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter1>) + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIter2>) + + typedef reverse_iterator<_BidirectionalIter1> _RevIter1; + typedef reverse_iterator<_BidirectionalIter2> _RevIter2; + + _RevIter1 __rlast1(__first1); + _RevIter2 __rlast2(__first2); + _RevIter1 __rresult = search(_RevIter1(__last1), __rlast1, + _RevIter2(__last2), __rlast2, + __comp); + + if (__rresult == __rlast1) + return __last1; + else { + _BidirectionalIter1 __result = __rresult.base(); + advance(__result, -distance(__first2, __last2)); + return __result; + } + } + + // Dispatching functions for find_end. + + template<typename _ForwardIter1, typename _ForwardIter2> + inline _ForwardIter1 + find_end(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIter1>::value_type, + typename iterator_traits<_ForwardIter2>::value_type>) + + return __find_end(__first1, __last1, __first2, __last2, + __iterator_category(__first1), + __iterator_category(__first2)); + } + + template<typename _ForwardIter1, typename _ForwardIter2, + typename _BinaryPredicate> + inline _ForwardIter1 + find_end(_ForwardIter1 __first1, _ForwardIter1 __last1, + _ForwardIter2 __first2, _ForwardIter2 __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIter1>::value_type, + typename iterator_traits<_ForwardIter2>::value_type>) + + return __find_end(__first1, __last1, __first2, __last2, + __iterator_category(__first1), + __iterator_category(__first2), + __comp); + } + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_ALGO_H */ + diff --git a/contrib/libstdc++/include/bits/stl_algobase.h b/contrib/libstdc++/include/bits/stl_algobase.h new file mode 100644 index 0000000000000..6e488eae355f2 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_algobase.h @@ -0,0 +1,820 @@ +// Bits and pieces used in algorithms -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_algobase.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_ALGOBASE_H +#define __GLIBCPP_INTERNAL_ALGOBASE_H + +#include <bits/c++config.h> +#include <cstring> +#include <climits> +#include <cstdlib> +#include <cstddef> +#include <new> +#include <iosfwd> +#include <bits/stl_pair.h> +#include <bits/type_traits.h> +#include <bits/stl_iterator_base_types.h> +#include <bits/stl_iterator_base_funcs.h> +#include <bits/stl_iterator.h> +#include <bits/concept_check.h> + +namespace std +{ + // swap and iter_swap + + /** + * @brief Swaps the contents of two iterators. + * @param a An iterator. + * @param b Another iterator. + * @return Nothing. + * + * This function swaps the values pointed to by two iterators, not the + * iterators themselves. + */ + template<typename _ForwardIter1, typename _ForwardIter2> + inline void + iter_swap(_ForwardIter1 __a, _ForwardIter2 __b) + { + typedef typename iterator_traits<_ForwardIter1>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIter2>::value_type _ValueType2; + + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter1>) + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter2>) + __glibcpp_function_requires(_ConvertibleConcept<_ValueType1, _ValueType2>) + __glibcpp_function_requires(_ConvertibleConcept<_ValueType2, _ValueType1>) + + _ValueType1 __tmp = *__a; + *__a = *__b; + *__b = __tmp; + } + + /** + * @brief Swaps two values. + * @param a A thing of arbitrary type. + * @param b Another thing of arbitrary type. + * @return Nothing. + * + * This is the simple classic generic implementation. It will work on + * any type which has a copy constructor and an assignment operator. + */ + template<typename _Tp> + inline void + swap(_Tp& __a, _Tp& __b) + { + // concept requirements + __glibcpp_function_requires(_SGIAssignableConcept<_Tp>) + + _Tp __tmp = __a; + __a = __b; + __b = __tmp; + } + + //-------------------------------------------------- + // min and max + + #undef min + #undef max + + /** + * @brief This does what you think it does. + * @param a A thing of arbitrary type. + * @param b Another thing of arbitrary type. + * @return The lesser of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template<typename _Tp> + inline const _Tp& + min(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + //return __b < __a ? __b : __a; + if (__b < __a) return __b; return __a; + } + + /** + * @brief This does what you think it does. + * @param a A thing of arbitrary type. + * @param b Another thing of arbitrary type. + * @return The greater of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template<typename _Tp> + inline const _Tp& + max(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcpp_function_requires(_LessThanComparableConcept<_Tp>) + //return __a < __b ? __b : __a; + if (__a < __b) return __b; return __a; + } + + /** + * @brief This does what you think it does. + * @param a A thing of arbitrary type. + * @param b Another thing of arbitrary type. + * @param comp A @link s20_3_3_comparisons comparison functor@endlink. + * @return The lesser of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template<typename _Tp, typename _Compare> + inline const _Tp& + min(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__b, __a) ? __b : __a; + if (__comp(__b, __a)) return __b; return __a; + } + + /** + * @brief This does what you think it does. + * @param a A thing of arbitrary type. + * @param b Another thing of arbitrary type. + * @param comp A @link s20_3_3_comparisons comparison functor@endlink. + * @return The greater of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template<typename _Tp, typename _Compare> + inline const _Tp& + max(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__a, __b) ? __b : __a; + if (__comp(__a, __b)) return __b; return __a; + } + + //-------------------------------------------------- + // copy + + // All of these auxiliary functions serve two purposes. (1) Replace + // calls to copy with memmove whenever possible. (Memmove, not memcpy, + // because the input and output ranges are permitted to overlap.) + // (2) If we're using random access iterators, then write the loop as + // a for loop with an explicit count. + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy(_InputIter __first, _InputIter __last, + _OutputIter __result, + input_iterator_tag) + { + for ( ; __first != __last; ++__result, ++__first) + *__result = *__first; + return __result; + } + + template<typename _RandomAccessIter, typename _OutputIter> + inline _OutputIter + __copy(_RandomAccessIter __first, _RandomAccessIter __last, + _OutputIter __result, + random_access_iterator_tag) + { + typedef typename iterator_traits<_RandomAccessIter>::difference_type + _Distance; + for (_Distance __n = __last - __first; __n > 0; --__n) { + *__result = *__first; + ++__first; + ++__result; + } + return __result; + } + + template<typename _Tp> + inline _Tp* + __copy_trivial(const _Tp* __first, const _Tp* __last, _Tp* __result) + { + memmove(__result, __first, sizeof(_Tp) * (__last - __first)); + return __result + (__last - __first); + } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_aux2(_InputIter __first, _InputIter __last, + _OutputIter __result, __false_type) + { return __copy(__first, __last, __result, __iterator_category(__first)); } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_aux2(_InputIter __first, _InputIter __last, + _OutputIter __result, __true_type) + { return __copy(__first, __last, __result, __iterator_category(__first)); } + + template<typename _Tp> + inline _Tp* + __copy_aux2(_Tp* __first, _Tp* __last, + _Tp* __result, __true_type) + { return __copy_trivial(__first, __last, __result); } + + template<typename _Tp> + inline _Tp* + __copy_aux2(const _Tp* __first, const _Tp* __last, + _Tp* __result, __true_type) + { return __copy_trivial(__first, __last, __result); } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_ni2(_InputIter __first, _InputIter __last, + _OutputIter __result, __true_type) + { + typedef typename iterator_traits<_InputIter>::value_type + _ValueType; + typedef typename __type_traits<_ValueType>::has_trivial_assignment_operator + _Trivial; + return _OutputIter(__copy_aux2(__first, __last, + __result.base(), + _Trivial())); + } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_ni2(_InputIter __first, _InputIter __last, + _OutputIter __result, __false_type) + { + typedef typename iterator_traits<_InputIter>::value_type + _ValueType; + typedef typename __type_traits<_ValueType>::has_trivial_assignment_operator + _Trivial; + return __copy_aux2(__first, __last, + __result, + _Trivial()); + } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_ni1(_InputIter __first, _InputIter __last, + _OutputIter __result, __true_type) + { + typedef typename _Is_normal_iterator<_OutputIter>::_Normal __Normal; + return __copy_ni2(__first.base(), __last.base(), __result, __Normal()); + } + + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + __copy_ni1(_InputIter __first, _InputIter __last, + _OutputIter __result, __false_type) + { + typedef typename _Is_normal_iterator<_OutputIter>::_Normal __Normal; + return __copy_ni2(__first, __last, __result, __Normal()); + } + + /** + * @brief Copies the range [first,last) into result. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @return result + (first - last) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). If the input range and the output + * range overlap, then the copy_backward function should be used instead. + */ + template<typename _InputIter, typename _OutputIter> + inline _OutputIter + copy(_InputIter __first, _InputIter __last, _OutputIter __result) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter, + typename iterator_traits<_InputIter>::value_type>) + + typedef typename _Is_normal_iterator<_InputIter>::_Normal __Normal; + return __copy_ni1(__first, __last, __result, __Normal()); + } + + //-------------------------------------------------- + // copy_backward + + template<typename _BidirectionalIter1, typename _BidirectionalIter2> + inline _BidirectionalIter2 + __copy_backward(_BidirectionalIter1 __first, _BidirectionalIter1 __last, + _BidirectionalIter2 __result, + bidirectional_iterator_tag) + { + while (__first != __last) + *--__result = *--__last; + return __result; + } + + template<typename _RandomAccessIter, typename _BidirectionalIter> + inline _BidirectionalIter + __copy_backward(_RandomAccessIter __first, _RandomAccessIter __last, + _BidirectionalIter __result, + random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIter>::difference_type __n; + for (__n = __last - __first; __n > 0; --__n) + *--__result = *--__last; + return __result; + } + + + // This dispatch class is a workaround for compilers that do not + // have partial ordering of function templates. All we're doing is + // creating a specialization so that we can turn a call to copy_backward + // into a memmove whenever possible. + + template<typename _BidirectionalIter1, typename _BidirectionalIter2, + typename _BoolType> + struct __copy_backward_dispatch + { + static _BidirectionalIter2 + copy(_BidirectionalIter1 __first, _BidirectionalIter1 __last, + _BidirectionalIter2 __result) + { + return __copy_backward(__first, __last, + __result, + __iterator_category(__first)); + } + }; + + template<typename _Tp> + struct __copy_backward_dispatch<_Tp*, _Tp*, __true_type> + { + static _Tp* + copy(const _Tp* __first, const _Tp* __last, _Tp* __result) + { + const ptrdiff_t _Num = __last - __first; + memmove(__result - _Num, __first, sizeof(_Tp) * _Num); + return __result - _Num; + } + }; + + template<typename _Tp> + struct __copy_backward_dispatch<const _Tp*, _Tp*, __true_type> + { + static _Tp* + copy(const _Tp* __first, const _Tp* __last, _Tp* __result) + { + return __copy_backward_dispatch<_Tp*, _Tp*, __true_type> + ::copy(__first, __last, __result); + } + }; + + template<typename _BI1, typename _BI2> + inline _BI2 + __copy_backward_aux(_BI1 __first, _BI1 __last, _BI2 __result) + { + typedef typename __type_traits<typename iterator_traits<_BI2>::value_type> + ::has_trivial_assignment_operator _Trivial; + return __copy_backward_dispatch<_BI1, _BI2, _Trivial> + ::copy(__first, __last, __result); + } + + template <typename _BI1, typename _BI2> + inline _BI2 + __copy_backward_output_normal_iterator(_BI1 __first, _BI1 __last, + _BI2 __result, __true_type) + { return _BI2(__copy_backward_aux(__first, __last, __result.base())); } + + template <typename _BI1, typename _BI2> + inline _BI2 + __copy_backward_output_normal_iterator(_BI1 __first, _BI1 __last, + _BI2 __result, __false_type) + { return __copy_backward_aux(__first, __last, __result); } + + template <typename _BI1, typename _BI2> + inline _BI2 + __copy_backward_input_normal_iterator(_BI1 __first, _BI1 __last, + _BI2 __result, __true_type) + { + typedef typename _Is_normal_iterator<_BI2>::_Normal __Normal; + return __copy_backward_output_normal_iterator(__first.base(), __last.base(), + __result, __Normal()); + } + + template <typename _BI1, typename _BI2> + inline _BI2 + __copy_backward_input_normal_iterator(_BI1 __first, _BI1 __last, + _BI2 __result, __false_type) + { + typedef typename _Is_normal_iterator<_BI2>::_Normal __Normal; + return __copy_backward_output_normal_iterator(__first, __last, __result, + __Normal()); + } + + /** + * @brief Copies the range [first,last) into result. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @return result - (first - last) + * + * The function has the same effect as copy, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + */ + template <typename _BI1, typename _BI2> + inline _BI2 + copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcpp_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcpp_function_requires(_ConvertibleConcept< + typename iterator_traits<_BI1>::value_type, + typename iterator_traits<_BI2>::value_type>) + + typedef typename _Is_normal_iterator<_BI1>::_Normal __Normal; + return __copy_backward_input_normal_iterator(__first, __last, __result, + __Normal()); + } + + + //-------------------------------------------------- + // fill and fill_n + + + /** + * @brief Fills the range [first,last) with copies of value. + * @param first A forward iterator. + * @param last A forward iterator. + * @param value A reference-to-const of arbitrary type. + * @return Nothing. + * + * This function fills a range with copies of the same value. For one-byte + * types filling contiguous areas of memory, this becomes an inline call to + * @c memset. + */ + template<typename _ForwardIter, typename _Tp> + void + fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) + { + // concept requirements + __glibcpp_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + + for ( ; __first != __last; ++__first) + *__first = __value; + } + + /** + * @brief Fills the range [first,first+n) with copies of value. + * @param first An output iterator. + * @param n The count of copies to perform. + * @param value A reference-to-const of arbitrary type. + * @return The iterator at first+n. + * + * This function fills a range with copies of the same value. For one-byte + * types filling contiguous areas of memory, this becomes an inline call to + * @c memset. + */ + template<typename _OutputIter, typename _Size, typename _Tp> + _OutputIter + fill_n(_OutputIter __first, _Size __n, const _Tp& __value) + { + // concept requirements + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter,_Tp>) + + for ( ; __n > 0; --__n, ++__first) + *__first = __value; + return __first; + } + + // Specialization: for one-byte types we can use memset. + + inline void + fill(unsigned char* __first, unsigned char* __last, const unsigned char& __c) + { + unsigned char __tmp = __c; + memset(__first, __tmp, __last - __first); + } + + inline void + fill(signed char* __first, signed char* __last, const signed char& __c) + { + signed char __tmp = __c; + memset(__first, static_cast<unsigned char>(__tmp), __last - __first); + } + + inline void + fill(char* __first, char* __last, const char& __c) + { + char __tmp = __c; + memset(__first, static_cast<unsigned char>(__tmp), __last - __first); + } + + template<typename _Size> + inline unsigned char* + fill_n(unsigned char* __first, _Size __n, const unsigned char& __c) + { + fill(__first, __first + __n, __c); + return __first + __n; + } + + template<typename _Size> + inline signed char* + fill_n(char* __first, _Size __n, const signed char& __c) + { + fill(__first, __first + __n, __c); + return __first + __n; + } + + template<typename _Size> + inline char* + fill_n(char* __first, _Size __n, const char& __c) + { + fill(__first, __first + __n, __c); + return __first + __n; + } + + + //-------------------------------------------------- + // equal and mismatch + + /** + * @brief Finds the places in ranges which don't match. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template<typename _InputIter1, typename _InputIter2> + pair<_InputIter1, _InputIter2> + mismatch(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIter2>::value_type>) + + while (__first1 != __last1 && *__first1 == *__first2) { + ++__first1; + ++__first2; + } + return pair<_InputIter1, _InputIter2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @param binary_pred A binary predicate @link s20_3_1_base functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template<typename _InputIter1, typename _InputIter2, typename _BinaryPredicate> + pair<_InputIter1, _InputIter2> + mismatch(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + + while (__first1 != __last1 && __binary_pred(*__first1, *__first2)) { + ++__first1; + ++__first2; + } + return pair<_InputIter1, _InputIter2>(__first1, __first2); + } + + /** + * @brief Tests a range for element-wise equality. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template<typename _InputIter1, typename _InputIter2> + inline bool + equal(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIter1>::value_type, + typename iterator_traits<_InputIter2>::value_type>) + + for ( ; __first1 != __last1; ++__first1, ++__first2) + if (!(*__first1 == *__first2)) + return false; + return true; + } + + /** + * @brief Tests a range for element-wise equality. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @param binary_pred A binary predicate @link s20_3_1_base functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template<typename _InputIter1, typename _InputIter2, typename _BinaryPredicate> + inline bool + equal(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + + for ( ; __first1 != __last1; ++__first1, ++__first2) + if (!__binary_pred(*__first1, *__first2)) + return false; + return true; + } + + //-------------------------------------------------- + // lexicographical_compare + + /** + * @brief Performs "dictionary" comparison on ranges. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @param last2 An input iterator. + * @return A boolean true or false. + * + * "Returns true if the sequence of elements defined by the range + * [first1,last1) is lexicographically less than the sequence of elements + * defined by the range [first2,last2). Returns false otherwise." + * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, + * then this is an inline call to @c memcmp. + */ + template<typename _InputIter1, typename _InputIter2> + bool + lexicographical_compare(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter1>::value_type>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_InputIter2>::value_type>) + + for ( ; __first1 != __last1 && __first2 != __last2 + ; ++__first1, ++__first2) { + if (*__first1 < *__first2) + return true; + if (*__first2 < *__first1) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + /** + * @brief Performs "dictionary" comparison on ranges. + * @param first1 An input iterator. + * @param last1 An input iterator. + * @param first2 An input iterator. + * @param last2 An input iterator. + * @param comp A @link s20_3_3_comparisons comparison functor@endlink. + * @return A boolean true or false. + * + * The same as the four-parameter @c lexigraphical_compare, but uses the + * comp parameter instead of @c <. + */ + template<typename _InputIter1, typename _InputIter2, typename _Compare> + bool + lexicographical_compare(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>) + + for ( ; __first1 != __last1 && __first2 != __last2 + ; ++__first1, ++__first2) { + if (__comp(*__first1, *__first2)) + return true; + if (__comp(*__first2, *__first1)) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + inline bool + lexicographical_compare(const unsigned char* __first1, const unsigned char* __last1, + const unsigned char* __first2, const unsigned char* __last2) + { + const size_t __len1 = __last1 - __first1; + const size_t __len2 = __last2 - __first2; + const int __result = memcmp(__first1, __first2, min(__len1, __len2)); + return __result != 0 ? __result < 0 : __len1 < __len2; + } + + inline bool + lexicographical_compare(const char* __first1, const char* __last1, + const char* __first2, const char* __last2) + { +#if CHAR_MAX == SCHAR_MAX + return lexicographical_compare((const signed char*) __first1, + (const signed char*) __last1, + (const signed char*) __first2, + (const signed char*) __last2); +#else /* CHAR_MAX == SCHAR_MAX */ + return lexicographical_compare((const unsigned char*) __first1, + (const unsigned char*) __last1, + (const unsigned char*) __first2, + (const unsigned char*) __last2); +#endif /* CHAR_MAX == SCHAR_MAX */ + } + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_ALGOBASE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_alloc.h b/contrib/libstdc++/include/bits/stl_alloc.h new file mode 100644 index 0000000000000..7c34000401c13 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_alloc.h @@ -0,0 +1,941 @@ +// Allocators -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_alloc.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_ALLOC_H +#define __GLIBCPP_INTERNAL_ALLOC_H + +/** + * @defgroup Allocators Memory Allocators + * @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 + * pointer type. The C++ standard allocators are intended to allocate + * individual objects, not pools or arenas. + * + * In this file allocators are of two different styles: "standard" and + * "SGI" (quotes included). "Standard" allocators conform to 20.4. "SGI" + * allocators differ in AT LEAST the following ways (add to this list as you + * discover them): + * + * - "Standard" allocate() takes two parameters (n_count,hint=0) but "SGI" + * allocate() takes one paramter (n_size). + * - Likewise, "standard" deallocate()'s argument is a count, but in "SGI" + * is a byte size. + * - max_size(), construct(), and destroy() are missing in "SGI" allocators. + * - reallocate(p,oldsz,newsz) is added in "SGI", and behaves as + * if p=realloc(p,newsz). + * + * "SGI" allocators may be wrapped in __allocator to convert the interface + * into a "standard" one. + * @endif + * + * 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 +*/ + +#include <cstddef> +#include <cstdlib> +#include <cstring> +#include <cassert> +#include <bits/functexcept.h> // For __throw_bad_alloc +#include <bits/stl_threads.h> + +namespace std +{ + /** + * @if maint + * A new-based allocator, as required by the standard. Allocation and + * deallocation forward to global new and delete. "SGI" style, minus + * reallocate(). + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + class __new_alloc + { + public: + static void* + allocate(size_t __n) + { return ::operator new(__n); } + + static void + deallocate(void* __p, size_t) + { ::operator delete(__p); } + }; + + + /** + * @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. + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template <int __inst> + class __malloc_alloc_template + { + private: + static void* _S_oom_malloc(size_t); + static void* _S_oom_realloc(void*, size_t); + static void (* __malloc_alloc_oom_handler)(); + + public: + static void* + allocate(size_t __n) + { + void* __result = malloc(__n); + if (0 == __result) __result = _S_oom_malloc(__n); + return __result; + } + + static void + deallocate(void* __p, size_t /* __n */) + { free(__p); } + + 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; + } + + static void (* __set_malloc_handler(void (*__f)()))() + { + void (* __old)() = __malloc_alloc_oom_handler; + __malloc_alloc_oom_handler = __f; + return(__old); + } + }; + + // malloc_alloc out-of-memory handling + template <int __inst> + void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0; + + template <int __inst> + void* + __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); + } + } + + 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); + } + } + + +// Determines the underlying allocator choice for the node allocator. +#ifdef __USE_MALLOC + typedef __malloc_alloc_template<0> __mem_interface; +#else + typedef __new_alloc __mem_interface; +#endif + + + /** + * @if maint + * This is used primarily (only?) in _Alloc_traits and other places to + * help provide the _Alloc_type typedef. + * + * This is neither "standard"-conforming nor "SGI". The _Alloc parameter + * must be "SGI" style. + * @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)); } + }; + + + /** + * @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 + * paid, therefore it is far better to just use the underlying allocator + * by itelf when no checking is desired. + * + * "There is some evidence that this can confuse Purify." - SGI comment + * + * This adaptor is "SGI" style. The _Alloc parameter must also be "SGI". + * @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) + { + 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) + { + 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; + } + }; + + +#ifdef __USE_MALLOC + +typedef __mem_interface __alloc; +typedef __mem_interface __single_client_alloc; + +#else + + +/** + * @if 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. + * + * @endif + * (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 _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; + }; + + // __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); + }; + + + template<bool __threads, int __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>&) + { 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. + template<bool __threads, int __inst> + char* + __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)); + } + } + + + // 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. + template<bool __threads, int __inst> + void* + __default_alloc_template<__threads, __inst>::_S_refill(size_t __n) + { + int __nobjs = 20; + char* __chunk = _S_chunk_alloc(__n, __nobjs); + _Obj* volatile* __my_free_list; + _Obj* __result; + _Obj* __current_obj; + _Obj* __next_obj; + int __i; + + if (1 == __nobjs) return(__chunk); + __my_free_list = _S_free_list + _S_freelist_index(__n); + + /* 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); + } + + + template<bool threads, int inst> + void* + __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) { + return(realloc(__p, __new_sz)); + } + 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); + } + + template<bool __threads, int __inst> + _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; + + template<bool __threads, int __inst> + 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; + + 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; + + +#endif /* ! __USE_MALLOC */ + + +/** + * 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; + }; + + 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; + }; +}; + + +template <class _T1, class _T2> +inline bool operator==(const allocator<_T1>&, const allocator<_T2>&) +{ + return true; +} + +template <class _T1, class _T2> +inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&) +{ + return false; +} + + +/** + * @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 <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; + }; + + __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; +} + +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; +} + + +//@{ +/** 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 <class _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; +} +//@} + + +/** + * @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 <class _Tp, class _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; + +/// 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 + +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 + +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; +}; +//@} + + // 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>; +#ifdef __USE_MALLOC + extern template class __malloc_alloc_template<0>; +#else + extern template class __default_alloc_template<true, 0>; +#endif +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_ALLOC_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_bvector.h b/contrib/libstdc++/include/bits/stl_bvector.h new file mode 100644 index 0000000000000..6cb6d9caf36fe --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_bvector.h @@ -0,0 +1,726 @@ +// bit_vector and vector<bool> specialization -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_bvector.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_BVECTOR_H +#define __GLIBCPP_INTERNAL_BVECTOR_H + +namespace std +{ + typedef unsigned long _Bit_type; + enum { _M_word_bit = int(CHAR_BIT * sizeof(_Bit_type)) }; + +struct _Bit_reference { + + _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); } + _Bit_reference& operator=(bool __x) + { + if (__x) *_M_p |= _M_mask; + else *_M_p &= ~_M_mask; + return *this; + } + _Bit_reference& operator=(const _Bit_reference& __x) + { 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); } + void flip() { *_M_p ^= _M_mask; } +}; + +inline void swap(_Bit_reference __x, _Bit_reference __y) +{ + bool __tmp = __x; + __x = __y; + __y = __tmp; +} + +struct _Bit_iterator_base : public iterator<random_access_iterator_tag, bool> +{ + _Bit_type * _M_p; + unsigned int _M_offset; + + _Bit_iterator_base(_Bit_type * __x, unsigned int __y) + : _M_p(__x), _M_offset(__y) {} + + void _M_bump_up() { + if (_M_offset++ == _M_word_bit - 1) { + _M_offset = 0; + ++_M_p; + } + } + void _M_bump_down() { + if (_M_offset-- == 0) { + _M_offset = _M_word_bit - 1; + --_M_p; + } + } + + void _M_incr(ptrdiff_t __i) { + difference_type __n = __i + _M_offset; + _M_p += __n / _M_word_bit; + __n = __n % _M_word_bit; + if (__n < 0) { + _M_offset = (unsigned int) __n + _M_word_bit; + --_M_p; + } else + _M_offset = (unsigned int) __n; + } + + bool operator==(const _Bit_iterator_base& __i) const { + return _M_p == __i._M_p && _M_offset == __i._M_offset; + } + bool operator<(const _Bit_iterator_base& __i) const { + return _M_p < __i._M_p || (_M_p == __i._M_p && _M_offset < __i._M_offset); + } + bool operator!=(const _Bit_iterator_base& __i) const { + return !(*this == __i); + } + bool operator>(const _Bit_iterator_base& __i) const { + return __i < *this; + } + bool operator<=(const _Bit_iterator_base& __i) const { + return !(__i < *this); + } + bool operator>=(const _Bit_iterator_base& __i) const { + return !(*this < __i); + } +}; + +inline ptrdiff_t +operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) { + return _M_word_bit * (__x._M_p - __y._M_p) + __x._M_offset - __y._M_offset; +} + + +struct _Bit_iterator : public _Bit_iterator_base +{ + typedef _Bit_reference reference; + typedef _Bit_reference* pointer; + typedef _Bit_iterator iterator; + + _Bit_iterator() : _Bit_iterator_base(0, 0) {} + _Bit_iterator(_Bit_type * __x, unsigned int __y) + : _Bit_iterator_base(__x, __y) {} + + reference operator*() const { return reference(_M_p, 1U << _M_offset); } + iterator& operator++() { + _M_bump_up(); + return *this; + } + iterator operator++(int) { + iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + iterator& operator--() { + _M_bump_down(); + return *this; + } + iterator operator--(int) { + iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + iterator& operator+=(difference_type __i) { + _M_incr(__i); + return *this; + } + iterator& operator-=(difference_type __i) { + *this += -__i; + return *this; + } + iterator operator+(difference_type __i) const { + iterator __tmp = *this; + return __tmp += __i; + } + iterator operator-(difference_type __i) const { + iterator __tmp = *this; + return __tmp -= __i; + } + + reference operator[](difference_type __i) { return *(*this + __i); } +}; + +inline _Bit_iterator +operator+(ptrdiff_t __n, const _Bit_iterator& __x) { return __x + __n; } + + +struct _Bit_const_iterator : public _Bit_iterator_base +{ + typedef bool reference; + typedef bool const_reference; + typedef const bool* pointer; + typedef _Bit_const_iterator const_iterator; + + _Bit_const_iterator() : _Bit_iterator_base(0, 0) {} + _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); + } + const_iterator& operator++() { + _M_bump_up(); + return *this; + } + const_iterator operator++(int) { + const_iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + const_iterator& operator--() { + _M_bump_down(); + return *this; + } + const_iterator operator--(int) { + const_iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + const_iterator& operator+=(difference_type __i) { + _M_incr(__i); + return *this; + } + const_iterator& operator-=(difference_type __i) { + *this += -__i; + return *this; + } + const_iterator operator+(difference_type __i) const { + const_iterator __tmp = *this; + return __tmp += __i; + } + const_iterator operator-(difference_type __i) const { + const_iterator __tmp = *this; + return __tmp -= __i; + } + const_reference operator[](difference_type __i) { + return *(*this + __i); + } +}; + +inline _Bit_const_iterator +operator+(ptrdiff_t __n, const _Bit_const_iterator& __x) { return __x + __n; } + + +// Bit-vector base class, which encapsulates the difference between +// old SGI-style allocators and standard-conforming allocators. + +// Base class for ordinary allocators. +template <class _Allocator, bool __is_static> +class _Bvector_alloc_base { +public: + typedef typename _Alloc_traits<bool, _Allocator>::allocator_type + allocator_type; + allocator_type get_allocator() const { return _M_data_allocator; } + + _Bvector_alloc_base(const allocator_type& __a) + : _M_data_allocator(__a), _M_start(), _M_finish(), _M_end_of_storage(0) {} + +protected: + _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<_Bit_type, _Allocator>::allocator_type + _M_data_allocator; + _Bit_iterator _M_start; + _Bit_iterator _M_finish; + _Bit_type * _M_end_of_storage; +}; + +// Specialization for instanceless allocators. +template <class _Allocator> +class _Bvector_alloc_base<_Allocator, true> { +public: + typedef typename _Alloc_traits<bool, _Allocator>::allocator_type + allocator_type; + allocator_type get_allocator() const { return allocator_type(); } + + _Bvector_alloc_base(const allocator_type&) + : _M_start(), _M_finish(), _M_end_of_storage(0) {} + +protected: + typedef typename _Alloc_traits<_Bit_type, _Allocator>::_Alloc_type + _Alloc_type; + + _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, + _M_end_of_storage - _M_start._M_p); + } + + _Bit_iterator _M_start; + _Bit_iterator _M_finish; + _Bit_type * _M_end_of_storage; +}; + +template <class _Alloc> +class _Bvector_base + : public _Bvector_alloc_base<_Alloc, + _Alloc_traits<bool, _Alloc>::_S_instanceless> +{ + typedef _Bvector_alloc_base<_Alloc, + _Alloc_traits<bool, _Alloc>::_S_instanceless> + _Base; +public: + typedef typename _Base::allocator_type allocator_type; + + _Bvector_base(const allocator_type& __a) : _Base(__a) {} + ~_Bvector_base() { _Base::_M_deallocate(); } +}; + +} // namespace std + +// Declare a partial specialization of vector<T, Alloc>. +#include <bits/stl_vector.h> +namespace std +{ + +template <typename _Alloc> + class vector<bool, _Alloc> : public _Bvector_base<_Alloc> + { + public: + typedef bool value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Bit_reference reference; + typedef bool const_reference; + typedef _Bit_reference* pointer; + typedef const bool* const_pointer; + + typedef _Bit_iterator iterator; + typedef _Bit_const_iterator const_iterator; + + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; + + typedef typename _Bvector_base<_Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { + return _Bvector_base<_Alloc>::get_allocator(); + } + + protected: + using _Bvector_base<_Alloc>::_M_bit_alloc; + using _Bvector_base<_Alloc>::_M_deallocate; + using _Bvector_base<_Alloc>::_M_start; + using _Bvector_base<_Alloc>::_M_finish; + using _Bvector_base<_Alloc>::_M_end_of_storage; + + protected: + void _M_initialize(size_type __n) { + _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); + } + void _M_insert_aux(iterator __position, bool __x) { + if (_M_finish._M_p != _M_end_of_storage) { + copy_backward(__position, _M_finish, _M_finish + 1); + *__position = __x; + ++_M_finish; + } + else { + 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 + _M_word_bit - 1)/_M_word_bit; + _M_start = iterator(__q, 0); + } + } + + template <class _InputIterator> + void _M_initialize_range(_InputIterator __first, _InputIterator __last, + input_iterator_tag) { + _M_start = iterator(); + _M_finish = iterator(); + _M_end_of_storage = 0; + for ( ; __first != __last; ++__first) + push_back(*__first); + } + + template <class _ForwardIterator> + void _M_initialize_range(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) { + size_type __n = distance(__first, __last); + _M_initialize(__n); + copy(__first, __last, _M_start); + } + + template <class _InputIterator> + void _M_insert_range(iterator __pos, + _InputIterator __first, _InputIterator __last, + input_iterator_tag) { + for ( ; __first != __last; ++__first) { + __pos = insert(__pos, *__first); + ++__pos; + } + } + + template <class _ForwardIterator> + void _M_insert_range(iterator __position, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) { + if (__first != __last) { + size_type __n = distance(__first, __last); + if (capacity() - size() >= __n) { + copy_backward(__position, end(), _M_finish + difference_type(__n)); + copy(__first, __last, __position); + _M_finish += difference_type(__n); + } + else { + size_type __len = size() + max(size(), __n); + _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 + _M_word_bit - 1)/_M_word_bit; + _M_start = iterator(__q, 0); + } + } + } + + public: + iterator begin() { return _M_start; } + const_iterator begin() const { return _M_start; } + iterator end() { return _M_finish; } + const_iterator end() const { return _M_finish; } + + 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()); + } + + size_type size() const { return size_type(end() - begin()); } + size_type max_size() const { return size_type(-1); } + size_type capacity() const { + return size_type(const_iterator(_M_end_of_storage, 0) - begin()); + } + bool empty() const { return begin() == end(); } + + reference operator[](size_type __n) + { return *(begin() + difference_type(__n)); } + const_reference operator[](size_type __n) const + { return *(begin() + difference_type(__n)); } + + void _M_range_check(size_type __n) const { + if (__n >= this->size()) + __throw_out_of_range("vector<bool>"); + } + + reference at(size_type __n) + { _M_range_check(__n); return (*this)[__n]; } + const_reference at(size_type __n) const + { _M_range_check(__n); return (*this)[__n]; } + + explicit vector(const allocator_type& __a = allocator_type()) + : _Bvector_base<_Alloc>(__a) {} + + vector(size_type __n, bool __value, + const allocator_type& __a = allocator_type()) + : _Bvector_base<_Alloc>(__a) + { + _M_initialize(__n); + fill(_M_start._M_p, _M_end_of_storage, __value ? ~0 : 0); + } + + explicit vector(size_type __n) + : _Bvector_base<_Alloc>(allocator_type()) + { + _M_initialize(__n); + fill(_M_start._M_p, _M_end_of_storage, 0); + } + + vector(const vector& __x) : _Bvector_base<_Alloc>(__x.get_allocator()) { + _M_initialize(__x.size()); + copy(__x.begin(), __x.end(), _M_start); + } + + // Check whether it's an integral type. If so, it's not an iterator. + + template <class _Integer> + void _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) { + _M_initialize(__n); + fill(_M_start._M_p, _M_end_of_storage, __x ? ~0 : 0); + } + + template <class _InputIterator> + void _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) { + _M_initialize_range(__first, __last, __iterator_category(__first)); + } + + template <class _InputIterator> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Bvector_base<_Alloc>(__a) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } + + ~vector() { } + + vector& operator=(const vector& __x) { + if (&__x == this) return *this; + if (__x.size() > capacity()) { + _M_deallocate(); + _M_initialize(__x.size()); + } + copy(__x.begin(), __x.end(), begin()); + _M_finish = begin() + difference_type(__x.size()); + return *this; + } + + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + void _M_fill_assign(size_t __n, bool __x) { + if (__n > size()) { + fill(_M_start._M_p, _M_end_of_storage, __x ? ~0 : 0); + insert(end(), __n - size(), __x); + } + else { + erase(begin() + __n, end()); + fill(_M_start._M_p, _M_end_of_storage, __x ? ~0 : 0); + } + } + + void assign(size_t __n, bool __x) { _M_fill_assign(__n, __x); } + + template <class _InputIterator> + void 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_t) __n, (bool) __val); } + + template <class _InputIter> + void _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) + { _M_assign_aux(__first, __last, __iterator_category(__first)); } + + template <class _InputIterator> + void _M_assign_aux(_InputIterator __first, _InputIterator __last, + input_iterator_tag) { + iterator __cur = begin(); + for ( ; __first != __last && __cur != end(); ++__cur, ++__first) + *__cur = *__first; + if (__first == __last) + erase(__cur, end()); + else + insert(end(), __first, __last); + } + + template <class _ForwardIterator> + void _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) { + size_type __len = distance(__first, __last); + if (__len < size()) + erase(copy(__first, __last, begin()), end()); + else { + _ForwardIterator __mid = __first; + advance(__mid, size()); + copy(__first, __mid, begin()); + insert(end(), __mid, __last); + } + } + + void reserve(size_type __n) { + if (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 + _M_word_bit - 1)/_M_word_bit; + } + } + + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(end() - 1); } + const_reference back() const { return *(end() - 1); } + void push_back(bool __x) { + if (_M_finish._M_p != _M_end_of_storage) + *_M_finish++ = __x; + else + _M_insert_aux(end(), __x); + } + void swap(vector<bool, _Alloc>& __x) { + std::swap(_M_start, __x._M_start); + std::swap(_M_finish, __x._M_finish); + std::swap(_M_end_of_storage, __x._M_end_of_storage); + } + iterator insert(iterator __position, bool __x = bool()) { + difference_type __n = __position - begin(); + if (_M_finish._M_p != _M_end_of_storage && __position == end()) + *_M_finish++ = __x; + else + _M_insert_aux(__position, __x); + return begin() + __n; + } + + // Check whether it's an integral type. If so, it's not an iterator. + + template <class _Integer> + void _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, + __true_type) { + _M_fill_insert(__pos, __n, __x); + } + + template <class _InputIterator> + void _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) { + _M_insert_range(__pos, __first, __last, __iterator_category(__first)); + } + + template <class _InputIterator> + void insert(iterator __position, + _InputIterator __first, _InputIterator __last) { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } + + void _M_fill_insert(iterator __position, size_type __n, bool __x) { + if (__n == 0) return; + if (capacity() - size() >= __n) { + copy_backward(__position, end(), _M_finish + difference_type(__n)); + fill(__position, __position + difference_type(__n), __x); + _M_finish += difference_type(__n); + } + else { + size_type __len = size() + max(size(), __n); + _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 + _M_word_bit - 1)/_M_word_bit; + _M_start = iterator(__q, 0); + } + } + + void insert(iterator __position, size_type __n, bool __x) { + _M_fill_insert(__position, __n, __x); + } + + void pop_back() { --_M_finish; } + iterator erase(iterator __position) { + if (__position + 1 != end()) + copy(__position + 1, end(), __position); + --_M_finish; + return __position; + } + iterator erase(iterator __first, iterator __last) { + _M_finish = copy(__last, end(), __first); + return __first; + } + void resize(size_type __new_size, bool __x = bool()) { + if (__new_size < size()) + erase(begin() + difference_type(__new_size), end()); + else + insert(end(), __new_size - size(), __x); + } + void flip() { + for (_Bit_type * __p = _M_start._M_p; __p != _M_end_of_storage; ++__p) + *__p = ~*__p; + } + + void clear() { erase(begin(), end()); } + }; + +// This typedef is non-standard. It is provided for backward compatibility. +typedef vector<bool, __alloc> bit_vector; + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_BVECTOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_construct.h b/contrib/libstdc++/include/bits/stl_construct.h new file mode 100644 index 0000000000000..685913888c855 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_construct.h @@ -0,0 +1,148 @@ +// nonstandard construct and destroy functions -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_construct.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_CONSTRUCT_H +#define _CPP_BITS_STL_CONSTRUCT_H 1 + +#include <bits/type_traits.h> +#include <new> + +namespace std +{ + /** + * @if maint + * Constructs an object in existing memory by invoking an allocated + * object's constructor with an initializer. + * @endif + */ + template <class _T1, class _T2> + inline void + _Construct(_T1* __p, const _T2& __value) + { new (static_cast<void*>(__p)) _T1(__value); } + + /** + * @if maint + * Constructs an object in existing memory by invoking an allocated + * object's default constructor (no initializers). + * @endif + */ + template <class _T1> + inline void + _Construct(_T1* __p) + { new (static_cast<void*>(__p)) _T1(); } + + /** + * @if maint + * Destroy a range of objects with nontrivial destructors. + * + * This is a helper function used only by _Destroy(). + * @endif + */ + template <class _ForwardIterator> + inline void + __destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type) + { for ( ; __first != __last; ++__first) _Destroy(&*__first); } + + /** + * @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(). + * @endif + */ + template <class _ForwardIterator> + inline void + __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) + { } + + /** + * @if maint + * Destroy the object pointed to by a pointer type. + * @endif + */ + template <class _Tp> + inline void + _Destroy(_Tp* __pointer) + { __pointer->~_Tp(); } + + /** + * @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. + * @endif + */ + template <class _ForwardIterator> + inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; + typedef typename __type_traits<_Value_type>::has_trivial_destructor + _Has_trivial_destructor; + + __destroy_aux(__first, __last, _Has_trivial_destructor()); + } +} // namespace std + +#endif /* _CPP_BITS_STL_CONSTRUCT_H */ + diff --git a/contrib/libstdc++/include/bits/stl_deque.h b/contrib/libstdc++/include/bits/stl_deque.h new file mode 100644 index 0000000000000..5fa8d125e7561 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_deque.h @@ -0,0 +1,1580 @@ +// deque implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_deque.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#include <bits/concept_check.h> +#include <bits/stl_iterator_base_types.h> +#include <bits/stl_iterator_base_funcs.h> + +#ifndef __GLIBCPP_INTERNAL_DEQUE_H +#define __GLIBCPP_INTERNAL_DEQUE_H + + +// Since this entire file is within namespace std, there's no reason to +// waste two spaces along the left column. Thus the leading indentation is +// slightly violated from here on. +namespace std +{ + +/** + * @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. + * @endif +*/ +inline size_t +__deque_buf_size(size_t __size) +{ return __size < 512 ? size_t(512 / __size) : size_t(1); } + + +/// A deque::iterator. +/** + * Quite a bit of intelligence here. Much of the functionality of deque is + * actually passed off to this class. A deque holds two of these internally, + * marking its valid range. Access to elements is done as offsets of either + * of those two, relying on operator overloading in this class. + * + * @if maint + * All the functions are op overloads except for _M_set_node. + * @endif +*/ +template <class _Tp, class _Ref, class _Ptr> +struct _Deque_iterator +{ + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } + + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp** _Map_pointer; + typedef _Deque_iterator _Self; + + _Tp* _M_cur; + _Tp* _M_first; + _Tp* _M_last; + _Map_pointer _M_node; + + _Deque_iterator(_Tp* __x, _Map_pointer __y) + : _M_cur(__x), _M_first(*__y), + _M_last(*__y + _S_buffer_size()), _M_node(__y) {} + _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {} + _Deque_iterator(const iterator& __x) + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) {} + + 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) { + _M_set_node(_M_node + 1); + _M_cur = _M_first; + } + return *this; + } + _Self operator++(int) { + _Self __tmp = *this; + ++*this; + return __tmp; + } + + _Self& operator--() { + if (_M_cur == _M_first) { + _M_set_node(_M_node - 1); + _M_cur = _M_last; + } + --_M_cur; + return *this; + } + _Self operator--(int) { + _Self __tmp = *this; + --*this; + return __tmp; + } + + _Self& operator+=(difference_type __n) + { + difference_type __offset = __n + (_M_cur - _M_first); + if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) + _M_cur += __n; + else { + difference_type __node_offset = + __offset > 0 ? __offset / difference_type(_S_buffer_size()) + : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; + _M_set_node(_M_node + __node_offset); + _M_cur = _M_first + + (__offset - __node_offset * difference_type(_S_buffer_size())); + } + return *this; + } + + _Self operator+(difference_type __n) const + { + _Self __tmp = *this; + return __tmp += __n; + } + + _Self& operator-=(difference_type __n) { return *this += -__n; } + + _Self operator-(difference_type __n) const { + _Self __tmp = *this; + return __tmp -= __n; + } + + 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); } + + /** @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. + * @endif + */ + void _M_set_node(_Map_pointer __new_node) { + _M_node = __new_node; + _M_first = *__new_node; + _M_last = _M_first + difference_type(_S_buffer_size()); + } +}; + +template <class _Tp, class _Ref, class _Ptr> +inline _Deque_iterator<_Tp, _Ref, _Ptr> +operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) +{ + return __x + __n; +} + + +/// @if maint Primary default version. @endif +/** + * @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. + * @endif +*/ +template <class _Tp, class _Alloc, bool __is_static> +class _Deque_alloc_base +{ +public: + typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { return _M_node_allocator; } + + _Deque_alloc_base(const allocator_type& __a) + : _M_node_allocator(__a), _M_map_allocator(__a), + _M_map(0), _M_map_size(0) + {} + +protected: + typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type + _Map_allocator_type; + + allocator_type _M_node_allocator; + _Map_allocator_type _M_map_allocator; + + _Tp* _M_allocate_node() { + return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp))); + } + void _M_deallocate_node(_Tp* __p) { + _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp))); + } + _Tp** _M_allocate_map(size_t __n) + { return _M_map_allocator.allocate(__n); } + void _M_deallocate_map(_Tp** __p, size_t __n) + { _M_map_allocator.deallocate(__p, __n); } + + _Tp** _M_map; + size_t _M_map_size; +}; + +/// @if maint Specialization for instanceless allocators. @endif +template <class _Tp, class _Alloc> +class _Deque_alloc_base<_Tp, _Alloc, true> +{ +public: + typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { return allocator_type(); } + + _Deque_alloc_base(const allocator_type&) : _M_map(0), _M_map_size(0) {} + +protected: + typedef typename _Alloc_traits<_Tp, _Alloc>::_Alloc_type _Node_alloc_type; + typedef typename _Alloc_traits<_Tp*, _Alloc>::_Alloc_type _Map_alloc_type; + + _Tp* _M_allocate_node() { + return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp))); + } + void _M_deallocate_node(_Tp* __p) { + _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp))); + } + _Tp** _M_allocate_map(size_t __n) + { return _Map_alloc_type::allocate(__n); } + void _M_deallocate_map(_Tp** __p, size_t __n) + { _Map_alloc_type::deallocate(__p, __n); } + + _Tp** _M_map; + size_t _M_map_size; +}; + + +/** + * @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. + * @endif +*/ +template <class _Tp, class _Alloc> +class _Deque_base + : public _Deque_alloc_base<_Tp,_Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> +{ +public: + typedef _Deque_alloc_base<_Tp,_Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + + _Deque_base(const allocator_type& __a, size_t __num_elements) + : _Base(__a), _M_start(), _M_finish() + { _M_initialize_map(__num_elements); } + _Deque_base(const allocator_type& __a) + : _Base(__a), _M_start(), _M_finish() {} + ~_Deque_base(); + +protected: + void _M_initialize_map(size_t); + void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish); + void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish); + enum { _S_initial_map_size = 8 }; + +protected: + iterator _M_start; + iterator _M_finish; +}; + + +template <class _Tp, class _Alloc> +_Deque_base<_Tp,_Alloc>::~_Deque_base() +{ + if (_M_map) { + _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1); + _M_deallocate_map(_M_map, _M_map_size); + } +} + +/** + * @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... + * @endif +*/ +template <class _Tp, class _Alloc> +void +_Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements) +{ + size_t __num_nodes = + __num_elements / __deque_buf_size(sizeof(_Tp)) + 1; + + _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2); + _M_map = _M_allocate_map(_M_map_size); + + _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2; + _Tp** __nfinish = __nstart + __num_nodes; + + try + { _M_create_nodes(__nstart, __nfinish); } + catch(...) + { + _M_deallocate_map(_M_map, _M_map_size); + _M_map = 0; + _M_map_size = 0; + __throw_exception_again; + } + + _M_start._M_set_node(__nstart); + _M_finish._M_set_node(__nfinish - 1); + _M_start._M_cur = _M_start._M_first; + _M_finish._M_cur = _M_finish._M_first + + __num_elements % __deque_buf_size(sizeof(_Tp)); +} + +template <class _Tp, class _Alloc> +void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish) +{ + _Tp** __cur; + try { + for (__cur = __nstart; __cur < __nfinish; ++__cur) + *__cur = _M_allocate_node(); + } + catch(...) + { + _M_destroy_nodes(__nstart, __cur); + __throw_exception_again; + } +} + +template <class _Tp, class _Alloc> +void +_Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) +{ + for (_Tp** __n = __nstart; __n < __nfinish; ++__n) + _M_deallocate_node(*__n); +} + + +/** + * @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 + * so users could control the node size. This extension turned out to violate + * the C++ standard (it can be detected using template template parameters), + * and it was removed. + * + * @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". + * (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, + * there will be one Tp element per node (i.e., an "array" of one). + * For non-huge Tp's, node size is inversely related to Tp size: the + * larger the Tp, the fewer Tp's will fit in a node. The goal here is to + * keep the total size of a node relatively small and constant over different + * Tp's, to improve allocator efficiency. + * + * **** As I write this, the nodes are /not/ allocated using the high-speed + * 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 + * 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 + * 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 + * correctly: i.node does not actually point to a node.) The member of + * 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: + * the implication of this is that i.cur is always a dereferenceable + * pointer, even if i is a past-the-end iterator. + * - Start and Finish are always nonsingular iterators. NOTE: this means that + * an empty deque must have one node, a deque with <N elements (where N is + * the node buffer size) must have one node, a deque with N through (2N-1) + * elements must have two nodes, etc. + * - For every node other than start.node and finish.node, every element in the + * node is an initialized object. If start.node == finish.node, then + * [start.cur, finish.cur) are initialized objects, and the elements outside + * 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. + * - [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 + * 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! + * + * The memory setup and layout occurs in the parent, _Base, and the iterator + * class is entirely responsible for "leaping" from one node to the next. All + * 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. + * @endif +*/ +template <class _Tp, class _Alloc = allocator<_Tp> > +class deque : protected _Deque_base<_Tp, _Alloc> +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + + typedef _Deque_base<_Tp, _Alloc> _Base; + +public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename _Base::allocator_type allocator_type; + allocator_type get_allocator() const { return _Base::get_allocator(); } + + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; + +protected: + typedef pointer* _Map_pointer; + static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } + + // Functions controlling memory layout, and nothing else. + using _Base::_M_initialize_map; + using _Base::_M_create_nodes; + using _Base::_M_destroy_nodes; + using _Base::_M_allocate_node; + using _Base::_M_deallocate_node; + using _Base::_M_allocate_map; + using _Base::_M_deallocate_map; + + /** @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. + * @endif + */ + using _Base::_M_map; + using _Base::_M_map_size; + using _Base::_M_start; + using _Base::_M_finish; + +public: // Basic accessors + iterator begin() { return _M_start; } + iterator end() { return _M_finish; } + const_iterator begin() const { return _M_start; } + const_iterator end() const { return _M_finish; } + + reverse_iterator rbegin() { return reverse_iterator(_M_finish); } + reverse_iterator rend() { return reverse_iterator(_M_start); } + const_reverse_iterator rbegin() const + { return const_reverse_iterator(_M_finish); } + const_reverse_iterator rend() const + { return const_reverse_iterator(_M_start); } + + reference operator[](size_type __n) + { return _M_start[difference_type(__n)]; } + const_reference operator[](size_type __n) const + { return _M_start[difference_type(__n)]; } + + void _M_range_check(size_type __n) const { + if (__n >= this->size()) + __throw_range_error("deque"); + } + + reference at(size_type __n) + { _M_range_check(__n); return (*this)[__n]; } + const_reference at(size_type __n) const + { _M_range_check(__n); return (*this)[__n]; } + + reference front() { return *_M_start; } + reference back() { + iterator __tmp = _M_finish; + --__tmp; + return *__tmp; + } + const_reference front() const { return *_M_start; } + const_reference back() const { + const_iterator __tmp = _M_finish; + --__tmp; + return *__tmp; + } + + size_type size() const { return _M_finish - _M_start; } + size_type max_size() const { return size_type(-1); } + bool empty() const { return _M_finish == _M_start; } + +public: // Constructor, destructor. + explicit deque(const allocator_type& __a = allocator_type()) + : _Base(__a, 0) {} + deque(const deque& __x) : _Base(__x.get_allocator(), __x.size()) + { uninitialized_copy(__x.begin(), __x.end(), _M_start); } + deque(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) : _Base(__a, __n) + { _M_fill_initialize(__value); } + + explicit + deque(size_type __n) + : _Base(allocator_type(), __n) + { _M_fill_initialize(value_type()); } + + // Check whether it's an integral type. If so, it's not an iterator. + template<class _InputIterator> + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } + + template<class _Integer> + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize_map(__n); + _M_fill_initialize(__x); + } + + template<class _InputIter> + void + _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type) + { + typedef typename iterator_traits<_InputIter>::iterator_category _IterCategory; + _M_range_initialize(__first, __last, _IterCategory()); + } + + ~deque() + { _Destroy(_M_start, _M_finish); } + + deque& operator= (const deque& __x) { + const size_type __len = size(); + if (&__x != this) { + if (__len >= __x.size()) + erase(copy(__x.begin(), __x.end(), _M_start), _M_finish); + else { + const_iterator __mid = __x.begin() + difference_type(__len); + copy(__x.begin(), __mid, _M_start); + insert(_M_finish, __mid, __x.end()); + } + } + return *this; + } + + void swap(deque& __x) { + std::swap(_M_start, __x._M_start); + std::swap(_M_finish, __x._M_finish); + std::swap(_M_map, __x._M_map); + std::swap(_M_map_size, __x._M_map_size); + } + +public: + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + void _M_fill_assign(size_type __n, const _Tp& __val) { + if (__n > size()) { + fill(begin(), end(), __val); + insert(end(), __n - size(), __val); + } + else { + erase(begin() + __n, end()); + fill(begin(), end(), __val); + } + } + + void + assign(size_type __n, const _Tp& __val) + { _M_fill_assign(__n, __val); } + + template<class _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + +private: // helper functions for assign() + + template<class _Integer> + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(static_cast<size_type>(__n), static_cast<_Tp>(__val)); } + + template<class _InputIterator> + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; + _M_assign_aux(__first, __last, _IterCategory()); + } + + template <class _InputIterator> + 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) { + size_type __len = distance(__first, __last); + if (__len > size()) { + _ForwardIterator __mid = __first; + advance(__mid, size()); + copy(__first, __mid, begin()); + insert(end(), __mid, __last); + } + else + erase(copy(__first, __last, begin()), end()); + } + +public: // push_* and pop_* + + void + push_back(const value_type& __t) + { + if (_M_finish._M_cur != _M_finish._M_last - 1) { + _Construct(_M_finish._M_cur, __t); + ++_M_finish._M_cur; + } + else + _M_push_back_aux(__t); + } + + void + push_back() + { + if (_M_finish._M_cur != _M_finish._M_last - 1) { + _Construct(_M_finish._M_cur); + ++_M_finish._M_cur; + } + else + _M_push_back_aux(); + } + + void + push_front(const value_type& __t) + { + if (_M_start._M_cur != _M_start._M_first) { + _Construct(_M_start._M_cur - 1, __t); + --_M_start._M_cur; + } + else + _M_push_front_aux(__t); + } + + void + push_front() + { + if (_M_start._M_cur != _M_start._M_first) { + _Construct(_M_start._M_cur - 1); + --_M_start._M_cur; + } + else + _M_push_front_aux(); + } + + + void + pop_back() + { + if (_M_finish._M_cur != _M_finish._M_first) { + --_M_finish._M_cur; + _Destroy(_M_finish._M_cur); + } + else + _M_pop_back_aux(); + } + + void + pop_front() + { + if (_M_start._M_cur != _M_start._M_last - 1) { + _Destroy(_M_start._M_cur); + ++_M_start._M_cur; + } + else + _M_pop_front_aux(); + } + +public: // Insert + + iterator + insert(iterator position, const value_type& __x) + { + if (position._M_cur == _M_start._M_cur) { + push_front(__x); + return _M_start; + } + else if (position._M_cur == _M_finish._M_cur) { + push_back(__x); + iterator __tmp = _M_finish; + --__tmp; + return __tmp; + } + else { + return _M_insert_aux(position, __x); + } + } + + iterator + insert(iterator __position) + { return insert(__position, value_type()); } + + void + insert(iterator __pos, size_type __n, const value_type& __x) + { _M_fill_insert(__pos, __n, __x); } + + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + + // Check whether it's an integral type. If so, it's not an iterator. + template<class _InputIterator> + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__pos, __first, __last, _Integral()); + } + + template<class _Integer> + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type) + { _M_fill_insert(__pos, static_cast<size_type>(__n), static_cast<value_type>(__x)); } + + template<class _InputIterator> + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; + insert(__pos, __first, __last, _IterCategory()); + } + + void resize(size_type __new_size, const value_type& __x) { + const size_type __len = size(); + if (__new_size < __len) + erase(_M_start + __new_size, _M_finish); + else + insert(_M_finish, __new_size - __len, __x); + } + + void resize(size_type new_size) { resize(new_size, value_type()); } + +public: // Erase + iterator erase(iterator __pos) { + iterator __next = __pos; + ++__next; + size_type __index = __pos - _M_start; + if (__index < (size() >> 1)) { + copy_backward(_M_start, __pos, __next); + pop_front(); + } + else { + copy(__next, _M_finish, __pos); + pop_back(); + } + return _M_start + __index; + } + + iterator erase(iterator __first, iterator __last); + void clear(); + +protected: // Internal construction/destruction + + void _M_fill_initialize(const value_type& __value); + + template <class _InputIterator> + void _M_range_initialize(_InputIterator __first, _InputIterator __last, + input_iterator_tag); + + template <class _ForwardIterator> + void _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); + +protected: // Internal push_* and pop_* + + void _M_push_back_aux(const value_type&); + void _M_push_back_aux(); + void _M_push_front_aux(const value_type&); + void _M_push_front_aux(); + void _M_pop_back_aux(); + void _M_pop_front_aux(); + +protected: // Internal insert functions + + template <class _InputIterator> + void insert(iterator __pos, _InputIterator __first, _InputIterator __last, + input_iterator_tag); + + template <class _ForwardIterator> + void insert(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); + + iterator _M_insert_aux(iterator __pos, const value_type& __x); + iterator _M_insert_aux(iterator __pos); + void _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); + + template <class _ForwardIterator> + void _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n); + + iterator _M_reserve_elements_at_front(size_type __n) { + size_type __vacancies = _M_start._M_cur - _M_start._M_first; + if (__n > __vacancies) + _M_new_elements_at_front(__n - __vacancies); + return _M_start - difference_type(__n); + } + + iterator _M_reserve_elements_at_back(size_type __n) { + size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1; + if (__n > __vacancies) + _M_new_elements_at_back(__n - __vacancies); + return _M_finish + difference_type(__n); + } + + void _M_new_elements_at_front(size_type __new_elements); + void _M_new_elements_at_back(size_type __new_elements); + +protected: // Allocation of _M_map and nodes + + // Makes sure the _M_map has space for new nodes. Does not actually + // add the nodes. Can invalidate _M_map pointers. (And consequently, + // deque iterators.) + + void _M_reserve_map_at_back (size_type __nodes_to_add = 1) { + if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map)) + _M_reallocate_map(__nodes_to_add, false); + } + + void _M_reserve_map_at_front (size_type __nodes_to_add = 1) { + if (__nodes_to_add > size_type(_M_start._M_node - _M_map)) + _M_reallocate_map(__nodes_to_add, true); + } + + void _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); +}; + +// Non-inline member functions + +template <class _Tp, class _Alloc> +template <class _InputIter> +void deque<_Tp, _Alloc> + ::_M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag) +{ + iterator __cur = begin(); + for ( ; __first != __last && __cur != end(); ++__cur, ++__first) + *__cur = *__first; + if (__first == __last) + erase(__cur, end()); + else + insert(end(), __first, __last); +} + +template <class _Tp, class _Alloc> +void deque<_Tp, _Alloc>::_M_fill_insert(iterator __pos, + size_type __n, const value_type& __x) +{ + if (__pos._M_cur == _M_start._M_cur) { + iterator __new_start = _M_reserve_elements_at_front(__n); + try { + uninitialized_fill(__new_start, _M_start, __x); + _M_start = __new_start; + } + catch(...) + { + _M_destroy_nodes(__new_start._M_node, _M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == _M_finish._M_cur) { + iterator __new_finish = _M_reserve_elements_at_back(__n); + try { + uninitialized_fill(_M_finish, __new_finish, __x); + _M_finish = __new_finish; + } + catch(...) + { + _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __n, __x); +} + +template <class _Tp, class _Alloc> +typename deque<_Tp,_Alloc>::iterator +deque<_Tp,_Alloc>::erase(iterator __first, iterator __last) +{ + if (__first == _M_start && __last == _M_finish) { + clear(); + return _M_finish; + } + else { + difference_type __n = __last - __first; + difference_type __elems_before = __first - _M_start; + if (static_cast<size_type>(__elems_before) < (size() - __n) / 2) { + copy_backward(_M_start, __first, __last); + iterator __new_start = _M_start + __n; + _Destroy(_M_start, __new_start); + _M_destroy_nodes(_M_start._M_node, __new_start._M_node); + _M_start = __new_start; + } + else { + copy(__last, _M_finish, __first); + iterator __new_finish = _M_finish - __n; + _Destroy(__new_finish, _M_finish); + _M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1); + _M_finish = __new_finish; + } + return _M_start + __elems_before; + } +} + +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::clear() +{ + for (_Map_pointer __node = _M_start._M_node + 1; + __node < _M_finish._M_node; + ++__node) { + _Destroy(*__node, *__node + _S_buffer_size()); + _M_deallocate_node(*__node); + } + + if (_M_start._M_node != _M_finish._M_node) { + _Destroy(_M_start._M_cur, _M_start._M_last); + _Destroy(_M_finish._M_first, _M_finish._M_cur); + _M_deallocate_node(_M_finish._M_first); + } + else + _Destroy(_M_start._M_cur, _M_finish._M_cur); + + _M_finish = _M_start; +} + +/** + * @if maint + * @brief Fills the deque with copies of value. + * @param value Initial value. + * @return Nothing. + * @pre _M_start and _M_finish have already been initialized, but none of the + * deque's elements have yet been constructed. + * + * This function is called only when the user provides an explicit size (with + * or without an explicit exemplar value). + * @endif +*/ +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_fill_initialize(const value_type& __value) +{ + _Map_pointer __cur; + try { + for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur) + uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value); + uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value); + } + catch(...) + { + _Destroy(_M_start, iterator(*__cur, __cur)); + __throw_exception_again; + } +} + +/** @{ + * @if maint + * @brief Fills the deque with whatever is in [first,last). + * @param first An input iterator. + * @param last An input iterator. + * @return Nothing. + * + * 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. + * @endif +*/ +template <class _Tp, class _Alloc> template <class _InputIterator> +void deque<_Tp,_Alloc>::_M_range_initialize(_InputIterator __first, + _InputIterator __last, + input_iterator_tag) +{ + _M_initialize_map(0); + try { + for ( ; __first != __last; ++__first) + push_back(*__first); + } + catch(...) + { + clear(); + __throw_exception_again; + } +} + +template <class _Tp, class _Alloc> template <class _ForwardIterator> +void deque<_Tp,_Alloc>::_M_range_initialize(_ForwardIterator __first, + _ForwardIterator __last, + forward_iterator_tag) +{ + size_type __n = distance(__first, __last); + _M_initialize_map(__n); + + _Map_pointer __cur_node; + try { + for (__cur_node = _M_start._M_node; + __cur_node < _M_finish._M_node; + ++__cur_node) { + _ForwardIterator __mid = __first; + advance(__mid, _S_buffer_size()); + uninitialized_copy(__first, __mid, *__cur_node); + __first = __mid; + } + uninitialized_copy(__first, __last, _M_finish._M_first); + } + catch(...) + { + _Destroy(_M_start, iterator(*__cur_node, __cur_node)); + __throw_exception_again; + } +} +/** @} */ + +// Called only if _M_finish._M_cur == _M_finish._M_last - 1. +template <class _Tp, class _Alloc> +void +deque<_Tp,_Alloc>::_M_push_back_aux(const value_type& __t) +{ + value_type __t_copy = __t; + _M_reserve_map_at_back(); + *(_M_finish._M_node + 1) = _M_allocate_node(); + try { + _Construct(_M_finish._M_cur, __t_copy); + _M_finish._M_set_node(_M_finish._M_node + 1); + _M_finish._M_cur = _M_finish._M_first; + } + catch(...) + { + _M_deallocate_node(*(_M_finish._M_node + 1)); + __throw_exception_again; + } +} + +// Called only if _M_finish._M_cur == _M_finish._M_last - 1. +template <class _Tp, class _Alloc> +void +deque<_Tp,_Alloc>::_M_push_back_aux() +{ + _M_reserve_map_at_back(); + *(_M_finish._M_node + 1) = _M_allocate_node(); + try { + _Construct(_M_finish._M_cur); + _M_finish._M_set_node(_M_finish._M_node + 1); + _M_finish._M_cur = _M_finish._M_first; + } + catch(...) + { + _M_deallocate_node(*(_M_finish._M_node + 1)); + __throw_exception_again; + } +} + +// Called only if _M_start._M_cur == _M_start._M_first. +template <class _Tp, class _Alloc> +void +deque<_Tp,_Alloc>::_M_push_front_aux(const value_type& __t) +{ + value_type __t_copy = __t; + _M_reserve_map_at_front(); + *(_M_start._M_node - 1) = _M_allocate_node(); + try { + _M_start._M_set_node(_M_start._M_node - 1); + _M_start._M_cur = _M_start._M_last - 1; + _Construct(_M_start._M_cur, __t_copy); + } + catch(...) + { + ++_M_start; + _M_deallocate_node(*(_M_start._M_node - 1)); + __throw_exception_again; + } +} + +// Called only if _M_start._M_cur == _M_start._M_first. +template <class _Tp, class _Alloc> +void +deque<_Tp,_Alloc>::_M_push_front_aux() +{ + _M_reserve_map_at_front(); + *(_M_start._M_node - 1) = _M_allocate_node(); + try { + _M_start._M_set_node(_M_start._M_node - 1); + _M_start._M_cur = _M_start._M_last - 1; + _Construct(_M_start._M_cur); + } + catch(...) + { + ++_M_start; + _M_deallocate_node(*(_M_start._M_node - 1)); + __throw_exception_again; + } +} + +// Called only if _M_finish._M_cur == _M_finish._M_first. +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_pop_back_aux() +{ + _M_deallocate_node(_M_finish._M_first); + _M_finish._M_set_node(_M_finish._M_node - 1); + _M_finish._M_cur = _M_finish._M_last - 1; + _Destroy(_M_finish._M_cur); +} + +// Called only if _M_start._M_cur == _M_start._M_last - 1. Note that +// if the deque has at least one element (a precondition for this member +// function), and if _M_start._M_cur == _M_start._M_last, then the deque +// must have at least two nodes. +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_pop_front_aux() +{ + _Destroy(_M_start._M_cur); + _M_deallocate_node(_M_start._M_first); + _M_start._M_set_node(_M_start._M_node + 1); + _M_start._M_cur = _M_start._M_first; +} + +template <class _Tp, class _Alloc> template <class _InputIterator> +void deque<_Tp,_Alloc>::insert(iterator __pos, + _InputIterator __first, _InputIterator __last, + input_iterator_tag) +{ + copy(__first, __last, inserter(*this, __pos)); +} + +template <class _Tp, class _Alloc> template <class _ForwardIterator> +void +deque<_Tp,_Alloc>::insert(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) { + size_type __n = distance(__first, __last); + if (__pos._M_cur == _M_start._M_cur) { + iterator __new_start = _M_reserve_elements_at_front(__n); + try { + uninitialized_copy(__first, __last, __new_start); + _M_start = __new_start; + } + catch(...) + { + _M_destroy_nodes(__new_start._M_node, _M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == _M_finish._M_cur) { + iterator __new_finish = _M_reserve_elements_at_back(__n); + try { + uninitialized_copy(__first, __last, _M_finish); + _M_finish = __new_finish; + } + catch(...) + { + _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __first, __last, __n); +} + +template <class _Tp, class _Alloc> +typename deque<_Tp, _Alloc>::iterator +deque<_Tp,_Alloc>::_M_insert_aux(iterator __pos, const value_type& __x) +{ + difference_type __index = __pos - _M_start; + value_type __x_copy = __x; + if (static_cast<size_type>(__index) < size() / 2) { + push_front(front()); + iterator __front1 = _M_start; + ++__front1; + iterator __front2 = __front1; + ++__front2; + __pos = _M_start + __index; + iterator __pos1 = __pos; + ++__pos1; + copy(__front2, __pos1, __front1); + } + else { + push_back(back()); + iterator __back1 = _M_finish; + --__back1; + iterator __back2 = __back1; + --__back2; + __pos = _M_start + __index; + copy_backward(__pos, __back2, __back1); + } + *__pos = __x_copy; + return __pos; +} + +template <class _Tp, class _Alloc> +typename deque<_Tp,_Alloc>::iterator +deque<_Tp,_Alloc>::_M_insert_aux(iterator __pos) +{ + difference_type __index = __pos - _M_start; + if (static_cast<size_type>(__index) < size() / 2) { + push_front(front()); + iterator __front1 = _M_start; + ++__front1; + iterator __front2 = __front1; + ++__front2; + __pos = _M_start + __index; + iterator __pos1 = __pos; + ++__pos1; + copy(__front2, __pos1, __front1); + } + else { + push_back(back()); + iterator __back1 = _M_finish; + --__back1; + iterator __back2 = __back1; + --__back2; + __pos = _M_start + __index; + copy_backward(__pos, __back2, __back1); + } + *__pos = value_type(); + return __pos; +} + +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_insert_aux(iterator __pos, + size_type __n, + const value_type& __x) +{ + const difference_type __elems_before = __pos - _M_start; + size_type __length = this->size(); + value_type __x_copy = __x; + if (__elems_before < difference_type(__length / 2)) { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = _M_start; + __pos = _M_start + __elems_before; + try { + if (__elems_before >= difference_type(__n)) { + iterator __start_n = _M_start + difference_type(__n); + uninitialized_copy(_M_start, __start_n, __new_start); + _M_start = __new_start; + copy(__start_n, __pos, __old_start); + fill(__pos - difference_type(__n), __pos, __x_copy); + } + else { + __uninitialized_copy_fill(_M_start, __pos, __new_start, + _M_start, __x_copy); + _M_start = __new_start; + fill(__old_start, __pos, __x_copy); + } + } + catch(...) + { + _M_destroy_nodes(__new_start._M_node, _M_start._M_node); + __throw_exception_again; + } + } + else { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = _M_finish; + const difference_type __elems_after = + difference_type(__length) - __elems_before; + __pos = _M_finish - __elems_after; + try { + if (__elems_after > difference_type(__n)) { + iterator __finish_n = _M_finish - difference_type(__n); + uninitialized_copy(__finish_n, _M_finish, _M_finish); + _M_finish = __new_finish; + copy_backward(__pos, __finish_n, __old_finish); + fill(__pos, __pos + difference_type(__n), __x_copy); + } + else { + __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n), + __x_copy, __pos, _M_finish); + _M_finish = __new_finish; + fill(__pos, __old_finish, __x_copy); + } + } + catch(...) + { + _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + __throw_exception_again; + } + } +} + +template <class _Tp, class _Alloc> template <class _ForwardIterator> +void deque<_Tp,_Alloc>::_M_insert_aux(iterator __pos, + _ForwardIterator __first, + _ForwardIterator __last, + size_type __n) +{ + const difference_type __elemsbefore = __pos - _M_start; + size_type __length = size(); + if (static_cast<size_type>(__elemsbefore) < __length / 2) { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = _M_start; + __pos = _M_start + __elemsbefore; + try { + if (__elemsbefore >= difference_type(__n)) { + iterator __start_n = _M_start + difference_type(__n); + uninitialized_copy(_M_start, __start_n, __new_start); + _M_start = __new_start; + copy(__start_n, __pos, __old_start); + copy(__first, __last, __pos - difference_type(__n)); + } + else { + _ForwardIterator __mid = __first; + advance(__mid, difference_type(__n) - __elemsbefore); + __uninitialized_copy_copy(_M_start, __pos, __first, __mid, + __new_start); + _M_start = __new_start; + copy(__mid, __last, __old_start); + } + } + catch(...) + { + _M_destroy_nodes(__new_start._M_node, _M_start._M_node); + __throw_exception_again; + } + } + else { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = _M_finish; + const difference_type __elemsafter = + difference_type(__length) - __elemsbefore; + __pos = _M_finish - __elemsafter; + try { + if (__elemsafter > difference_type(__n)) { + iterator __finish_n = _M_finish - difference_type(__n); + uninitialized_copy(__finish_n, _M_finish, _M_finish); + _M_finish = __new_finish; + copy_backward(__pos, __finish_n, __old_finish); + copy(__first, __last, __pos); + } + else { + _ForwardIterator __mid = __first; + advance(__mid, __elemsafter); + __uninitialized_copy_copy(__mid, __last, __pos, _M_finish, _M_finish); + _M_finish = __new_finish; + copy(__first, __mid, __pos); + } + } + catch(...) + { + _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + __throw_exception_again; + } + } +} + +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_new_elements_at_front(size_type __new_elems) +{ + size_type __new_nodes + = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); + _M_reserve_map_at_front(__new_nodes); + size_type __i; + try { + for (__i = 1; __i <= __new_nodes; ++__i) + *(_M_start._M_node - __i) = _M_allocate_node(); + } + catch(...) { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(_M_start._M_node - __j)); + __throw_exception_again; + } +} + +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_new_elements_at_back(size_type __new_elems) +{ + size_type __new_nodes + = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); + _M_reserve_map_at_back(__new_nodes); + size_type __i; + try { + for (__i = 1; __i <= __new_nodes; ++__i) + *(_M_finish._M_node + __i) = _M_allocate_node(); + } + catch(...) { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(_M_finish._M_node + __j)); + __throw_exception_again; + } +} + +template <class _Tp, class _Alloc> +void deque<_Tp,_Alloc>::_M_reallocate_map(size_type __nodes_to_add, + bool __add_at_front) +{ + size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1; + size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; + + _Map_pointer __new_nstart; + if (_M_map_size > 2 * __new_num_nodes) { + __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + if (__new_nstart < _M_start._M_node) + copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); + else + copy_backward(_M_start._M_node, _M_finish._M_node + 1, + __new_nstart + __old_num_nodes); + } + else { + size_type __new_map_size = + _M_map_size + max(_M_map_size, __nodes_to_add) + 2; + + _Map_pointer __new_map = _M_allocate_map(__new_map_size); + __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); + _M_deallocate_map(_M_map, _M_map_size); + + _M_map = __new_map; + _M_map_size = __new_map_size; + } + + _M_start._M_set_node(__new_nstart); + _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); +} + + +// Nonmember functions. + +template <class _Tp, class _Alloc> +inline bool operator==(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return __x.size() == __y.size() && + equal(__x.begin(), __x.end(), __y.begin()); +} + +template <class _Tp, class _Alloc> +inline bool operator<(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); +} + +template <class _Tp, class _Alloc> +inline bool operator!=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__x == __y); +} + +template <class _Tp, class _Alloc> +inline bool operator>(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return __y < __x; +} + +template <class _Tp, class _Alloc> +inline bool operator<=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__y < __x); +} +template <class _Tp, class _Alloc> +inline bool operator>=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__x < __y); +} + +template <class _Tp, class _Alloc> +inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) { + __x.swap(__y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_DEQUE_H */ + diff --git a/contrib/libstdc++/include/bits/stl_function.h b/contrib/libstdc++/include/bits/stl_function.h new file mode 100644 index 0000000000000..9ea975d4a8dc8 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_function.h @@ -0,0 +1,736 @@ +// Functor implementations -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_function.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_FUNCTION_H +#define __GLIBCPP_INTERNAL_FUNCTION_H + +namespace std +{ +// 20.3.1 base classes +/** @defgroup s20_3_1_base Functor Base Classes + * Function objects, or @e functors, are objects with an @c operator() + * defined and accessible. They can be passed as arguments to algorithm + * templates and used in place of a function pointer. Not only is the + * resulting expressiveness of the library increased, but the generated + * code can be more efficient than what you might write by hand. When we + * refer to "functors," then, generally we include function pointers in + * the description as well. + * + * Often, functors are only created as temporaries passed to algorithm + * calls, rather than being created as named variables. + * + * Two examples taken from the standard itself follow. To perform a + * by-element addition of two vectors @c a and @c b containing @c double, + * and put the result in @c a, use + * \code + * transform (a.begin(), a.end(), b.begin(), a.begin(), plus<double>()); + * \endcode + * To negate every element in @c a, use + * \code + * transform(a.begin(), a.end(), a.begin(), negate<double>()); + * \endcode + * The addition and negation functions will be inlined directly. + * + * The standard functiors are derived from structs named @c unary_function + * and @c binary_function. These two classes contain nothing but typedefs, + * to aid in generic (template) programming. If you write your own + * functors, you might consider doing the same. + * + * @{ +*/ +/** + * This is one of the @link s20_3_1_base functor base classes@endlink. +*/ +template <class _Arg, class _Result> +struct unary_function { + typedef _Arg argument_type; ///< @c argument_type is the type of the argument (no surprises here) + typedef _Result result_type; ///< @c result_type is the return type +}; + +/** + * This is one of the @link s20_3_1_base functor base classes@endlink. +*/ +template <class _Arg1, class _Arg2, class _Result> +struct binary_function { + typedef _Arg1 first_argument_type; ///< the type of the first argument (no surprises here) + typedef _Arg2 second_argument_type; ///< the type of the second argument + typedef _Result result_type; ///< type of the return type +}; +/** @} */ + +// 20.3.2 arithmetic +/** @defgroup s20_3_2_arithmetic Arithmetic Classes + * Because basic math often needs to be done during an algorithm, the library + * provides functors for those operations. See the documentation for + * @link s20_3_1_base the base classes@endlink for examples of their use. + * + * @{ +*/ +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct plus : public binary_function<_Tp,_Tp,_Tp> { + _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x + __y; } +}; + +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct minus : public binary_function<_Tp,_Tp,_Tp> { + _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x - __y; } +}; + +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct multiplies : public binary_function<_Tp,_Tp,_Tp> { + _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x * __y; } +}; + +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct divides : public binary_function<_Tp,_Tp,_Tp> { + _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x / __y; } +}; + +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct modulus : public binary_function<_Tp,_Tp,_Tp> +{ + _Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x % __y; } +}; + +/// One of the @link s20_3_2_arithmetic math functors@endlink. +template <class _Tp> +struct negate : public unary_function<_Tp,_Tp> +{ + _Tp operator()(const _Tp& __x) const { return -__x; } +}; +/** @} */ + +// 20.3.3 comparisons +/** @defgroup s20_3_3_comparisons Comparison Classes + * The library provides six wrapper functors for all the basic comparisons + * in C++, like @c <. + * + * @{ +*/ +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct equal_to : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x == __y; } +}; + +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct not_equal_to : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; } +}; + +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct greater : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; } +}; + +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct less : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; } +}; + +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct greater_equal : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x >= __y; } +}; + +/// One of the @link s20_3_3_comparisons comparison functors@endlink. +template <class _Tp> +struct less_equal : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x <= __y; } +}; +/** @} */ + +// 20.3.4 logical operations +/** @defgroup s20_3_4_logical Boolean Operations Classes + * Here are wrapper functors for Boolean operations: @c &&, @c ||, and @c !. + * + * @{ +*/ +/// One of the @link s20_3_4_logical Boolean operations functors@endlink. +template <class _Tp> +struct logical_and : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x && __y; } +}; + +/// One of the @link s20_3_4_logical Boolean operations functors@endlink. +template <class _Tp> +struct logical_or : public binary_function<_Tp,_Tp,bool> +{ + bool operator()(const _Tp& __x, const _Tp& __y) const { return __x || __y; } +}; + +/// One of the @link s20_3_4_logical Boolean operations functors@endlink. +template <class _Tp> +struct logical_not : public unary_function<_Tp,bool> +{ + bool operator()(const _Tp& __x) const { return !__x; } +}; +/** @} */ + +// 20.3.5 negators +/** @defgroup s20_3_5_negators Negators + * The functions @c not1 and @c not2 each take a predicate functor + * and return an instance of @c unary_negate or + * @c binary_negate, respectively. These classes are functors whose + * @c operator() performs the stored predicate function and then returns + * the negation of the result. + * + * For example, given a vector of integers and a trivial predicate, + * \code + * struct IntGreaterThanThree + * : public std::unary_function<int, bool> + * { + * bool operator() (int x) { return x > 3; } + * }; + * + * std::find_if (v.begin(), v.end(), not1(IntGreaterThanThree())); + * \endcode + * The call to @c find_if will locate the first index (i) of @c v for which + * "!(v[i] > 3)" is true. + * + * The not1/unary_negate combination works on predicates taking a single + * argument. The not2/binary_negate combination works on predicates which + * take two arguments. + * + * @{ +*/ +/// One of the @link s20_3_5_negators negation functors@endlink. +template <class _Predicate> +class unary_negate + : public unary_function<typename _Predicate::argument_type, bool> { +protected: + _Predicate _M_pred; +public: + explicit unary_negate(const _Predicate& __x) : _M_pred(__x) {} + bool operator()(const typename _Predicate::argument_type& __x) const { + return !_M_pred(__x); + } +}; + +/// One of the @link s20_3_5_negators negation functors@endlink. +template <class _Predicate> +inline unary_negate<_Predicate> +not1(const _Predicate& __pred) +{ + return unary_negate<_Predicate>(__pred); +} + +/// One of the @link s20_3_5_negators negation functors@endlink. +template <class _Predicate> +class binary_negate + : public binary_function<typename _Predicate::first_argument_type, + typename _Predicate::second_argument_type, + bool> { +protected: + _Predicate _M_pred; +public: + explicit binary_negate(const _Predicate& __x) : _M_pred(__x) {} + bool operator()(const typename _Predicate::first_argument_type& __x, + const typename _Predicate::second_argument_type& __y) const + { + return !_M_pred(__x, __y); + } +}; + +/// One of the @link s20_3_5_negators negation functors@endlink. +template <class _Predicate> +inline binary_negate<_Predicate> +not2(const _Predicate& __pred) +{ + return binary_negate<_Predicate>(__pred); +} +/** @} */ + +// 20.3.6 binders +/** @defgroup s20_3_6_binder Binder Classes + * Binders turn functions/functors with two arguments into functors with + * a single argument, storing an argument to be applied later. For + * example, an variable @c B of type @c binder1st is constructed from a functor + * @c f and an argument @c x. Later, B's @c operator() is called with a + * single argument @c y. The return value is the value of @c f(x,y). + * @c B can be "called" with various arguments (y1, y2, ...) and will in + * turn call @c f(x,y1), @c f(x,y2), ... + * + * The function @c bind1st is provided to save some typing. It takes the + * function and an argument as parameters, and returns an instance of + * @c binder1st. + * + * The type @c binder2nd and its creator function @c bind2nd do the same + * thing, but the stored argument is passed as the second parameter instead + * of the first, e.g., @c bind2nd(std::minus<float>,1.3) will create a + * functor whose @c operator() accepts a floating-point number, subtracts + * 1.3 from it, and returns the result. (If @c bind1st had been used, + * the functor would perform "1.3 - x" instead. + * + * Creator-wrapper functions like @c bind1st are intended to be used in + * calling algorithms. Their return values will be temporary objects. + * (The goal is to not require you to type names like + * @c std::binder1st<std::plus<int>> for declaring a variable to hold the + * return value from @c bind1st(std::plus<int>,5). + * + * These become more useful when combined with the composition functions. + * + * @{ +*/ +/// One of the @link s20_3_6_binder binder functors@endlink. +template <class _Operation> +class binder1st + : public unary_function<typename _Operation::second_argument_type, + typename _Operation::result_type> { +protected: + _Operation op; + typename _Operation::first_argument_type value; +public: + binder1st(const _Operation& __x, + const typename _Operation::first_argument_type& __y) + : op(__x), value(__y) {} + typename _Operation::result_type + operator()(const typename _Operation::second_argument_type& __x) const { + return op(value, __x); + } +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::second_argument_type& __x) const { + return op(value, __x); + } +#endif +}; + +/// One of the @link s20_3_6_binder binder functors@endlink. +template <class _Operation, class _Tp> +inline binder1st<_Operation> +bind1st(const _Operation& __fn, const _Tp& __x) +{ + typedef typename _Operation::first_argument_type _Arg1_type; + return binder1st<_Operation>(__fn, _Arg1_type(__x)); +} + +/// One of the @link s20_3_6_binder binder functors@endlink. +template <class _Operation> +class binder2nd + : public unary_function<typename _Operation::first_argument_type, + typename _Operation::result_type> { +protected: + _Operation op; + typename _Operation::second_argument_type value; +public: + binder2nd(const _Operation& __x, + const typename _Operation::second_argument_type& __y) + : op(__x), value(__y) {} + typename _Operation::result_type + operator()(const typename _Operation::first_argument_type& __x) const { + return op(__x, value); + } +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::first_argument_type& __x) const { + return op(__x, value); + } +#endif +}; + +/// One of the @link s20_3_6_binder binder functors@endlink. +template <class _Operation, class _Tp> +inline binder2nd<_Operation> +bind2nd(const _Operation& __fn, const _Tp& __x) +{ + typedef typename _Operation::second_argument_type _Arg2_type; + return binder2nd<_Operation>(__fn, _Arg2_type(__x)); +} +/** @} */ + +// 20.3.7 adaptors pointers functions +/** @defgroup s20_3_7_adaptors Adaptors for pointers to functions + * The advantage of function objects over pointers to functions is that + * the objects in the standard library declare nested typedefs describing + * their argument and result types with uniform names (e.g., @c result_type + * from the base classes @c unary_function and @c binary_function). + * Sometimes those typedefs are required, not just optional. + * + * Adaptors are provided to turn pointers to unary (single-argument) and + * binary (double-argument) functions into function objects. The long-winded + * functor @c pointer_to_unary_function is constructed with a function + * pointer @c f, and its @c operator() called with argument @c x returns + * @c f(x). The functor @c pointer_to_binary_function does the same thing, + * but with a double-argument @c f and @c operator(). + * + * The function @c ptr_fun takes a pointer-to-function @c f and constructs + * an instance of the appropriate functor. + * + * @{ +*/ +/// One of the @link s20_3_7_adaptors adaptors for function pointers@endlink. +template <class _Arg, class _Result> +class pointer_to_unary_function : public unary_function<_Arg, _Result> { +protected: + _Result (*_M_ptr)(_Arg); +public: + pointer_to_unary_function() {} + explicit pointer_to_unary_function(_Result (*__x)(_Arg)) : _M_ptr(__x) {} + _Result operator()(_Arg __x) const { return _M_ptr(__x); } +}; + +/// One of the @link s20_3_7_adaptors adaptors for function pointers@endlink. +template <class _Arg, class _Result> +inline pointer_to_unary_function<_Arg, _Result> ptr_fun(_Result (*__x)(_Arg)) +{ + return pointer_to_unary_function<_Arg, _Result>(__x); +} + +/// One of the @link s20_3_7_adaptors adaptors for function pointers@endlink. +template <class _Arg1, class _Arg2, class _Result> +class pointer_to_binary_function : + public binary_function<_Arg1,_Arg2,_Result> { +protected: + _Result (*_M_ptr)(_Arg1, _Arg2); +public: + pointer_to_binary_function() {} + explicit pointer_to_binary_function(_Result (*__x)(_Arg1, _Arg2)) + : _M_ptr(__x) {} + _Result operator()(_Arg1 __x, _Arg2 __y) const { + return _M_ptr(__x, __y); + } +}; + +/// One of the @link s20_3_7_adaptors adaptors for function pointers@endlink. +template <class _Arg1, class _Arg2, class _Result> +inline pointer_to_binary_function<_Arg1,_Arg2,_Result> +ptr_fun(_Result (*__x)(_Arg1, _Arg2)) { + return pointer_to_binary_function<_Arg1,_Arg2,_Result>(__x); +} +/** @} */ + +template <class _Tp> +struct _Identity : public unary_function<_Tp,_Tp> { + _Tp& operator()(_Tp& __x) const { return __x; } + const _Tp& operator()(const _Tp& __x) const { return __x; } +}; + +template <class _Pair> +struct _Select1st : public unary_function<_Pair, typename _Pair::first_type> { + typename _Pair::first_type& operator()(_Pair& __x) const { + return __x.first; + } + const typename _Pair::first_type& operator()(const _Pair& __x) const { + return __x.first; + } +}; + +template <class _Pair> +struct _Select2nd : public unary_function<_Pair, typename _Pair::second_type> +{ + typename _Pair::second_type& operator()(_Pair& __x) const { + return __x.second; + } + const typename _Pair::second_type& operator()(const _Pair& __x) const { + return __x.second; + } +}; + +// 20.3.8 adaptors pointers members +/** @defgroup s20_3_8_memadaptors Adaptors for pointers to members + * There are a total of 16 = 2^4 function objects in this family. + * (1) Member functions taking no arguments vs member functions taking + * one argument. + * (2) Call through pointer vs call through reference. + * (3) Member function with void return type vs member function with + * non-void return type. + * (4) Const vs non-const member function. + * + * Note that choice (3) is nothing more than a workaround: according + * to the draft, compilers should handle void and non-void the same way. + * This feature is not yet widely implemented, though. You can only use + * member functions returning void if your compiler supports partial + * specialization. + * + * All of this complexity is in the function objects themselves. You can + * ignore it by using the helper function mem_fun and mem_fun_ref, + * which create whichever type of adaptor is appropriate. + * + * @{ +*/ +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp> +class mem_fun_t : public unary_function<_Tp*,_Ret> { +public: + explicit mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {} + _Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); } +private: + _Ret (_Tp::*_M_f)(); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp> +class const_mem_fun_t : public unary_function<const _Tp*,_Ret> { +public: + explicit const_mem_fun_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {} + _Ret operator()(const _Tp* __p) const { return (__p->*_M_f)(); } +private: + _Ret (_Tp::*_M_f)() const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp> +class mem_fun_ref_t : public unary_function<_Tp,_Ret> { +public: + explicit mem_fun_ref_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {} + _Ret operator()(_Tp& __r) const { return (__r.*_M_f)(); } +private: + _Ret (_Tp::*_M_f)(); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp> +class const_mem_fun_ref_t : public unary_function<_Tp,_Ret> { +public: + explicit const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) : _M_f(__pf) {} + _Ret operator()(const _Tp& __r) const { return (__r.*_M_f)(); } +private: + _Ret (_Tp::*_M_f)() const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp, class _Arg> +class mem_fun1_t : public binary_function<_Tp*,_Arg,_Ret> { +public: + explicit mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) : _M_f(__pf) {} + _Ret operator()(_Tp* __p, _Arg __x) const { return (__p->*_M_f)(__x); } +private: + _Ret (_Tp::*_M_f)(_Arg); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp, class _Arg> +class const_mem_fun1_t : public binary_function<const _Tp*,_Arg,_Ret> { +public: + explicit const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const) : _M_f(__pf) {} + _Ret operator()(const _Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } +private: + _Ret (_Tp::*_M_f)(_Arg) const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp, class _Arg> +class mem_fun1_ref_t : public binary_function<_Tp,_Arg,_Ret> { +public: + explicit mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg)) : _M_f(__pf) {} + _Ret operator()(_Tp& __r, _Arg __x) const { return (__r.*_M_f)(__x); } +private: + _Ret (_Tp::*_M_f)(_Arg); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Ret, class _Tp, class _Arg> +class const_mem_fun1_ref_t : public binary_function<_Tp,_Arg,_Ret> { +public: + explicit const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const) : _M_f(__pf) {} + _Ret operator()(const _Tp& __r, _Arg __x) const { return (__r.*_M_f)(__x); } +private: + _Ret (_Tp::*_M_f)(_Arg) const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp> +class mem_fun_t<void, _Tp> : public unary_function<_Tp*,void> { +public: + explicit mem_fun_t(void (_Tp::*__pf)()) : _M_f(__pf) {} + void operator()(_Tp* __p) const { (__p->*_M_f)(); } +private: + void (_Tp::*_M_f)(); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp> +class const_mem_fun_t<void, _Tp> : public unary_function<const _Tp*,void> { +public: + explicit const_mem_fun_t(void (_Tp::*__pf)() const) : _M_f(__pf) {} + void operator()(const _Tp* __p) const { (__p->*_M_f)(); } +private: + void (_Tp::*_M_f)() const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp> +class mem_fun_ref_t<void, _Tp> : public unary_function<_Tp,void> { +public: + explicit mem_fun_ref_t(void (_Tp::*__pf)()) : _M_f(__pf) {} + void operator()(_Tp& __r) const { (__r.*_M_f)(); } +private: + void (_Tp::*_M_f)(); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp> +class const_mem_fun_ref_t<void, _Tp> : public unary_function<_Tp,void> { +public: + explicit const_mem_fun_ref_t(void (_Tp::*__pf)() const) : _M_f(__pf) {} + void operator()(const _Tp& __r) const { (__r.*_M_f)(); } +private: + void (_Tp::*_M_f)() const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp, class _Arg> +class mem_fun1_t<void, _Tp, _Arg> : public binary_function<_Tp*,_Arg,void> { +public: + explicit mem_fun1_t(void (_Tp::*__pf)(_Arg)) : _M_f(__pf) {} + void operator()(_Tp* __p, _Arg __x) const { (__p->*_M_f)(__x); } +private: + void (_Tp::*_M_f)(_Arg); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp, class _Arg> +class const_mem_fun1_t<void, _Tp, _Arg> + : public binary_function<const _Tp*,_Arg,void> { +public: + explicit const_mem_fun1_t(void (_Tp::*__pf)(_Arg) const) : _M_f(__pf) {} + void operator()(const _Tp* __p, _Arg __x) const { (__p->*_M_f)(__x); } +private: + void (_Tp::*_M_f)(_Arg) const; +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp, class _Arg> +class mem_fun1_ref_t<void, _Tp, _Arg> + : public binary_function<_Tp,_Arg,void> { +public: + explicit mem_fun1_ref_t(void (_Tp::*__pf)(_Arg)) : _M_f(__pf) {} + void operator()(_Tp& __r, _Arg __x) const { (__r.*_M_f)(__x); } +private: + void (_Tp::*_M_f)(_Arg); +}; + +/// One of the @link s20_3_8_memadaptors adaptors for member pointers@endlink. +template <class _Tp, class _Arg> +class const_mem_fun1_ref_t<void, _Tp, _Arg> + : public binary_function<_Tp,_Arg,void> { +public: + explicit const_mem_fun1_ref_t(void (_Tp::*__pf)(_Arg) const) : _M_f(__pf) {} + void operator()(const _Tp& __r, _Arg __x) const { (__r.*_M_f)(__x); } +private: + void (_Tp::*_M_f)(_Arg) const; +}; + + +// Mem_fun adaptor helper functions. There are only two: +// mem_fun and mem_fun_ref. + +template <class _Ret, class _Tp> +inline mem_fun_t<_Ret,_Tp> mem_fun(_Ret (_Tp::*__f)()) + { return mem_fun_t<_Ret,_Tp>(__f); } + +template <class _Ret, class _Tp> +inline const_mem_fun_t<_Ret,_Tp> mem_fun(_Ret (_Tp::*__f)() const) + { return const_mem_fun_t<_Ret,_Tp>(__f); } + +template <class _Ret, class _Tp> +inline mem_fun_ref_t<_Ret,_Tp> mem_fun_ref(_Ret (_Tp::*__f)()) + { return mem_fun_ref_t<_Ret,_Tp>(__f); } + +template <class _Ret, class _Tp> +inline const_mem_fun_ref_t<_Ret,_Tp> mem_fun_ref(_Ret (_Tp::*__f)() const) + { return const_mem_fun_ref_t<_Ret,_Tp>(__f); } + +template <class _Ret, class _Tp, class _Arg> +inline mem_fun1_t<_Ret,_Tp,_Arg> mem_fun(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_t<_Ret,_Tp,_Arg>(__f); } + +template <class _Ret, class _Tp, class _Arg> +inline const_mem_fun1_t<_Ret,_Tp,_Arg> mem_fun(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_t<_Ret,_Tp,_Arg>(__f); } + +template <class _Ret, class _Tp, class _Arg> +inline mem_fun1_ref_t<_Ret,_Tp,_Arg> mem_fun_ref(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_ref_t<_Ret,_Tp,_Arg>(__f); } + +template <class _Ret, class _Tp, class _Arg> +inline const_mem_fun1_ref_t<_Ret,_Tp,_Arg> +mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_ref_t<_Ret,_Tp,_Arg>(__f); } + +/** @} */ + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_FUNCTION_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_heap.h b/contrib/libstdc++/include/bits/stl_heap.h new file mode 100644 index 0000000000000..c19195aad39a4 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_heap.h @@ -0,0 +1,308 @@ +// Heap implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_heap.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_HEAP_H +#define _CPP_BITS_STL_HEAP_H 1 + +namespace std +{ + + // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap. + + template<typename _RandomAccessIterator, typename _Distance, typename _Tp> + void + __push_heap(_RandomAccessIterator __first, + _Distance __holeIndex, _Distance __topIndex, _Tp __value) + { + _Distance __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex && *(__first + __parent) < __value) { + *(__first + __holeIndex) = *(__first + __parent); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = __value; + } + + template<typename _RandomAccessIterator> + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + __push_heap(__first, _DistanceType((__last - __first) - 1), _DistanceType(0), + _ValueType(*(__last - 1))); + } + + template<typename _RandomAccessIterator, typename _Distance, typename _Tp, + typename _Compare> + void + __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __topIndex, _Tp __value, _Compare __comp) + { + _Distance __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex && __comp(*(__first + __parent), __value)) { + *(__first + __holeIndex) = *(__first + __parent); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = __value; + } + + template<typename _RandomAccessIterator, typename _Compare> + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + __push_heap(__first, _DistanceType((__last - __first) - 1), _DistanceType(0), + _ValueType(*(__last - 1)), __comp); + } + + template<typename _RandomAccessIterator, typename _Distance, typename _Tp> + void + __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __len, _Tp __value) + { + _Distance __topIndex = __holeIndex; + _Distance __secondChild = 2 * __holeIndex + 2; + while (__secondChild < __len) { + if (*(__first + __secondChild) < *(__first + (__secondChild - 1))) + __secondChild--; + *(__first + __holeIndex) = *(__first + __secondChild); + __holeIndex = __secondChild; + __secondChild = 2 * (__secondChild + 1); + } + if (__secondChild == __len) { + *(__first + __holeIndex) = *(__first + (__secondChild - 1)); + __holeIndex = __secondChild - 1; + } + __push_heap(__first, __holeIndex, __topIndex, __value); + } + + template<typename _RandomAccessIterator, typename _Tp> + inline void + __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _RandomAccessIterator __result, _Tp __value) + { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type _Distance; + *__result = *__first; + __adjust_heap(__first, _Distance(0), _Distance(__last - __first), __value); + } + + template<typename _RandomAccessIterator> + inline void + pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + __pop_heap(__first, __last - 1, __last - 1, _ValueType(*(__last - 1))); + } + + template<typename _RandomAccessIterator, typename _Distance, + typename _Tp, typename _Compare> + void + __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __len, _Tp __value, _Compare __comp) + { + _Distance __topIndex = __holeIndex; + _Distance __secondChild = 2 * __holeIndex + 2; + while (__secondChild < __len) { + if (__comp(*(__first + __secondChild), *(__first + (__secondChild - 1)))) + __secondChild--; + *(__first + __holeIndex) = *(__first + __secondChild); + __holeIndex = __secondChild; + __secondChild = 2 * (__secondChild + 1); + } + if (__secondChild == __len) { + *(__first + __holeIndex) = *(__first + (__secondChild - 1)); + __holeIndex = __secondChild - 1; + } + __push_heap(__first, __holeIndex, __topIndex, __value, __comp); + } + + template<typename _RandomAccessIterator, typename _Tp, typename _Compare> + inline void + __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _RandomAccessIterator __result, _Tp __value, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type _Distance; + *__result = *__first; + __adjust_heap(__first, _Distance(0), _Distance(__last - __first), + __value, __comp); + } + + template<typename _RandomAccessIterator, typename _Compare> + inline void + pop_heap(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; + __pop_heap(__first, __last - 1, __last - 1, _ValueType(*(__last - 1)), __comp); + } + + template<typename _RandomAccessIterator> + void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcpp_function_requires(_LessThanComparableConcept<_ValueType>) + + if (__last - __first < 2) return; + _DistanceType __len = __last - __first; + _DistanceType __parent = (__len - 2)/2; + + while (true) { + __adjust_heap(__first, __parent, __len, _ValueType(*(__first + __parent))); + if (__parent == 0) return; + __parent--; + } + } + + template<typename _RandomAccessIterator, typename _Compare> + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + if (__last - __first < 2) return; + _DistanceType __len = __last - __first; + _DistanceType __parent = (__len - 2)/2; + + while (true) { + __adjust_heap(__first, __parent, __len, + _ValueType(*(__first + __parent)), __comp); + if (__parent == 0) return; + __parent--; + } + } + + template<typename _RandomAccessIterator> + void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcpp_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + + while (__last - __first > 1) + pop_heap(__first, __last--); + } + + template<typename _RandomAccessIterator, typename _Compare> + void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcpp_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + while (__last - __first > 1) + pop_heap(__first, __last--, __comp); + } + +} // namespace std + +#endif /* _CPP_BITS_STL_HEAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_iterator.h b/contrib/libstdc++/include/bits/stl_iterator.h new file mode 100644 index 0000000000000..d8a6d8ca374ae --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_iterator.h @@ -0,0 +1,733 @@ +// Iterators -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_iterator.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + * + * This file implements reverse_iterator, back_insert_iterator, + * front_insert_iterator, insert_iterator, __normal_iterator, and their + * supporting functions and overloaded operators. + */ + +#ifndef __GLIBCPP_INTERNAL_ITERATOR_H +#define __GLIBCPP_INTERNAL_ITERATOR_H + +namespace std +{ + // 24.4.1 Reverse iterators + /** + * "Bidirectional and random access iterators have corresponding reverse + * %iterator adaptors that iterate through the data structure in the + * opposite direction. They have the same signatures as the corresponding + * iterators. The fundamental relation between a reverse %iterator and its + * corresponding %iterator @c i is established by the identity: + * @code + * &*(reverse_iterator(i)) == &*(i - 1) + * @endcode + * + * This mapping is dictated by the fact that while there is always a + * pointer past the end of an array, there might not be a valid pointer + * before the beginning of an array." [24.4.1]/1,2 + * + * Reverse iterators can be tricky and surprising at first. Their + * semantics make sense, however, and the trickiness is a side effect of + * the requirement that the iterators must be safe. + */ + template<typename _Iterator> + class reverse_iterator + : public iterator<typename iterator_traits<_Iterator>::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator current; + + public: + typedef _Iterator iterator_type; + typedef typename iterator_traits<_Iterator>::difference_type + difference_type; + typedef typename iterator_traits<_Iterator>::reference reference; + typedef typename iterator_traits<_Iterator>::pointer pointer; + + public: + /** + * The default constructor gives an undefined state to this %iterator. + */ + reverse_iterator() { } + + /** + * This %iterator will move in the opposite direction that @p x does. + */ + explicit + reverse_iterator(iterator_type __x) : current(__x) { } + + /** + * The copy constructor is normal. + */ + reverse_iterator(const reverse_iterator& __x) + : current(__x.current) { } + + /** + * A reverse_iterator across other types can be copied in the normal + * fashion. + */ + template<typename _Iter> + reverse_iterator(const reverse_iterator<_Iter>& __x) + : current(__x.base()) { } + + /** + * @return @c current, the %iterator used for underlying work. + */ + iterator_type + base() const { return current; } + + /** + * @return TODO + * + * @doctodo + */ + reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + + /** + * @return TODO + * + * @doctodo + */ + pointer + operator->() const { return &(operator*()); } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator& + operator++() + { + --current; + return *this; + } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator& + operator--() + { + ++current; + return *this; + } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + + /** + * @return TODO + * + * @doctodo + */ + reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + + /** + * @return TODO + * + * @doctodo + */ + reference + operator[](difference_type __n) const { return *(*this + __n); } + }; + + //@{ + /** + * @param x A %reverse_iterator. + * @param y A %reverse_iterator. + * @return A simple bool. + * + * Reverse iterators forward many operations to their underlying base() + * iterators. Others are implemented in terms of one another. + * + */ + template<typename _Iterator> + inline bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template<typename _Iterator> + inline bool + operator<(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() < __x.base(); } + + template<typename _Iterator> + inline bool + operator!=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template<typename _Iterator> + inline bool + operator>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y < __x; } + + template<typename _Iterator> + inline bool + operator<=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template<typename _Iterator> + inline bool + operator>=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x < __y); } + + template<typename _Iterator> + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } + + template<typename _Iterator> + inline reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } + //@} + + // 24.4.2.2.1 back_insert_iterator + /** + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator appends it to the container using + * push_back. + * + * Tip: Using the back_inserter function to create these iterators can + * save typing. + */ + template<typename _Container> + class back_insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + + /// The only way to create this %iterator is with a container. + explicit + back_insert_iterator(_Container& __x) : container(&__x) { } + + /** + * @param value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container<T>. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a "position" in the + * container (you can think of the position as being permanently at + * the end, if you like). Assigning a value to the %iterator will + * always append the value to the end of the container. + */ + back_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_back(__value); + return *this; + } + + /// Simply returns *this. + back_insert_iterator& + operator*() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + back_insert_iterator& + operator++() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + back_insert_iterator + operator++(int) { return *this; } + }; + + /** + * @param x A container of arbitrary type. + * @return An instance of back_insert_iterator working on @p x. + * + * This wrapper function helps in creating back_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template<typename _Container> + inline back_insert_iterator<_Container> + back_inserter(_Container& __x) + { return back_insert_iterator<_Container>(__x); } + + /** + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator prepends it to the container using + * push_front. + * + * Tip: Using the front_inserter function to create these iterators can + * save typing. + */ + template<typename _Container> + class front_insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + + /// The only way to create this %iterator is with a container. + explicit front_insert_iterator(_Container& __x) : container(&__x) { } + + /** + * @param value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container<T>. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a "position" in the + * container (you can think of the position as being permanently at + * the front, if you like). Assigning a value to the %iterator will + * always prepend the value to the front of the container. + */ + front_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_front(__value); + return *this; + } + + /// Simply returns *this. + front_insert_iterator& + operator*() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + front_insert_iterator& + operator++() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + front_insert_iterator + operator++(int) { return *this; } + }; + + /** + * @param x A container of arbitrary type. + * @return An instance of front_insert_iterator working on @p x. + * + * This wrapper function helps in creating front_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template<typename _Container> + inline front_insert_iterator<_Container> + front_inserter(_Container& __x) + { return front_insert_iterator<_Container>(__x); } + + /** + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator inserts it in the container at the + * %iterator's position, rather than overwriting the value at that + * position. + * + * (Sequences will actually insert a @e copy of the value before the + * %iterator's position.) + * + * Tip: Using the inserter function to create these iterators can + * save typing. + */ + template<typename _Container> + class insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + typename _Container::iterator iter; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + + /** + * The only way to create this %iterator is with a container and an + * initial position (a normal %iterator into the container). + */ + insert_iterator(_Container& __x, typename _Container::iterator __i) + : container(&__x), iter(__i) {} + + /** + * @param value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container<T>. + * @return This %iterator, for chained operations. + * + * This kind of %iterator maintains its own position in the + * container. Assigning a value to the %iterator will insert the + * value into the container at the place before the %iterator. + * + * The position is maintained such that subsequent assignments will + * insert values immediately after one another. For example, + * @code + * // vector v contains A and Z + * + * insert_iterator i (v, ++v.begin()); + * i = 1; + * i = 2; + * i = 3; + * + * // vector v contains A, 1, 2, 3, and Z + * @endcode + */ + insert_iterator& + operator=(const typename _Container::const_reference __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } + + /// Simply returns *this. + insert_iterator& + operator*() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + insert_iterator& + operator++() { return *this; } + + /// Simply returns *this. (This %iterator does not "move".) + insert_iterator& + operator++(int) { return *this; } + }; + + /** + * @param x A container of arbitrary type. + * @return An instance of insert_iterator working on @p x. + * + * This wrapper function helps in creating insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template<typename _Container, typename _Iterator> + inline insert_iterator<_Container> + inserter(_Container& __x, _Iterator __i) + { + 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 + // not a class, e.g. a pointer, into an iterator that is a class. + // 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, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator _M_current; + + public: + typedef typename iterator_traits<_Iterator>::difference_type + difference_type; + typedef typename iterator_traits<_Iterator>::reference reference; + typedef typename iterator_traits<_Iterator>::pointer pointer; + + __normal_iterator() : _M_current(_Iterator()) { } + + explicit + __normal_iterator(const _Iterator& __i) : _M_current(__i) { } + + // Allow iterator to const_iterator conversion + template<typename _Iter> + inline __normal_iterator(const __normal_iterator<_Iter, _Container>& __i) + : _M_current(__i.base()) { } + + // Forward iterator requirements + reference + operator*() const { return *_M_current; } + + pointer + operator->() const { return _M_current; } + + __normal_iterator& + operator++() { ++_M_current; return *this; } + + __normal_iterator + operator++(int) { return __normal_iterator(_M_current++); } + + // Bidirectional iterator requirements + __normal_iterator& + operator--() { --_M_current; return *this; } + + __normal_iterator + operator--(int) { return __normal_iterator(_M_current--); } + + // Random access iterator requirements + reference + operator[](const difference_type& __n) const + { return _M_current[__n]; } + + __normal_iterator& + operator+=(const difference_type& __n) + { _M_current += __n; return *this; } + + __normal_iterator + operator+(const difference_type& __n) const + { return __normal_iterator(_M_current + __n); } + + __normal_iterator& + operator-=(const difference_type& __n) + { _M_current -= __n; return *this; } + + __normal_iterator + 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 + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + 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.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> + inline bool + operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + 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.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.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.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 _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 __gnu_cxx + +#endif + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_iterator_base_funcs.h b/contrib/libstdc++/include/bits/stl_iterator_base_funcs.h new file mode 100644 index 0000000000000..8389f5e7d03a7 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_iterator_base_funcs.h @@ -0,0 +1,179 @@ +// Functions used by iterators -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_iterator_base_funcs.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + * + * This file contains all of the general iterator-related utility + * functions, such as distance() and advance(). + */ + +#ifndef __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H +#define __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H + +#pragma GCC system_header +#include <bits/concept_check.h> + +// Since this entire file is within namespace std, there's no reason to +// waste two spaces along the left column. Thus the leading indentation is +// slightly violated from here on. +namespace std +{ +template<typename _InputIterator> + inline typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, input_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) { + ++__first; ++__n; + } + return __n; + } + +template<typename _RandomAccessIterator> + inline typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) + return __last - __first; + } + +/** + * @brief A generalization of pointer arithmetic. + * @param first An input iterator. + * @param last An input iterator. + * @return The distance between them. + * + * Returns @c n such that first + n == last. This requires that @p last + * must be reachable from @p first. Note that @c n may be negative. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. +*/ +template<typename _InputIterator> + inline typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + // concept requirements -- taken care of in __distance + return __distance(__first, __last, __iterator_category(__first)); + } + +template<typename _InputIter, typename _Distance> + inline void + __advance(_InputIter& __i, _Distance __n, input_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) + while (__n--) ++__i; + } + +template<typename _BidirectionalIterator, typename _Distance> + inline void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>) + + if (__n > 0) + while (__n--) ++__i; + else + while (__n++) --__i; + } + +template<typename _RandomAccessIterator, typename _Distance> + inline void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) + __i += __n; + } + +/** + * @brief A generalization of pointer arithmetic. + * @param i An input iterator. + * @param n The "delta" by which to change @p i. + * @return Nothing. + * + * This increments @p i by @p n. For bidirectional and random access + * iterators, @p n may be negative, in which case @p i is decremented. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. +*/ +template<typename _InputIterator, typename _Distance> + inline void + advance(_InputIterator& __i, _Distance __n) + { + // concept requirements -- taken care of in __advance + __advance(__i, __n, __iterator_category(__i)); + } + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H */ + + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_iterator_base_types.h b/contrib/libstdc++/include/bits/stl_iterator_base_types.h new file mode 100644 index 0000000000000..5dff8fc3f447e --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_iterator_base_types.h @@ -0,0 +1,162 @@ +// Types used in iterator implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_iterator_base_types.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + * + * This file contains all of the general iterator-related utility types, + * such as iterator_traits and struct iterator. + */ + +#ifndef __GLIBCPP_INTERNAL_ITERATOR_BASE_TYPES_H +#define __GLIBCPP_INTERNAL_ITERATOR_BASE_TYPES_H + +#pragma GCC system_header + +namespace std +{ + /** + * @defgroup iterator_tags Iterator Tags + * These are empty types, used to distinguish different iterators. The + * distinction is not made by what they contain, but simply by what they + * are. Different underlying algorithms can then be used based on the + * different operations supporetd by different iterator types. + * @{ + */ + /// Marking input iterators. + struct input_iterator_tag {}; + /// Marking output iterators. + struct output_iterator_tag {}; + /// Forward iterators support a superset of input iterator operations. + struct forward_iterator_tag : public input_iterator_tag {}; + /// Bidirectional iterators support a superset of forward iterator operations. + struct bidirectional_iterator_tag : public forward_iterator_tag {}; + /// Random-access iterators support a superset of bidirectional iterator operations. + struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + //@} + + + /** + * This class does nothing but define nested typedefs. %Iterator classes + * can inherit from this class to save some work. The typedefs are then + * used in specializations and overloading. + * + * In particular, there are no default implementations of requirements + * such as @c operator++ and the like. (How could there be?) + */ + template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t, + typename _Pointer = _Tp*, typename _Reference = _Tp&> + struct iterator { + /// One of the @link iterator_tags tag types@endlink. + typedef _Category iterator_category; + /// The type "pointed to" by the iterator. + typedef _Tp value_type; + /// Distance between iterators is represented as this type. + typedef _Distance difference_type; + /// This type represents a pointer-to-value_type. + typedef _Pointer pointer; + /// This type represents a reference-to-value_type. + typedef _Reference reference; + }; + + /** + * This class does nothing but define nested typedefs. The general + * version simply "forwards" the nested typedefs from the Iterator + * argument. Specialized versions for pointers and pointers-to-const + * provide tighter, more correct semantics. + */ + template<typename _Iterator> + struct iterator_traits { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; + + template<typename _Tp> + struct iterator_traits<_Tp*> { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + + template<typename _Tp> + struct iterator_traits<const _Tp*> { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; + + /** + * @if maint + * This function is not a part of the C++ standard but is syntactic + * sugar for internal library use only. + * @endif + */ + template<typename _Iter> + inline typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_TYPES_H */ + diff --git a/contrib/libstdc++/include/bits/stl_list.h b/contrib/libstdc++/include/bits/stl_list.h new file mode 100644 index 0000000000000..3d470b1f25f0d --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_list.h @@ -0,0 +1,989 @@ +// List implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_list.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_LIST_H +#define __GLIBCPP_INTERNAL_LIST_H + +#include <bits/concept_check.h> + +namespace std +{ + + struct _List_node_base + { + _List_node_base* _M_next; + _List_node_base* _M_prev; + }; + + template<typename _Tp> + struct _List_node : public _List_node_base + { + _Tp _M_data; + }; + + struct _List_iterator_base + { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef bidirectional_iterator_tag iterator_category; + + _List_node_base* _M_node; + + _List_iterator_base(_List_node_base* __x) + : _M_node(__x) + { } + + _List_iterator_base() + { } + + void + _M_incr() + { _M_node = _M_node->_M_next; } + + void + _M_decr() + { _M_node = _M_node->_M_prev; } + + bool + operator==(const _List_iterator_base& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _List_iterator_base& __x) const + { return _M_node != __x._M_node; } + }; + + template<typename _Tp, typename _Ref, typename _Ptr> + struct _List_iterator : public _List_iterator_base + { + typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + typedef _List_iterator<_Tp,_Ref,_Ptr> _Self; + + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef _List_node<_Tp> _Node; + + _List_iterator(_Node* __x) + : _List_iterator_base(__x) + { } + + _List_iterator() + { } + + _List_iterator(const iterator& __x) + : _List_iterator_base(__x._M_node) + { } + + reference + operator*() const + { return ((_Node*) _M_node)->_M_data; } + + pointer + operator->() const + { return &(operator*()); } + + _Self& + operator++() + { + this->_M_incr(); + return *this; + } + + _Self + operator++(int) + { + _Self __tmp = *this; + this->_M_incr(); + return __tmp; + } + + _Self& + operator--() + { + this->_M_decr(); + return *this; + } + + _Self + operator--(int) + { + _Self __tmp = *this; + this->_M_decr(); + return __tmp; + } + }; + + + // Base class that encapsulates details of allocators. Three cases: + // an ordinary standard-conforming allocator, a standard-conforming + // allocator with no non-static data, and an SGI-style allocator. + // This complexity is necessary only because we're worrying about backward + // compatibility and because we want to avoid wasting storage on an + // allocator instance if it isn't necessary. + + + // Base for general standard-conforming allocators. + template<typename _Tp, typename _Allocator, bool _IsStatic> + class _List_alloc_base + { + public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + + allocator_type + get_allocator() const + { return _Node_allocator; } + + _List_alloc_base(const allocator_type& __a) + : _Node_allocator(__a) + { } + + protected: + _List_node<_Tp>* + _M_get_node() + { return _Node_allocator.allocate(1); } + + void + _M_put_node(_List_node<_Tp>* __p) + { _Node_allocator.deallocate(__p, 1); } + + protected: + typename _Alloc_traits<_List_node<_Tp>, _Allocator>::allocator_type + _Node_allocator; + + _List_node<_Tp>* _M_node; + }; + + // Specialization for instanceless allocators. + + template<typename _Tp, typename _Allocator> + class _List_alloc_base<_Tp, _Allocator, true> + { + public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + + allocator_type + get_allocator() const + { return allocator_type(); } + + _List_alloc_base(const allocator_type&) + { } + + protected: + typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type + _Alloc_type; + + _List_node<_Tp>* + _M_get_node() + { return _Alloc_type::allocate(1); } + + void + _M_put_node(_List_node<_Tp>* __p) + { _Alloc_type::deallocate(__p, 1); } + + protected: + _List_node<_Tp>* _M_node; + }; + + template<typename _Tp, typename _Alloc> + class _List_base + : public _List_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + { + public: + typedef _List_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + + _List_base(const allocator_type& __a) + : _Base(__a) + { + _M_node = _M_get_node(); + _M_node->_M_next = _M_node; + _M_node->_M_prev = _M_node; + } + + ~_List_base() + { + clear(); + _M_put_node(_M_node); + } + + 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> + { + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + + typedef _List_base<_Tp, _Alloc> _Base; + protected: + typedef void* _Void_pointer; + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef _List_node<_Tp> _Node; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef typename _Base::allocator_type allocator_type; + + typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; + + protected: + using _Base::_M_node; + using _Base::_M_put_node; + using _Base::_M_get_node; + + protected: + _Node* + _M_create_node(const _Tp& __x) + { + _Node* __p = _M_get_node(); + try { + _Construct(&__p->_M_data, __x); + } + catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; + } + + _Node* + _M_create_node() + { + _Node* __p = _M_get_node(); + try { + _Construct(&__p->_M_data); + } + catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; + } + + public: + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + + explicit + list(const allocator_type& __a = allocator_type()) + : _Base(__a) + { } + + iterator + begin() + { return static_cast<_Node*>(_M_node->_M_next); } + + const_iterator + begin() const + { return static_cast<_Node*>(_M_node->_M_next); } + + iterator + end() + { return _M_node; } + + const_iterator + end() const + { return _M_node; } + + 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->_M_next == _M_node; } + + size_type + size() const + { return distance(begin(), end()); } + + size_type + max_size() const + { return size_type(-1); } + + reference + front() + { return *begin(); } + + const_reference + front() const + { return *begin(); } + + reference + back() + { return *(--end()); } + + const_reference + back() const + { return *(--end()); } + + void + swap(list<_Tp, _Alloc>& __x) + { std::swap(_M_node, __x._M_node); } + + iterator + insert(iterator __position, const _Tp& __x) + { + _Node* __tmp = _M_create_node(__x); + __tmp->_M_next = __position._M_node; + __tmp->_M_prev = __position._M_node->_M_prev; + __position._M_node->_M_prev->_M_next = __tmp; + __position._M_node->_M_prev = __tmp; + return __tmp; + } + + iterator + insert(iterator __position) + { return insert(__position, _Tp()); } + + // Check whether it's an integral type. If so, it's not an iterator. + template<typename _Integer> + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type) + { _M_fill_insert(__pos, (size_type) __n, (_Tp) __x); } + + template<typename _InputIterator> + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type); + + template<typename _InputIterator> + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__pos, __first, __last, _Integral()); + } + + void + insert(iterator __pos, size_type __n, const _Tp& __x) + { _M_fill_insert(__pos, __n, __x); } + + void + _M_fill_insert(iterator __pos, size_type __n, const _Tp& __x); + + void + push_front(const _Tp& __x) + { insert(begin(), __x); } + + void + push_front() + { insert(begin()); } + + void + push_back(const _Tp& __x) + { insert(end(), __x); } + + void + push_back() + { insert(end()); } + + iterator + erase(iterator __position) + { + _List_node_base* __next_node = __position._M_node->_M_next; + _List_node_base* __prev_node = __position._M_node->_M_prev; + _Node* __n = static_cast<_Node*>(__position._M_node); + __prev_node->_M_next = __next_node; + __next_node->_M_prev = __prev_node; + _Destroy(&__n->_M_data); + _M_put_node(__n); + return iterator(static_cast<_Node*>(__next_node)); + } + + iterator + erase(iterator __first, iterator __last); + + void + clear() + { _Base::clear(); } + + void + resize(size_type __new_size, const _Tp& __x); + + void + resize(size_type __new_size) + { this->resize(__new_size, _Tp()); } + + void + pop_front() + { erase(begin()); } + + void + pop_back() + { + iterator __tmp = end(); + erase(--__tmp); + } + + list(size_type __n, const _Tp& __value, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { insert(begin(), __n, __value); } + + explicit + list(size_type __n) + : _Base(allocator_type()) + { insert(begin(), __n, _Tp()); } + + // We don't need any dispatching tricks here, because insert does all of + // that anyway. + template<typename _InputIterator> + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { insert(begin(), __first, __last); } + + list(const list<_Tp, _Alloc>& __x) + : _Base(__x.get_allocator()) + { insert(begin(), __x.begin(), __x.end()); } + + ~list() + { } + + list<_Tp, _Alloc>& + operator=(const list<_Tp, _Alloc>& __x); + + public: + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + void + assign(size_type __n, const _Tp& __val) + { _M_fill_assign(__n, __val); } + + void + _M_fill_assign(size_type __n, const _Tp& __val); + + template<typename _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + + template<typename _Integer> + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign((size_type) __n, (_Tp) __val); } + + template<typename _InputIterator> + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type); + + protected: + void + _M_transfer(iterator __position, iterator __first, iterator __last) + { + if (__position != __last) { + // Remove [first, last) from its old position. + __last._M_node->_M_prev->_M_next = __position._M_node; + __first._M_node->_M_prev->_M_next = __last._M_node; + __position._M_node->_M_prev->_M_next = __first._M_node; + + // Splice [first, last) into its new position. + _List_node_base* __tmp = __position._M_node->_M_prev; + __position._M_node->_M_prev = __last._M_node->_M_prev; + __last._M_node->_M_prev = __first._M_node->_M_prev; + __first._M_node->_M_prev = __tmp; + } + } + + public: + void + splice(iterator __position, list& __x) + { + if (!__x.empty()) + this->_M_transfer(__position, __x.begin(), __x.end()); + } + + void + splice(iterator __position, list&, iterator __i) + { + iterator __j = __i; + ++__j; + if (__position == __i || __position == __j) return; + this->_M_transfer(__position, __i, __j); + } + + void + splice(iterator __position, list&, iterator __first, iterator __last) + { + if (__first != __last) + this->_M_transfer(__position, __first, __last); + } + + void + remove(const _Tp& __value); + + void + unique(); + + void + merge(list& __x); + + void + reverse(); + + void + sort(); + + template<typename _Predicate> + void + remove_if(_Predicate); + + template<typename _BinaryPredicate> + void + unique(_BinaryPredicate); + + template<typename _StrictWeakOrdering> + void + merge(list&, _StrictWeakOrdering); + + template<typename _StrictWeakOrdering> + void + sort(_StrictWeakOrdering); + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { + typedef typename list<_Tp,_Alloc>::const_iterator const_iterator; + const_iterator __end1 = __x.end(); + const_iterator __end2 = __y.end(); + + const_iterator __i1 = __x.begin(); + const_iterator __i2 = __y.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { + return lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); + } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__x == __y); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return __y < __x; } + + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__y < __x); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__x < __y); } + + template<typename _Tp, typename _Alloc> + inline void + swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) + { __x.swap(__y); } + + // move these to stl_list.tcc + + template<typename _Tp, typename _Alloc> + void _List_base<_Tp,_Alloc>:: + clear() + { + _List_node<_Tp>* __cur = static_cast<_List_node<_Tp>*>(_M_node->_M_next); + while (__cur != _M_node) { + _List_node<_Tp>* __tmp = __cur; + __cur = static_cast<_List_node<_Tp>*>(__cur->_M_next); + _Destroy(&__tmp->_M_data); + _M_put_node(__tmp); + } + _M_node->_M_next = _M_node; + _M_node->_M_prev = _M_node; + } + + template<typename _Tp, typename _Alloc> + template <typename _InputIter> + void list<_Tp, _Alloc>:: + _M_insert_dispatch(iterator __position, _InputIter __first, _InputIter __last, + __false_type) + { + for ( ; __first != __last; ++__first) + insert(__position, *__first); + + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + _M_fill_insert(iterator __position, size_type __n, const _Tp& __x) + { + for ( ; __n > 0; --__n) + insert(__position, __x); + } + + template<typename _Tp, typename _Alloc> + typename list<_Tp,_Alloc>::iterator list<_Tp, _Alloc>:: + erase(iterator __first, iterator __last) + { + while (__first != __last) + erase(__first++); + return __last; + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + resize(size_type __new_size, const _Tp& __x) + { + iterator __i = begin(); + size_type __len = 0; + for ( ; __i != end() && __len < __new_size; ++__i, ++__len) + ; + if (__len == __new_size) + erase(__i, end()); + else // __i == end() + insert(end(), __new_size - __len, __x); + } + + template<typename _Tp, typename _Alloc> + list<_Tp, _Alloc>& list<_Tp, _Alloc>:: + operator=(const list<_Tp, _Alloc>& __x) + { + if (this != &__x) { + iterator __first1 = begin(); + iterator __last1 = end(); + const_iterator __first2 = __x.begin(); + const_iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + *__first1++ = *__first2++; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + return *this; + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + _M_fill_assign(size_type __n, const _Tp& __val) { + iterator __i = begin(); + for ( ; __i != end() && __n > 0; ++__i, --__n) + *__i = __val; + if (__n > 0) + insert(end(), __n, __val); + else + erase(__i, end()); + } + + template<typename _Tp, typename _Alloc> + template <typename _InputIter> + void list<_Tp, _Alloc>:: + _M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type) + { + iterator __first1 = begin(); + iterator __last1 = end(); + for ( ; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + remove(const _Tp& __value) + { + iterator __first = begin(); + iterator __last = end(); + while (__first != __last) { + iterator __next = __first; + ++__next; + if (*__first == __value) erase(__first); + __first = __next; + } + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + unique() + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) return; + iterator __next = __first; + while (++__next != __last) { + if (*__first == *__next) + erase(__next); + else + __first = __next; + __next = __first; + } + } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + merge(list<_Tp, _Alloc>& __x) + { + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) _M_transfer(__last1, __first2, __last2); + } + + inline void + __List_base_reverse(_List_node_base* __p) + { + _List_node_base* __tmp = __p; + do { + std::swap(__tmp->_M_next, __tmp->_M_prev); + __tmp = __tmp->_M_prev; // Old next node is now prev. + } while (__tmp != __p); + } + + template<typename _Tp, typename _Alloc> + inline void list<_Tp, _Alloc>:: + reverse() + { __List_base_reverse(this->_M_node); } + + template<typename _Tp, typename _Alloc> + void list<_Tp, _Alloc>:: + sort() + { + // Do nothing if the list has length 0 or 1. + if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) { + list<_Tp, _Alloc> __carry; + list<_Tp, _Alloc> __counter[64]; + int __fill = 0; + while (!empty()) { + __carry.splice(__carry.begin(), *this, begin()); + int __i = 0; + while(__i < __fill && !__counter[__i].empty()) { + __counter[__i].merge(__carry); + __carry.swap(__counter[__i++]); + } + __carry.swap(__counter[__i]); + if (__i == __fill) ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1]); + swap(__counter[__fill-1]); + } + } + + template<typename _Tp, typename _Alloc> + template <typename _Predicate> + void list<_Tp, _Alloc>:: + remove_if(_Predicate __pred) + { + iterator __first = begin(); + iterator __last = end(); + while (__first != __last) { + iterator __next = __first; + ++__next; + if (__pred(*__first)) erase(__first); + __first = __next; + } + } + + template<typename _Tp, typename _Alloc> + template <typename _BinaryPredicate> + void list<_Tp, _Alloc>:: + unique(_BinaryPredicate __binary_pred) + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) return; + iterator __next = __first; + while (++__next != __last) { + if (__binary_pred(*__first, *__next)) + erase(__next); + else + __first = __next; + __next = __first; + } + } + + template<typename _Tp, typename _Alloc> + template <typename _StrictWeakOrdering> + void list<_Tp, _Alloc>:: + merge(list<_Tp, _Alloc>& __x, _StrictWeakOrdering __comp) + { + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) _M_transfer(__last1, __first2, __last2); + } + + template<typename _Tp, typename _Alloc> + template <typename _StrictWeakOrdering> + void list<_Tp, _Alloc>:: + sort(_StrictWeakOrdering __comp) + { + // Do nothing if the list has length 0 or 1. + if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) { + list<_Tp, _Alloc> __carry; + list<_Tp, _Alloc> __counter[64]; + int __fill = 0; + while (!empty()) { + __carry.splice(__carry.begin(), *this, begin()); + int __i = 0; + while(__i < __fill && !__counter[__i].empty()) { + __counter[__i].merge(__carry, __comp); + __carry.swap(__counter[__i++]); + } + __carry.swap(__counter[__i]); + if (__i == __fill) ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1], __comp); + swap(__counter[__fill-1]); + } + } + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_LIST_H */ + +// vi:set ts=2 sw=2: +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_map.h b/contrib/libstdc++/include/bits/stl_map.h new file mode 100644 index 0000000000000..07c62e4fb5b4f --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_map.h @@ -0,0 +1,503 @@ +// Map implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_map.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_MAP_H +#define _CPP_BITS_STL_MAP_H 1 + +#include <bits/concept_check.h> + +namespace std +{ + +/** + * @brief A standard container made up of pairs (see std::pair in <utility>) + * which can be retrieved based on a key. + * + * This is an associative container. Values contained within it can be + * quickly retrieved through a key element. Example: MyMap["First"] would + * return the data associated with the key "First". +*/ +template <class _Key, class _Tp, class _Compare = less<_Key>, + class _Alloc = allocator<pair<const _Key, _Tp> > > +class map +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept); + +public: + // typedefs: + typedef _Key key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + + class value_compare + : public binary_function<value_type, value_type, bool> { + friend class map<_Key,_Tp,_Compare,_Alloc>; + protected : + _Compare comp; + value_compare(_Compare __c) : comp(__c) {} + public: + bool operator()(const value_type& __x, const value_type& __y) const { + return comp(__x.first, __y.first); + } + }; + +private: + typedef _Rb_tree<key_type, value_type, + _Select1st<value_type>, key_compare, _Alloc> _Rep_type; + _Rep_type _M_t; // red-black tree representing map +public: + typedef typename _Rep_type::pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::allocator_type allocator_type; + + // allocation/deallocation + + map() : _M_t(_Compare(), allocator_type()) {} + explicit map(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) {} + + template <class _InputIterator> + map(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) + { _M_t.insert_unique(__first, __last); } + + template <class _InputIterator> + map(_InputIterator __first, _InputIterator __last, const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); } + map(const map<_Key,_Tp,_Compare,_Alloc>& __x) : _M_t(__x._M_t) {} + + map<_Key,_Tp,_Compare,_Alloc>& + operator=(const map<_Key, _Tp, _Compare, _Alloc>& __x) + { + _M_t = __x._M_t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return _M_t.key_comp(); } + value_compare value_comp() const { return value_compare(_M_t.key_comp()); } + allocator_type get_allocator() const { return _M_t.get_allocator(); } + + /** + * Returns a read/write iterator that points to the first pair in the map. + * Iteration is done in ascending order according to the keys. + */ + iterator begin() { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the map. Iteration is done in ascending order according to the keys. + */ + const_iterator begin() const { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in the + * map. Iteration is done in ascending order according to the keys. + */ + iterator end() { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator end() const { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the map. Iteration is done in descending order according to the keys. + */ + reverse_iterator rbegin() { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * pair in the map. Iteration is done in descending order according to + * the keys. + */ + const_reverse_iterator rbegin() const { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the map. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator rend() { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the map. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator rend() const { return _M_t.rend(); } + + /** Returns true if the map is empty. (Thus begin() would equal end().) */ + bool empty() const { return _M_t.empty(); } + /** Returns the size of the map. */ + size_type size() const { return _M_t.size(); } + /** Returns the maximum size of the map. */ + size_type max_size() const { return _M_t.max_size(); } + + /** + * @brief Subscript ( [] ) access to map data. + * @param k The key for which data should be retrieved. + * + * Allows for easy lookup with the subscript ( [] ) operator. Returns the + * data associated with the key specified in subscript. If the key does + * not exist a pair with that key is created with a default value, which + * is then returned. + */ + _Tp& operator[](const key_type& __k) { + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) + __i = insert(__i, value_type(__k, _Tp())); + return (*__i).second; + } + + void swap(map<_Key,_Tp,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); } + + // insert/erase + /** + * @brief Attempts to insert a std::pair into the map. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return A pair of which the first element is an iterator that points + * to the possibly inserted pair, a second element of type bool + * to show if the pair was actually inserted. + * + * This function attempts to insert a (key, value) pair into the map. A + * map relies on unique keys and thus a pair is only inserted if its first + * element (the key) is not already present in the map. + */ + pair<iterator,bool> insert(const value_type& __x) + { return _M_t.insert_unique(__x); } + + /** + * @brief Attempts to insert a std::pair into the map. + * @param position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function is not concerned about whether the insertion took place + * or not and thus does not return a boolean like the single-argument + * insert() does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + */ + iterator insert(iterator position, const value_type& __x) + { return _M_t.insert_unique(position, __x); } + + /** + * @brief A template function that attemps to insert elements from + * another range (possibly another map). + * @param first Iterator pointing to the start of the range to be inserted. + * @param last Iterator pointing to the end of the range. + */ + template <class _InputIterator> + void insert(_InputIterator __first, _InputIterator __last) { + _M_t.insert_unique(__first, __last); + } + + /** + * @brief Erases an element from a map. + * @param position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, from + * a map. Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibilty. + */ + void erase(iterator __position) { _M_t.erase(__position); } + + /** + * @brief Erases an element according to the provided key. + * @param x Key of element to be erased. + * @return Doc me! (Number of elements that match key? Only makes sense + * with multimap) + * + * This function erases an element, located by the given key, from a map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibilty. + */ + size_type erase(const key_type& __x) { return _M_t.erase(__x); } + + /** + * @brief Erases a [first,last) range of elements from a map. + * @param first Iterator pointing to the start of the range to be erased. + * @param last Iterator pointing to the end of the range to be erased. + * + * This function erases a sequence of elements from a map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibilty. + */ + void erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } + + /** Erases all elements in a map. Note that this function only erases + * the elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void clear() { _M_t.clear(); } + + // map operations: + + /** + * @brief Tries to locate an element in a map. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after pair. If unsuccessful it returns the + * one past the end ( end() ) iterator. + */ + iterator find(const key_type& __x) { return _M_t.find(__x); } + + /** + * @brief Tries to locate an element in a map. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant iterator + * pointing to the sought after pair. If unsuccessful it returns the + * one past the end ( end() ) iterator. + */ + const_iterator find(const key_type& __x) const { return _M_t.find(__x); } + + /** + * @brief Finds the number of elements with given key. + * @param x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + * + * This function only makes sense for multimaps. + */ + size_type count(const key_type& __x) const { + return _M_t.find(__x) == _M_t.end() ? 0 : 1; + } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to first element matching given key, or + * end() if not found. + * + * This function is useful only with std::multimap. It returns the first + * element of a subsequence of elements that matches the given key. If + * unsuccessful it returns an iterator pointing to the first element that + * has a greater value than given key or end() if no such element exists. + */ + iterator lower_bound(const key_type& __x) {return _M_t.lower_bound(__x); } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * matching given key, or end() if not found. + * + * This function is useful only with std::multimap. It returns the first + * element of a subsequence of elements that matches the given key. If + * unsuccessful the iterator will point to the next greatest element or, + * if no such greater element exists, to end(). + */ + const_iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to last element matching given key. + * + * This function only makes sense with multimaps. + */ + iterator upper_bound(const key_type& __x) {return _M_t.upper_bound(__x); } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to last element matching + * given key. + * + * This function only makes sense with multimaps. + */ + const_iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + + /** + * @brief Finds a subsequence matching given key. + * @param x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function improves on lower_bound() and upper_bound() by giving a more + * elegant and efficient solution. It returns a pair of which the first + * element possibly points to the first element matching the given key + * and the second element possibly points to the last element matching the + * given key. If unsuccessful the first element of the returned pair will + * contain an iterator pointing to the next greatest element or, if no such + * greater element exists, to end(). + * + * This function only makes sense for multimaps. + */ + pair<iterator,iterator> equal_range(const key_type& __x) { + return _M_t.equal_range(__x); + } + + /** + * @brief Finds a subsequence matching given key. + * @param x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points to + * the subsequence matching given key. + * + * This function improves on lower_bound() and upper_bound() by giving a more + * elegant and efficient solution. It returns a pair of which the first + * element possibly points to the first element matching the given key + * and the second element possibly points to the last element matching the + * given key. If unsuccessful the first element of the returned pair will + * contain an iterator pointing to the next greatest element or, if no such + * a greater element exists, to end(). + * + * This function only makes sense for multimaps. + */ + pair<const_iterator,const_iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } + + template <class _K1, class _T1, class _C1, class _A1> + friend bool operator== (const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); + template <class _K1, class _T1, class _C1, class _A1> + friend bool operator< (const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +}; + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return __x._M_t == __y._M_t; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator<(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return __x._M_t < __y._M_t; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__x == __y); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return __y < __x; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__y < __x); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator>=(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__x < __y); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline void swap(map<_Key,_Tp,_Compare,_Alloc>& __x, + map<_Key,_Tp,_Compare,_Alloc>& __y) { + __x.swap(__y); +} + +} // namespace std + +#endif /* _CPP_BITS_STL_MAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_multimap.h b/contrib/libstdc++/include/bits/stl_multimap.h new file mode 100644 index 0000000000000..5947d7537a671 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_multimap.h @@ -0,0 +1,491 @@ +// Multimap implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_multimap.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_MULTIMAP_H +#define __GLIBCPP_INTERNAL_MULTIMAP_H + +#include <bits/concept_check.h> + +namespace std +{ +// Forward declaration of operators < and ==, needed for friend declaration. +template <class _Key, class _Tp, + class _Compare = less<_Key>, + class _Alloc = allocator<pair<const _Key, _Tp> > > +class multimap; + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y); + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y); + +/** + * @brief A standard container made up of pairs (see std::pair in <utility>) + * which can be retrieved based on a key. + * + * This is an associative container. Values contained within it can be + * quickly retrieved through a key element. In contrast with a map a + * multimap can have multiple duplicate keys. +*/ +template <class _Key, class _Tp, class _Compare, class _Alloc> +class multimap +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept); + +public: + +// typedefs: + + typedef _Key key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + + class value_compare : public binary_function<value_type, value_type, bool> { + friend class multimap<_Key,_Tp,_Compare,_Alloc>; + protected: + _Compare comp; + value_compare(_Compare __c) : comp(__c) {} + public: + bool operator()(const value_type& __x, const value_type& __y) const { + return comp(__x.first, __y.first); + } + }; + +private: + typedef _Rb_tree<key_type, value_type, + _Select1st<value_type>, key_compare, _Alloc> _Rep_type; + _Rep_type _M_t; // red-black tree representing multimap +public: + typedef typename _Rep_type::pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::allocator_type allocator_type; + +// allocation/deallocation + + multimap() : _M_t(_Compare(), allocator_type()) { } + explicit multimap(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { } + + template <class _InputIterator> + multimap(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) + { _M_t.insert_equal(__first, __last); } + + template <class _InputIterator> + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); } + multimap(const multimap<_Key,_Tp,_Compare,_Alloc>& __x) : _M_t(__x._M_t) { } + + multimap<_Key,_Tp,_Compare,_Alloc>& + operator=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x) { + _M_t = __x._M_t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return _M_t.key_comp(); } + value_compare value_comp() const { return value_compare(_M_t.key_comp()); } + allocator_type get_allocator() const { return _M_t.get_allocator(); } + + /** + * Returns a read/write iterator that points to the first pair in the + * multimap. Iteration is done in ascending order according to the keys. + */ + iterator begin() { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the multimap. Iteration is done in ascending order according to the + * keys. + */ + const_iterator begin() const { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in the + * multimap. Iteration is done in ascending order according to the keys. + */ + iterator end() { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator end() const { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the multimap. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator rbegin() { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * pair in the multimap. Iteration is done in descending order according + * to the keys. + */ + const_reverse_iterator rbegin() const { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the multimap. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator rend() { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the multimap. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator rend() const { return _M_t.rend(); } + + /** Returns true if the map is empty. (Thus begin() would equal end().) */ + bool empty() const { return _M_t.empty(); } + + /** Returns the size of the map. */ + size_type size() const { return _M_t.size(); } + + /** Returns the maximum size of the map. */ + size_type max_size() const { return _M_t.max_size(); } + + void swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); } + + // insert/erase + /** + * @brief Inserts a std::pair into the multimap. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the multimap. Contrary + * to a std::map the multimap does not rely on unique keys and thus a + * multiple pairs with the same key can be inserted. + */ + iterator insert(const value_type& __x) { return _M_t.insert_equal(__x); } + + /** + * @brief Inserts a std::pair into the multimap. + * @param position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the multimap. Contrary + * to a std::map the multimap does not rely on unique keys and thus a + * multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + */ + iterator insert(iterator __position, const value_type& __x) { + return _M_t.insert_equal(__position, __x); + } + + /** + * @brief A template function that attemps to insert elements from + * another range (possibly another multimap or standard container). + * @param first Iterator pointing to the start of the range to be + * inserted. + * @param last Iterator pointing to the end of the range to be inserted. + */ + template <class _InputIterator> + void insert(_InputIterator __first, _InputIterator __last) { + _M_t.insert_equal(__first, __last); + } + + /** + * @brief Erases an element from a multimap. + * @param position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, from + * a mutlimap. Note that this function only erases the element, and that + * if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's responsibilty. + */ + void erase(iterator __position) { _M_t.erase(__position); } + + /** + * @brief Erases an element according to the provided key. + * @param x Key of element to be erased. + * @return Doc me! (Number of elements erased?) + * + * This function erases all elements, located by the given key, from a + * multimap. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibilty. + */ + size_type erase(const key_type& __x) { return _M_t.erase(__x); } + + /** + * @brief Erases a [first,last) range of elements from a multimap. + * @param first Iterator pointing to the start of the range to be erased. + * @param last Iterator pointing to the end of the range to be erased. + * + * This function erases a sequence of elements from a multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's responsibilty. + */ + void erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } + + /** Erases all elements in a multimap. Note that this function only erases + * the elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void clear() { _M_t.clear(); } + + // multimap operations: + + /** + * @brief Tries to locate an element in a multimap. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to sought-after (first matching?) element, + * or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after pair. If unsuccessful it returns the + * one past the end ( end() ) iterator. + */ + iterator find(const key_type& __x) { return _M_t.find(__x); } + + /** + * @brief Tries to locate an element in a multimap. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to sought-after (first + * matching?) element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant iterator + * pointing to the sought after pair. If unsuccessful it returns the + * one past the end ( end() ) iterator. + */ + const_iterator find(const key_type& __x) const { return _M_t.find(__x); } + + /** + * @brief Finds the number of elements with given key. + * @param x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + */ + size_type count(const key_type& __x) const { return _M_t.count(__x); } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to first element matching given key, or + * end() if not found. + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator lower_bound(const key_type& __x) {return _M_t.lower_bound(__x); } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * matching given key, or end() if not found. + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful the iterator will point + * to the next greatest element or, if no such greater element exists, to + * end(). + */ + const_iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to last element matching given key. + */ + iterator upper_bound(const key_type& __x) {return _M_t.upper_bound(__x); } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to last element matching + * given key. + */ + const_iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + + /** + * @brief Finds a subsequence matching given key. + * @param x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function improves on lower_bound() and upper_bound() by giving a more + * elegant and efficient solution. It returns a pair of which the first + * element possibly points to the first element matching the given key + * and the second element possibly points to the last element matching the + * given key. If unsuccessful the first element of the returned pair will + * contain an iterator pointing to the next greatest element or, if no such + * greater element exists, to end(). + */ + pair<iterator,iterator> equal_range(const key_type& __x) { + return _M_t.equal_range(__x); + } + + /** + * @brief Finds a subsequence matching given key. + * @param x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points to + * the subsequence matching given key. + * + * This function improves on lower_bound() and upper_bound() by giving a more + * elegant and efficient solution. It returns a pair of which the first + * element possibly points to the first element matching the given key + * and the second element possibly points to the last element matching the + * given key. If unsuccessful the first element of the returned pair will + * contain an iterator pointing to the next greatest element or, if no such + * a greater element exists, to end(). + */ + pair<const_iterator,const_iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } + + template <class _K1, class _T1, class _C1, class _A1> + friend bool operator== (const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); + template <class _K1, class _T1, class _C1, class _A1> + friend bool operator< (const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +}; + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return __x._M_t == __y._M_t; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return __x._M_t < __y._M_t; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__x == __y); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return __y < __x; +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__y < __x); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline bool operator>=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + return !(__x < __y); +} + +template <class _Key, class _Tp, class _Compare, class _Alloc> +inline void swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x, + multimap<_Key,_Tp,_Compare,_Alloc>& __y) { + __x.swap(__y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_MULTIMAP_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_multiset.h b/contrib/libstdc++/include/bits/stl_multiset.h new file mode 100644 index 0000000000000..2bfc8f10c32b4 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_multiset.h @@ -0,0 +1,277 @@ +// Multiset implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_multiset.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_MULTISET_H +#define __GLIBCPP_INTERNAL_MULTISET_H + +#include <bits/concept_check.h> + +namespace std +{ + +// Forward declaration of operators < and ==, needed for friend declaration. + +template <class _Key, class _Compare = less<_Key>, + class _Alloc = allocator<_Key> > +class multiset; + +template <class _Key, class _Compare, class _Alloc> +inline bool operator==(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y); + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y); + +template <class _Key, class _Compare, class _Alloc> +class multiset +{ + // concept requirements + __glibcpp_class_requires(_Key, _SGIAssignableConcept) + __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept); + +public: + + // typedefs: + + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; +private: + typedef _Rb_tree<key_type, value_type, + _Identity<value_type>, key_compare, _Alloc> _Rep_type; + _Rep_type _M_t; // red-black tree representing multiset +public: + typedef typename _Rep_type::const_pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::const_reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::allocator_type allocator_type; + + // allocation/deallocation + + multiset() : _M_t(_Compare(), allocator_type()) {} + explicit multiset(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) {} + + template <class _InputIterator> + multiset(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) + { _M_t.insert_equal(__first, __last); } + + template <class _InputIterator> + multiset(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); } + + multiset(const multiset<_Key,_Compare,_Alloc>& __x) : _M_t(__x._M_t) {} + + multiset<_Key,_Compare,_Alloc>& + operator=(const multiset<_Key,_Compare,_Alloc>& __x) { + _M_t = __x._M_t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return _M_t.key_comp(); } + value_compare value_comp() const { return _M_t.key_comp(); } + allocator_type get_allocator() const { return _M_t.get_allocator(); } + + iterator begin() const { return _M_t.begin(); } + iterator end() const { return _M_t.end(); } + reverse_iterator rbegin() const { return _M_t.rbegin(); } + reverse_iterator rend() const { return _M_t.rend(); } + bool empty() const { return _M_t.empty(); } + size_type size() const { return _M_t.size(); } + size_type max_size() const { return _M_t.max_size(); } + void swap(multiset<_Key,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); } + + // insert/erase + iterator insert(const value_type& __x) { + return _M_t.insert_equal(__x); + } + iterator insert(iterator __position, const value_type& __x) { + typedef typename _Rep_type::iterator _Rep_iterator; + return _M_t.insert_equal((_Rep_iterator&)__position, __x); + } + + template <class _InputIterator> + void insert(_InputIterator __first, _InputIterator __last) { + _M_t.insert_equal(__first, __last); + } + void erase(iterator __position) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__position); + } + size_type erase(const key_type& __x) { + return _M_t.erase(__x); + } + void erase(iterator __first, iterator __last) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); + } + void clear() { _M_t.clear(); } + + // multiset operations: + + size_type count(const key_type& __x) const { return _M_t.count(__x); } + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//214. set::find() missing const overload + iterator find(const key_type& __x) { return _M_t.find(__x); } + const_iterator find(const key_type& __x) const { return _M_t.find(__x); } + iterator lower_bound(const key_type& __x) { + return _M_t.lower_bound(__x); + } + const_iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + iterator upper_bound(const key_type& __x) { + return _M_t.upper_bound(__x); + } + const_iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + pair<iterator,iterator> equal_range(const key_type& __x) { + return _M_t.equal_range(__x); + } + pair<const_iterator,const_iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } +#else + iterator find(const key_type& __x) const { return _M_t.find(__x); } + iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + pair<iterator,iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } +#endif + + template <class _K1, class _C1, class _A1> + friend bool operator== (const multiset<_K1,_C1,_A1>&, + const multiset<_K1,_C1,_A1>&); + template <class _K1, class _C1, class _A1> + friend bool operator< (const multiset<_K1,_C1,_A1>&, + const multiset<_K1,_C1,_A1>&); +}; + +template <class _Key, class _Compare, class _Alloc> +inline bool operator==(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return __x._M_t == __y._M_t; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return __x._M_t < __y._M_t; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator!=(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return !(__x == __y); +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator>(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return __y < __x; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<=(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return !(__y < __x); +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator>=(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) { + return !(__x < __y); +} + +template <class _Key, class _Compare, class _Alloc> +inline void swap(multiset<_Key,_Compare,_Alloc>& __x, + multiset<_Key,_Compare,_Alloc>& __y) { + __x.swap(__y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_MULTISET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_numeric.h b/contrib/libstdc++/include/bits/stl_numeric.h new file mode 100644 index 0000000000000..23f2bcc4512c5 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_numeric.h @@ -0,0 +1,215 @@ +// Numeric functions implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_numeric.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_NUMERIC_H +#define _CPP_BITS_STL_NUMERIC_H 1 + +namespace std +{ + + template<typename _InputIterator, typename _Tp> + _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + + for ( ; __first != __last; ++__first) + __init = __init + *__first; + return __init; + } + + template<typename _InputIterator, typename _Tp, typename _BinaryOperation> + _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + + for ( ; __first != __last; ++__first) + __init = __binary_op(__init, *__first); + return __init; + } + + template<typename _InputIterator1, typename _InputIterator2, typename _Tp> + _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator2>) + + for ( ; __first1 != __last1; ++__first1, ++__first2) + __init = __init + (*__first1 * *__first2); + return __init; + } + + template<typename _InputIterator1, typename _InputIterator2, typename _Tp, + typename _BinaryOperation1, typename _BinaryOperation2> + _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator2>) + + for ( ; __first1 != __last1; ++__first1, ++__first2) + __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); + return __init; + } + + template<typename _InputIterator, typename _OutputIterator> + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIterator, _ValueType>) + + if (__first == __last) return __result; + *__result = *__first; + _ValueType __value = *__first; + while (++__first != __last) { + __value = __value + *__first; + *++__result = __value; + } + return ++__result; + } + + template<typename _InputIterator, typename _OutputIterator, typename _BinaryOperation> + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIterator, _ValueType>) + + if (__first == __last) return __result; + *__result = *__first; + _ValueType __value = *__first; + while (++__first != __last) { + __value = __binary_op(__value, *__first); + *++__result = __value; + } + return ++__result; + } + + template<typename _InputIterator, typename _OutputIterator> + _OutputIterator + adjacent_difference(_InputIterator __first, + _InputIterator __last, _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIterator, _ValueType>) + + if (__first == __last) return __result; + *__result = *__first; + _ValueType __value = *__first; + while (++__first != __last) { + _ValueType __tmp = *__first; + *++__result = __tmp - __value; + __value = __tmp; + } + return ++__result; + } + + template<typename _InputIterator, typename _OutputIterator, typename _BinaryOperation> + _OutputIterator + adjacent_difference(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcpp_function_requires(_OutputIteratorConcept<_OutputIterator, _ValueType>) + + if (__first == __last) return __result; + *__result = *__first; + _ValueType __value = *__first; + while (++__first != __last) { + _ValueType __tmp = *__first; + *++__result = __binary_op(__tmp, __value); + __value = __tmp; + } + return ++__result; + } + +} // namespace std + +#endif /* _CPP_BITS_STL_NUMERIC_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_pair.h b/contrib/libstdc++/include/bits/stl_pair.h new file mode 100644 index 0000000000000..d689ccc8d27d6 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_pair.h @@ -0,0 +1,157 @@ +// Pair implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_pair.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_PAIR_H +#define __GLIBCPP_INTERNAL_PAIR_H + +namespace std +{ + +/// pair holds two objects of arbitrary type. +template <class _T1, class _T2> +struct pair { + typedef _T1 first_type; ///< @c first_type is the first bound type + typedef _T2 second_type; ///< @c second_type is the second bound type + + _T1 first; ///< @c first is a copy of the first object + _T2 second; ///< @c second is a copy of the second object +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//265. std::pair::pair() effects overly restrictive + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ + pair() : first(), second() {} +#else + pair() : first(_T1()), second(_T2()) {} +#endif + /** Two objects may be passed to a @c pair constructor to be copied. */ + pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) {} + + /** There is also a templated copy ctor for the @c pair class itself. */ + template <class _U1, class _U2> + pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {} +}; + +/// Two pairs of the same type are equal iff their members are equal. +template <class _T1, class _T2> +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 +template <class _T1, class _T2> +inline bool operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) +{ + return __x.first < __y.first || + (!(__y.first < __x.first) && __x.second < __y.second); +} + +/// Uses @c operator== to find the result. +template <class _T1, class _T2> +inline bool operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { + return !(__x == __y); +} + +/// Uses @c operator< to find the result. +template <class _T1, class _T2> +inline bool operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { + return __y < __x; +} + +/// Uses @c operator< to find the result. +template <class _T1, class _T2> +inline bool operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { + return !(__y < __x); +} + +/// Uses @c operator< to find the result. +template <class _T1, class _T2> +inline bool operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) { + return !(__x < __y); +} + +/** + * @brief A convenience wrapper for creating a pair from two objects. + * @param x The first object. + * @param y The second object. + * @return A newly-constructed pair<> object of the appropriate type. + * + * The standard requires that the objects be passed by reference-to-const, + * but LWG issue #181 says they should be passed by const value. We follow + * the LWG by default. +*/ +template <class _T1, class _T2> +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//181. make_pair() unintended behavior +inline pair<_T1, _T2> make_pair(_T1 __x, _T2 __y) +#else +inline pair<_T1, _T2> make_pair(const _T1& __x, const _T2& __y) +#endif +{ + return pair<_T1, _T2>(__x, __y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_PAIR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_pthread_alloc.h b/contrib/libstdc++/include/bits/stl_pthread_alloc.h new file mode 100644 index 0000000000000..09b7d727af65c --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_pthread_alloc.h @@ -0,0 +1,60 @@ +// Wrapper of pthread allocation header -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_pthread_alloc.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_PTHREAD_ALLOC_H +#define _CPP_BITS_STL_PTHREAD_ALLOC_H 1 + +#include <bits/pthread_allocimpl.h> + +using std::_Pthread_alloc_template; +using std::pthread_alloc; + +#endif /* _CPP_BITS_STL_PTHREAD_ALLOC_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_queue.h b/contrib/libstdc++/include/bits/stl_queue.h new file mode 100644 index 0000000000000..5503640187aca --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_queue.h @@ -0,0 +1,244 @@ +// Queue implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_queue.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_QUEUE_H +#define __GLIBCPP_INTERNAL_QUEUE_H + +#include <bits/concept_check.h> + +namespace std +{ + +// Forward declarations of operators < and ==, needed for friend declaration. + +template <class _Tp, + class _Sequence = deque<_Tp> > +class queue; + +template <class _Tp, class _Seq> +inline bool operator==(const queue<_Tp, _Seq>&, const queue<_Tp, _Seq>&); + +template <class _Tp, class _Seq> +inline bool operator<(const queue<_Tp, _Seq>&, const queue<_Tp, _Seq>&); + + +template <class _Tp, class _Sequence> +class queue +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires(_Sequence, _FrontInsertionSequenceConcept) + __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept) + typedef typename _Sequence::value_type _Sequence_value_type; + __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept); + + template <class _Tp1, class _Seq1> + friend bool operator== (const queue<_Tp1, _Seq1>&, + const queue<_Tp1, _Seq1>&); + template <class _Tp1, class _Seq1> + friend bool operator< (const queue<_Tp1, _Seq1>&, + const queue<_Tp1, _Seq1>&); +public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; +protected: + _Sequence c; +public: + explicit queue(const _Sequence& __c = _Sequence()) : c(__c) {} + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference front() { return c.front(); } + const_reference front() const { return c.front(); } + reference back() { return c.back(); } + const_reference back() const { return c.back(); } + void push(const value_type& __x) { c.push_back(__x); } + void pop() { c.pop_front(); } +}; + +template <class _Tp, class _Sequence> +bool +operator==(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return __x.c == __y.c; +} + +template <class _Tp, class _Sequence> +bool +operator<(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return __x.c < __y.c; +} + +template <class _Tp, class _Sequence> +bool +operator!=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return !(__x == __y); +} + +template <class _Tp, class _Sequence> +bool +operator>(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return __y < __x; +} + +template <class _Tp, class _Sequence> +bool +operator<=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return !(__y < __x); +} + +template <class _Tp, class _Sequence> +bool +operator>=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) +{ + return !(__x < __y); +} + +template <class _Tp, + class _Sequence = vector<_Tp>, + class _Compare = less<typename _Sequence::value_type> > +class priority_queue +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires(_Sequence, _SequenceConcept) + __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept) + typedef typename _Sequence::value_type _Sequence_value_type; + __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept); + __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept); + +public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; +protected: + _Sequence c; + _Compare comp; +public: + explicit priority_queue(const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { make_heap(c.begin(), c.end(), comp); } + + template <class _InputIterator> + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { + c.insert(c.end(), __first, __last); + make_heap(c.begin(), c.end(), comp); + } + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + const_reference top() const { return c.front(); } + + void + push(const value_type& __x) + { + try + { + c.push_back(__x); + push_heap(c.begin(), c.end(), comp); + } + catch(...) + { + c.clear(); + __throw_exception_again; + } + } + + void + pop() + { + try + { + pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + catch(...) + { + c.clear(); + __throw_exception_again; + } + } +}; + +// no equality is provided + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_QUEUE_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_raw_storage_iter.h b/contrib/libstdc++/include/bits/stl_raw_storage_iter.h new file mode 100644 index 0000000000000..59aa004296e88 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_raw_storage_iter.h @@ -0,0 +1,112 @@ +// -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_raw_storage_iter.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_RAW_STORAGE_ITERATOR_H +#define _CPP_BITS_STL_RAW_STORAGE_ITERATOR_H 1 + +namespace std +{ + /** + * This iterator class lets algorithms store their results into + * uninitialized memory. + */ + template <class _ForwardIterator, class _Tp> + class raw_storage_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _ForwardIterator _M_iter; + + public: + explicit + raw_storage_iterator(_ForwardIterator __x) : _M_iter(__x) {} + + raw_storage_iterator& + operator*() { return *this; } + + raw_storage_iterator& + operator=(const _Tp& __element) + { + _Construct(&*_M_iter, __element); + return *this; + } + + raw_storage_iterator<_ForwardIterator, _Tp>& + operator++() + { + ++_M_iter; + return *this; + } + + raw_storage_iterator<_ForwardIterator, _Tp> + operator++(int) + { + raw_storage_iterator<_ForwardIterator, _Tp> __tmp = *this; + ++_M_iter; + return __tmp; + } + }; +} // namespace std + +#endif + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_relops.h b/contrib/libstdc++/include/bits/stl_relops.h new file mode 100644 index 0000000000000..ce3dc0b9b393f --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_relops.h @@ -0,0 +1,141 @@ +// std::rel_ops implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1996,1997 + * Silicon Graphics + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file stl_relops.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + * + * @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 + * with http://gcc.gnu.org/ml/libstdc++/2001-01/msg00223.html , or the + * 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. + * @endif + */ + +#ifndef _CPP_BITS_STL_RELOPS_H +#define _CPP_BITS_STL_RELOPS_H 1 + +namespace std +{ + namespace rel_ops + { + /** @namespace std::rel_ops + * @brief The generated relational operators are sequestered here. + */ + +/** + * @brief Defines @c != for arbitrary types, in terms of @c ==. + * @param x A thing. + * @param y Another thing. + * @return x != y + * + * This function uses @c == to determine its result. +*/ +template <class _Tp> +inline bool operator!=(const _Tp& __x, const _Tp& __y) { + return !(__x == __y); +} + +/** + * @brief Defines @c > for arbitrary types, in terms of @c <. + * @param x A thing. + * @param y Another thing. + * @return x > y + * + * This function uses @c < to determine its result. +*/ +template <class _Tp> +inline bool operator>(const _Tp& __x, const _Tp& __y) { + return __y < __x; +} + +/** + * @brief Defines @c <= for arbitrary types, in terms of @c <. + * @param x A thing. + * @param y Another thing. + * @return x <= y + * + * This function uses @c < to determine its result. +*/ +template <class _Tp> +inline bool operator<=(const _Tp& __x, const _Tp& __y) { + return !(__y < __x); +} + +/** + * @brief Defines @c >= for arbitrary types, in terms of @c <. + * @param x A thing. + * @param y Another thing. + * @return x >= y + * + * This function uses @c < to determine its result. +*/ +template <class _Tp> +inline bool operator>=(const _Tp& __x, const _Tp& __y) { + return !(__x < __y); +} + + } // namespace rel_ops +} // namespace std + +#endif /* _CPP_BITS_STL_RELOPS_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_set.h b/contrib/libstdc++/include/bits/stl_set.h new file mode 100644 index 0000000000000..ee708c292179a --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_set.h @@ -0,0 +1,274 @@ +// Set implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_set.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_SET_H +#define __GLIBCPP_INTERNAL_SET_H + +#include <bits/concept_check.h> + +namespace std +{ + +// Forward declarations of operators < and ==, needed for friend declaration. + +template <class _Key, class _Compare = less<_Key>, + class _Alloc = allocator<_Key> > +class set; + +template <class _Key, class _Compare, class _Alloc> +inline bool operator==(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y); + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y); + + +template <class _Key, class _Compare, class _Alloc> +class set +{ + // concept requirements + __glibcpp_class_requires(_Key, _SGIAssignableConcept) + __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept); + +public: + // typedefs: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; +private: + typedef _Rb_tree<key_type, value_type, + _Identity<value_type>, key_compare, _Alloc> _Rep_type; + _Rep_type _M_t; // red-black tree representing set +public: + typedef typename _Rep_type::const_pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::const_reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::allocator_type allocator_type; + + // allocation/deallocation + + set() : _M_t(_Compare(), allocator_type()) {} + explicit set(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) {} + + template <class _InputIterator> + set(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) + { _M_t.insert_unique(__first, __last); } + + template <class _InputIterator> + set(_InputIterator __first, _InputIterator __last, const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { _M_t.insert_unique(__first, __last); } + + set(const set<_Key,_Compare,_Alloc>& __x) : _M_t(__x._M_t) {} + set<_Key,_Compare,_Alloc>& operator=(const set<_Key, _Compare, _Alloc>& __x) + { + _M_t = __x._M_t; + return *this; + } + + // accessors: + + key_compare key_comp() const { return _M_t.key_comp(); } + value_compare value_comp() const { return _M_t.key_comp(); } + allocator_type get_allocator() const { return _M_t.get_allocator(); } + + iterator begin() const { return _M_t.begin(); } + iterator end() const { return _M_t.end(); } + reverse_iterator rbegin() const { return _M_t.rbegin(); } + reverse_iterator rend() const { return _M_t.rend(); } + bool empty() const { return _M_t.empty(); } + size_type size() const { return _M_t.size(); } + size_type max_size() const { return _M_t.max_size(); } + void swap(set<_Key,_Compare,_Alloc>& __x) { _M_t.swap(__x._M_t); } + + // insert/erase + pair<iterator,bool> insert(const value_type& __x) { + pair<typename _Rep_type::iterator, bool> __p = _M_t.insert_unique(__x); + return pair<iterator, bool>(__p.first, __p.second); + } + iterator insert(iterator __position, const value_type& __x) { + typedef typename _Rep_type::iterator _Rep_iterator; + return _M_t.insert_unique((_Rep_iterator&)__position, __x); + } + template <class _InputIterator> + void insert(_InputIterator __first, _InputIterator __last) { + _M_t.insert_unique(__first, __last); + } + void erase(iterator __position) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__position); + } + size_type erase(const key_type& __x) { + return _M_t.erase(__x); + } + void erase(iterator __first, iterator __last) { + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); + } + void clear() { _M_t.clear(); } + + // set operations: + + size_type count(const key_type& __x) const { + return _M_t.find(__x) == _M_t.end() ? 0 : 1; + } + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//214. set::find() missing const overload + iterator find(const key_type& __x) { return _M_t.find(__x); } + const_iterator find(const key_type& __x) const { return _M_t.find(__x); } + iterator lower_bound(const key_type& __x) { + return _M_t.lower_bound(__x); + } + const_iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + iterator upper_bound(const key_type& __x) { + return _M_t.upper_bound(__x); + } + const_iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + pair<iterator,iterator> equal_range(const key_type& __x) { + return _M_t.equal_range(__x); + } + pair<const_iterator,const_iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } +#else + iterator find(const key_type& __x) const { return _M_t.find(__x); } + iterator lower_bound(const key_type& __x) const { + return _M_t.lower_bound(__x); + } + iterator upper_bound(const key_type& __x) const { + return _M_t.upper_bound(__x); + } + pair<iterator,iterator> equal_range(const key_type& __x) const { + return _M_t.equal_range(__x); + } +#endif + + template <class _K1, class _C1, class _A1> + friend bool operator== (const set<_K1,_C1,_A1>&, const set<_K1,_C1,_A1>&); + template <class _K1, class _C1, class _A1> + friend bool operator< (const set<_K1,_C1,_A1>&, const set<_K1,_C1,_A1>&); +}; + +template <class _Key, class _Compare, class _Alloc> +inline bool operator==(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return __x._M_t == __y._M_t; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return __x._M_t < __y._M_t; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator!=(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return !(__x == __y); +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator>(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return __y < __x; +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator<=(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return !(__y < __x); +} + +template <class _Key, class _Compare, class _Alloc> +inline bool operator>=(const set<_Key,_Compare,_Alloc>& __x, + const set<_Key,_Compare,_Alloc>& __y) { + return !(__x < __y); +} + +template <class _Key, class _Compare, class _Alloc> +inline void swap(set<_Key,_Compare,_Alloc>& __x, + set<_Key,_Compare,_Alloc>& __y) { + __x.swap(__y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_SET_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_stack.h b/contrib/libstdc++/include/bits/stl_stack.h new file mode 100644 index 0000000000000..0a80b109f6a8c --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_stack.h @@ -0,0 +1,160 @@ +// Stack implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_stack.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_STACK_H +#define __GLIBCPP_INTERNAL_STACK_H + +#include <bits/concept_check.h> + +namespace std +{ + +// Forward declarations of operators == and <, needed for friend declaration. + +template <class _Tp, + class _Sequence = deque<_Tp> > +class stack; + +template <class _Tp, class _Seq> +bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); + +template <class _Tp, class _Seq> +bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); + + +template <class _Tp, class _Sequence> +class stack +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept) + typedef typename _Sequence::value_type _Sequence_value_type; + __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept); + + template <class _Tp1, class _Seq1> + friend bool operator== (const stack<_Tp1, _Seq1>&, + const stack<_Tp1, _Seq1>&); + template <class _Tp1, class _Seq1> + friend bool operator< (const stack<_Tp1, _Seq1>&, + const stack<_Tp1, _Seq1>&); +public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; +protected: + _Sequence c; +public: + stack() : c() {} + explicit stack(const _Sequence& __s) : c(__s) {} + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference top() { return c.back(); } + const_reference top() const { return c.back(); } + void push(const value_type& __x) { c.push_back(__x); } + void pop() { c.pop_back(); } +}; + +template <class _Tp, class _Seq> +bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return __x.c == __y.c; +} + +template <class _Tp, class _Seq> +bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return __x.c < __y.c; +} + +template <class _Tp, class _Seq> +bool operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return !(__x == __y); +} + +template <class _Tp, class _Seq> +bool operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return __y < __x; +} + +template <class _Tp, class _Seq> +bool operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return !(__y < __x); +} + +template <class _Tp, class _Seq> +bool operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) +{ + return !(__x < __y); +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_STACK_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_tempbuf.h b/contrib/libstdc++/include/bits/stl_tempbuf.h new file mode 100644 index 0000000000000..7b88f9333ec76 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_tempbuf.h @@ -0,0 +1,149 @@ +// Temporary buffer implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_tempbuf.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_TEMPBUF_H +#define __GLIBCPP_INTERNAL_TEMPBUF_H + +namespace std +{ + +/** + * @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. + * @endif +*/ +template <class _ForwardIterator, class _Tp> + class _Temporary_buffer +{ + // concept requirements + __glibcpp_class_requires(_ForwardIterator, _ForwardIteratorConcept) + + ptrdiff_t _M_original_len; + ptrdiff_t _M_len; + _Tp* _M_buffer; + + // this is basically get_temporary_buffer() all over again + void _M_allocate_buffer() { + _M_original_len = _M_len; + _M_buffer = 0; + + if (_M_len > (ptrdiff_t)(INT_MAX / sizeof(_Tp))) + _M_len = INT_MAX / sizeof(_Tp); + + while (_M_len > 0) { + _M_buffer = (_Tp*) malloc(_M_len * sizeof(_Tp)); + if (_M_buffer) + break; + _M_len /= 2; + } + } + + void _M_initialize_buffer(const _Tp&, __true_type) {} + void _M_initialize_buffer(const _Tp& val, __false_type) { + uninitialized_fill_n(_M_buffer, _M_len, val); + } + +public: + /// As per Table mumble. + ptrdiff_t size() const { return _M_len; } + /// Returns the size requested by the constructor; may be >size(). + ptrdiff_t requested_size() const { return _M_original_len; } + /// As per Table mumble. + _Tp* begin() { return _M_buffer; } + /// As per Table mumble. + _Tp* end() { return _M_buffer + _M_len; } + + _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) { + // Workaround for a __type_traits bug in the pre-7.3 compiler. + typedef typename __type_traits<_Tp>::has_trivial_default_constructor + _Trivial; + + try { + _M_len = distance(__first, __last); + _M_allocate_buffer(); + if (_M_len > 0) + _M_initialize_buffer(*__first, _Trivial()); + } + catch(...) + { + free(_M_buffer); + _M_buffer = 0; + _M_len = 0; + __throw_exception_again; + } + } + + ~_Temporary_buffer() { + _Destroy(_M_buffer, _M_buffer + _M_len); + free(_M_buffer); + } + +private: + // Disable copy constructor and assignment operator. + _Temporary_buffer(const _Temporary_buffer&) {} + void operator=(const _Temporary_buffer&) {} +}; + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_TEMPBUF_H */ + diff --git a/contrib/libstdc++/include/bits/stl_threads.h b/contrib/libstdc++/include/bits/stl_threads.h new file mode 100644 index 0000000000000..0150cd58c85cb --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_threads.h @@ -0,0 +1,236 @@ +// Threading support -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * Copyright (c) 1997-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_threads.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __SGI_STL_INTERNAL_THREADS_H +#define __SGI_STL_INTERNAL_THREADS_H + +// The only supported threading model is GCC's own gthr.h abstraction layer. +#include "bits/gthr.h" + +namespace std +{ + // Class _Refcount_Base provides a type, _RC_t, a data member, + // _M_ref_count, and member functions _M_incr and _M_decr, which perform + // atomic preincrement/predecrement. The constructor initializes + // _M_ref_count. + struct _Refcount_Base + { + // The type _RC_t + typedef size_t _RC_t; + + // The data member _M_ref_count + volatile _RC_t _M_ref_count; + + // Constructor + __gthread_mutex_t _M_ref_count_lock; + + _Refcount_Base(_RC_t __n) : _M_ref_count(__n) + { +#ifdef __GTHREAD_MUTEX_INIT + __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; + _M_ref_count_lock = __tmp; +#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) + __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock); +#else +#error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org. +#endif + } + + void + _M_incr() + { + __gthread_mutex_lock(&_M_ref_count_lock); + ++_M_ref_count; + __gthread_mutex_unlock(&_M_ref_count_lock); + } + + _RC_t + _M_decr() + { + __gthread_mutex_lock(&_M_ref_count_lock); + volatile _RC_t __tmp = --_M_ref_count; + __gthread_mutex_unlock(&_M_ref_count_lock); + return __tmp; + } + }; + + // Atomic swap on unsigned long + // This is guaranteed to behave as though it were atomic only if all + // possibly concurrent updates use _Atomic_swap. + // In some cases the operation is emulated with a lock. +#if defined (__GTHREAD_MUTEX_INIT) + // This could be optimized to use the atomicity.h abstraction layer. + // vyzo: simple _Atomic_swap implementation following the guidelines above + // We use a template here only to get a unique initialized instance. + template<int __dummy> + struct _Swap_lock_struct + { static __gthread_mutex_t _S_swap_lock; }; + + template<int __dummy> + __gthread_mutex_t + _Swap_lock_struct<__dummy>::_S_swap_lock = __GTHREAD_MUTEX_INIT; + + // This should be portable, but performance is expected to be quite + // awful. This really needs platform specific code. + inline unsigned long + _Atomic_swap(unsigned long * __p, unsigned long __q) + { + __gthread_mutex_lock(&_Swap_lock_struct<0>::_S_swap_lock); + unsigned long __result = *__p; + *__p = __q; + __gthread_mutex_unlock(&_Swap_lock_struct<0>::_S_swap_lock); + return __result; + } +#endif + + // Locking class. Note that this class *does not have a + // constructor*. It must be initialized either statically, with + // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling + // the _M_initialize member function. (This is similar to the ways + // that a pthreads mutex can be initialized.) There are explicit + // member functions for acquiring and releasing the lock. + + // There is no constructor because static initialization is + // essential for some uses, and only a class aggregate (see section + // 8.5.1 of the C++ standard) can be initialized that way. That + // means we must have no constructors, no base classes, no virtual + // functions, and no private or protected members. + +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + extern __gthread_mutex_t _GLIBCPP_mutex; + extern __gthread_mutex_t *_GLIBCPP_mutex_address; + extern __gthread_once_t _GLIBCPP_once; + extern void _GLIBCPP_mutex_init (void); + extern void _GLIBCPP_mutex_address_init (void); +#endif + + struct _STL_mutex_lock + { + // The class must be statically initialized with __STL_MUTEX_INITIALIZER. +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + volatile int _M_init_flag; + __gthread_once_t _M_once; +#endif + __gthread_mutex_t _M_lock; + + void + _M_initialize() + { +#ifdef __GTHREAD_MUTEX_INIT + // There should be no code in this path given the usage rules above. +#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) + if (_M_init_flag) return; + if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0 + && __gthread_active_p ()) + abort (); + __gthread_mutex_lock (&_GLIBCPP_mutex); + if (!_M_init_flag) + { + // Even though we have a global lock, we use __gthread_once to be + // absolutely certain the _M_lock mutex is only initialized once on + // multiprocessor systems. + _GLIBCPP_mutex_address = &_M_lock; + if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0 + && __gthread_active_p ()) + abort (); + _M_init_flag = 1; + } + __gthread_mutex_unlock (&_GLIBCPP_mutex); +#endif + } + + void + _M_acquire_lock() + { +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + if (!_M_init_flag) _M_initialize(); +#endif + __gthread_mutex_lock(&_M_lock); + } + + void + _M_release_lock() + { +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + if (!_M_init_flag) _M_initialize(); +#endif + __gthread_mutex_unlock(&_M_lock); + } + }; + +#ifdef __GTHREAD_MUTEX_INIT +#define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } +#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) +#ifdef __GTHREAD_MUTEX_INIT_DEFAULT +#define __STL_MUTEX_INITIALIZER \ + = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT } +#else +#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT } +#endif +#endif + + // A locking class that uses _STL_mutex_lock. The constructor takes a + // reference to an _STL_mutex_lock, and acquires a lock. The + // destructor releases the lock. It's not clear that this is exactly + // the right functionality. It will probably change in the future. + struct _STL_auto_lock + { + _STL_mutex_lock& _M_lock; + + _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) + { _M_lock._M_acquire_lock(); } + + ~_STL_auto_lock() { _M_lock._M_release_lock(); } + + private: + void operator=(const _STL_auto_lock&); + _STL_auto_lock(const _STL_auto_lock&); + }; + +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/stl_tree.h b/contrib/libstdc++/include/bits/stl_tree.h new file mode 100644 index 0000000000000..d2ae142e9265c --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_tree.h @@ -0,0 +1,1462 @@ +// RB tree implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + */ + +/** @file stl_tree.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_TREE_H +#define __GLIBCPP_INTERNAL_TREE_H + +/* + +Red-black tree class, designed for use in implementing STL +associative containers (set, multiset, map, and multimap). The +insertion and deletion algorithms are based on those in Cormen, +Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990), +except that + +(1) the header cell is maintained with links not only to the root +but also to the leftmost node of the tree, to enable constant time +begin(), and to the rightmost node of the tree, to enable linear time +performance when used with the generic set algorithms (set_union, +etc.); + +(2) when a node being deleted has two children its successor node is +relinked into its place, rather than copied, so that the only +iterators invalidated are those referring to the deleted node. + +*/ + +#include <bits/stl_algobase.h> +#include <bits/stl_alloc.h> +#include <bits/stl_construct.h> +#include <bits/stl_function.h> + +namespace std +{ + enum _Rb_tree_color { _M_red = false, _M_black = true }; + + 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; + } + + static _Base_ptr + _S_maximum(_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __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 + { + 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; + } + + _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) + { + _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 = _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); + } + } + } + __root->_M_color = _M_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; + } + 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 + } + 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; + } + + // 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; + } + + _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; + } + + 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; + } + + ~_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()); + } + + 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()); + } + + 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; + } + + 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; + } + } + + 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) + { + for ( ; __first != __last; ++__first) + insert_equal(*__first); + } + + 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); + } + + 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; + } + + 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; + } + + 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; + } + + 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; + } + } + + 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++); + } + + 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++); + } + + 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. + + 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; + } + + 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 + { + pair<const_iterator, const_iterator> __p = equal_range(__k); + size_type __n = distance(__p.first, __p.second); + return __n; + } + + 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)); + } + + 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; + } + + 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 == _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 (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) + return false; + return true; + } +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/stl_uninitialized.h b/contrib/libstdc++/include/bits/stl_uninitialized.h new file mode 100644 index 0000000000000..b5f7b8c40b697 --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_uninitialized.h @@ -0,0 +1,290 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_uninitialized.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STL_UNINITIALIZED_H +#define _CPP_BITS_STL_UNINITIALIZED_H 1 + +#include <cstring> + +namespace std +{ + + // uninitialized_copy + + template<typename _InputIter, typename _ForwardIter> + inline _ForwardIter + __uninitialized_copy_aux(_InputIter __first, _InputIter __last, + _ForwardIter __result, + __true_type) + { return copy(__first, __last, __result); } + + template<typename _InputIter, typename _ForwardIter> + _ForwardIter + __uninitialized_copy_aux(_InputIter __first, _InputIter __last, + _ForwardIter __result, + __false_type) + { + _ForwardIter __cur = __result; + try { + for ( ; __first != __last; ++__first, ++__cur) + _Construct(&*__cur, *__first); + return __cur; + } + catch(...) + { + _Destroy(__result, __cur); + __throw_exception_again; + } + } + + /** + * @brief Copies the range [first,last) into result. + * @param first An input iterator. + * @param last An input iterator. + * @param result An output iterator. + * @return result + (first - last) + * + * Like copy(), but does not require an initialized output range. + */ + template<typename _InputIter, typename _ForwardIter> + inline _ForwardIter + uninitialized_copy(_InputIter __first, _InputIter __last, _ForwardIter __result) + { + 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()); + } + + inline char* + uninitialized_copy(const char* __first, const char* __last, char* __result) + { + memmove(__result, __first, __last - __first); + return __result + (__last - __first); + } + + inline wchar_t* + uninitialized_copy(const wchar_t* __first, const wchar_t* __last, + wchar_t* __result) + { + memmove(__result, __first, sizeof(wchar_t) * (__last - __first)); + return __result + (__last - __first); + } + + // Valid if copy construction is equivalent to assignment, and if the + // destructor is trivial. + template<typename _ForwardIter, typename _Tp> + inline void + __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, + const _Tp& __x, __true_type) + { fill(__first, __last, __x); } + + template<typename _ForwardIter, typename _Tp> + void + __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last, + const _Tp& __x, __false_type) + { + _ForwardIter __cur = __first; + try { + for ( ; __cur != __last; ++__cur) + _Construct(&*__cur, __x); + } + catch(...) + { + _Destroy(__first, __cur); + __throw_exception_again; + } + } + + /** + * @brief Copies the value x into the range [first,last). + * @param first An input iterator. + * @param last An input iterator. + * @param x The source value. + * @return Nothing. + * + * Like fill(), but does not require an initialized output range. + */ + template<typename _ForwardIter, typename _Tp> + inline void + uninitialized_fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename __type_traits<_ValueType>::is_POD_type _Is_POD; + __uninitialized_fill_aux(__first, __last, __x, _Is_POD()); + } + + // Valid if copy construction is equivalent to assignment, and if the + // destructor is trivial. + template<typename _ForwardIter, typename _Size, typename _Tp> + inline _ForwardIter + __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, + const _Tp& __x, __true_type) + { + return fill_n(__first, __n, __x); + } + + template<typename _ForwardIter, typename _Size, typename _Tp> + _ForwardIter + __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n, + const _Tp& __x, __false_type) + { + _ForwardIter __cur = __first; + try { + for ( ; __n > 0; --__n, ++__cur) + _Construct(&*__cur, __x); + return __cur; + } + catch(...) + { + _Destroy(__first, __cur); + __throw_exception_again; + } + } + + /** + * @brief Copies the value x into the range [first,first+n). + * @param first An input iterator. + * @param n The number of copies to make. + * @param x The source value. + * @return first+n + * + * Like fill_n(), but does not require an initialized output range. + */ + template<typename _ForwardIter, typename _Size, typename _Tp> + inline _ForwardIter + uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIter>::value_type _ValueType; + typedef typename __type_traits<_ValueType>::is_POD_type _Is_POD; + return __uninitialized_fill_n_aux(__first, __n, __x, _Is_POD()); + } + + // Extensions: __uninitialized_copy_copy, __uninitialized_copy_fill, + // __uninitialized_fill_copy. + + // __uninitialized_copy_copy + // Copies [first1, last1) into [result, result + (last1 - first1)), and + // copies [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + + template<typename _InputIter1, typename _InputIter2, typename _ForwardIter> + inline _ForwardIter + __uninitialized_copy_copy(_InputIter1 __first1, _InputIter1 __last1, + _InputIter2 __first2, _InputIter2 __last2, + _ForwardIter __result) + { + _ForwardIter __mid = uninitialized_copy(__first1, __last1, __result); + try { + return uninitialized_copy(__first2, __last2, __mid); + } + catch(...) + { + _Destroy(__result, __mid); + __throw_exception_again; + } + } + + // __uninitialized_fill_copy + // Fills [result, mid) with x, and copies [first, last) into + // [mid, mid + (last - first)). + template<typename _ForwardIter, typename _Tp, typename _InputIter> + inline _ForwardIter + __uninitialized_fill_copy(_ForwardIter __result, _ForwardIter __mid, + const _Tp& __x, + _InputIter __first, _InputIter __last) + { + uninitialized_fill(__result, __mid, __x); + try { + return uninitialized_copy(__first, __last, __mid); + } + catch(...) + { + _Destroy(__result, __mid); + __throw_exception_again; + } + } + + // __uninitialized_copy_fill + // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and + // fills [first2 + (last1 - first1), last2) with x. + template<typename _InputIter, typename _ForwardIter, typename _Tp> + inline void + __uninitialized_copy_fill(_InputIter __first1, _InputIter __last1, + _ForwardIter __first2, _ForwardIter __last2, + const _Tp& __x) + { + _ForwardIter __mid2 = uninitialized_copy(__first1, __last1, __first2); + try { + uninitialized_fill(__mid2, __last2, __x); + } + catch(...) + { + _Destroy(__first2, __mid2); + __throw_exception_again; + } + } + +} // namespace std + +#endif /* _CPP_BITS_STL_UNINITIALIZED_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stl_vector.h b/contrib/libstdc++/include/bits/stl_vector.h new file mode 100644 index 0000000000000..5e2ea54d9135d --- /dev/null +++ b/contrib/libstdc++/include/bits/stl_vector.h @@ -0,0 +1,1083 @@ +// Vector implementation -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file stl_vector.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef __GLIBCPP_INTERNAL_VECTOR_H +#define __GLIBCPP_INTERNAL_VECTOR_H + +#include <bits/stl_iterator_base_funcs.h> +#include <bits/functexcept.h> +#include <bits/concept_check.h> + +namespace std +{ + +// The vector base class serves 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. + +// Base class for ordinary allocators. +template <class _Tp, class _Allocator, bool _IsStatic> +class _Vector_alloc_base { +public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + allocator_type get_allocator() const { return _M_data_allocator; } + + _Vector_alloc_base(const allocator_type& __a) + : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) + {} + +protected: + allocator_type _M_data_allocator; + _Tp* _M_start; + _Tp* _M_finish; + _Tp* _M_end_of_storage; + + _Tp* _M_allocate(size_t __n) + { return _M_data_allocator.allocate(__n); } + void _M_deallocate(_Tp* __p, size_t __n) + { if (__p) _M_data_allocator.deallocate(__p, __n); } +}; + +// Specialization for allocators that have the property that we don't +// actually have to store an allocator object. +template <class _Tp, class _Allocator> +class _Vector_alloc_base<_Tp, _Allocator, true> { +public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + allocator_type get_allocator() const { return allocator_type(); } + + _Vector_alloc_base(const allocator_type&) + : _M_start(0), _M_finish(0), _M_end_of_storage(0) + {} + +protected: + _Tp* _M_start; + _Tp* _M_finish; + _Tp* _M_end_of_storage; + + typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; + _Tp* _M_allocate(size_t __n) + { return _Alloc_type::allocate(__n); } + void _M_deallocate(_Tp* __p, size_t __n) + { _Alloc_type::deallocate(__p, __n);} +}; + +template <class _Tp, class _Alloc> +struct _Vector_base + : public _Vector_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> +{ + typedef _Vector_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + + _Vector_base(const allocator_type& __a) : _Base(__a) {} + _Vector_base(size_t __n, const allocator_type& __a) : _Base(__a) { + _M_start = _M_allocate(__n); + _M_finish = _M_start; + _M_end_of_storage = _M_start + __n; + } + + ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } +}; + + +/** + * @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. + * Subscripting ( [] ) access is also provided as with C-style arrays. +*/ +template <class _Tp, class _Alloc = allocator<_Tp> > +class vector : protected _Vector_base<_Tp, _Alloc> +{ + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + +private: + typedef _Vector_base<_Tp, _Alloc> _Base; + typedef vector<_Tp, _Alloc> vector_type; +public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + 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; + typedef ptrdiff_t difference_type; + + typedef typename _Base::allocator_type allocator_type; + allocator_type get_allocator() const { return _Base::get_allocator(); } + + typedef reverse_iterator<const_iterator> const_reverse_iterator; + typedef reverse_iterator<iterator> reverse_iterator; + +protected: + using _Base::_M_allocate; + using _Base::_M_deallocate; + using _Base::_M_start; + using _Base::_M_finish; + using _Base::_M_end_of_storage; + +protected: + void _M_insert_aux(iterator __position, const _Tp& __x); + void _M_insert_aux(iterator __position); + +public: + /** + * Returns a read/write iterator that points to the first element in the + * vector. Iteration is done in ordinary element order. + */ + iterator begin() { return iterator (_M_start); } + + /** + * Returns a read-only (constant) iterator that points to the first element + * in the vector. Iteration is done in ordinary element order. + */ + const_iterator begin() const + { return const_iterator (_M_start); } + + /** + * Returns a read/write iterator that points one past the last element in + * the vector. Iteration is done in ordinary element order. + */ + iterator end() { return iterator (_M_finish); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the vector. Iteration is done in ordinary element order. + */ + const_iterator end() const { return const_iterator (_M_finish); } + + /** + * Returns a read/write reverse iterator that points to the last element in + * the vector. Iteration is done in reverse element order. + */ + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * element in the vector. Iteration is done in reverse element order. + */ + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first element in the vector. Iteration is done in reverse element + * order. + */ + reverse_iterator rend() + { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the vector. Iteration is done in reverse + * element order. + */ + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + /** Returns the number of elements in the vector. */ + size_type size() const + { return size_type(end() - begin()); } + + /** Returns the size of the largest possible vector. */ + size_type max_size() const + { return size_type(-1) / sizeof(_Tp); } + + /** + * Returns the amount of memory that has been alocated for the current + * elements (?). + */ + size_type capacity() const + { return size_type(const_iterator(_M_end_of_storage) - begin()); } + + /** + * Returns true if the vector is empty. (Thus begin() would equal end().) + */ + bool empty() const + { return begin() == end(); } + + /** + * @brief Subscript access to the data contained in the vector. + * @param n The element for which data should be accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + reference operator[](size_type __n) { return *(begin() + __n); } + + /** + * @brief Subscript access to the data contained in the vector. + * @param n The element for which data should be accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + const_reference operator[](size_type __n) const { return *(begin() + __n); } + + void _M_range_check(size_type __n) const { + if (__n >= this->size()) + __throw_out_of_range("vector"); + } + + /** + * @brief Provides access to the data contained in the vector. + * @param n The element for which data should be accessed. + * @return Read/write reference to data. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the vector. The function throws + * out_of_range if the check fails. + */ + reference at(size_type __n) + { _M_range_check(__n); return (*this)[__n]; } + + /** + * @brief Provides access to the data contained in the vector. + * @param n The element for which data should be accessed. + * @return Read-only (constant) reference to data. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the vector. The function throws + * out_of_range if the check fails. + */ + const_reference at(size_type __n) const + { _M_range_check(__n); return (*this)[__n]; } + + + explicit vector(const allocator_type& __a = allocator_type()) + : _Base(__a) {} + + vector(size_type __n, const _Tp& __value, + const allocator_type& __a = allocator_type()) + : _Base(__n, __a) + { _M_finish = uninitialized_fill_n(_M_start, __n, __value); } + + explicit vector(size_type __n) + : _Base(__n, allocator_type()) + { _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); } + + vector(const vector<_Tp, _Alloc>& __x) + : _Base(__x.size(), __x.get_allocator()) + { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); } + + // Check whether it's an integral type. If so, it's not an iterator. + template <class _InputIterator> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_initialize_aux(__first, __last, _Integral()); + } + + template <class _Integer> + void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) + { + _M_start = _M_allocate(__n); + _M_end_of_storage = _M_start + __n; + _M_finish = uninitialized_fill_n(_M_start, __n, __value); + } + + template<class _InputIterator> + void + _M_initialize_aux(_InputIterator __first, _InputIterator __last, __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; + _M_range_initialize(__first, __last, _IterCategory()); + } + + ~vector() + { _Destroy(_M_start, _M_finish); } + + vector<_Tp, _Alloc>& operator=(const vector<_Tp, _Alloc>& __x); + + /** + * @brief Attempt to preallocate enough memory for specified number of + * elements. + * @param n Number of elements required + * + * This function attempts to reserve enough memory for the vector to hold + * the specified number of elements. If the number requested is more than + * max_size() length_error is thrown. + * + * The advantage of this function is that if optimal code is a necessity + * and the user can determine the number of elements that will be required + * the user can reserve the memory and thus prevent a possible + * reallocation of memory and copy of vector data. + */ + void reserve(size_type __n) { + if (capacity() < __n) { + const size_type __old_size = size(); + pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __tmp; + _M_finish = __tmp + __old_size; + _M_end_of_storage = _M_start + __n; + } + } + + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + /** + * @brief Assigns a given value or range to a vector. + * @param n Number of elements to be assigned. + * @param val Value to be assigned. + * + * This function can be used to assign a range to a vector or fill it + * with a specified number of copies of the given value. + * Note that the assignment completely changes the vector and that the + * resulting vector's size is the same as the number of elements assigned. + * Old data may be lost. + */ + void assign(size_type __n, const _Tp& __val) { _M_fill_assign(__n, __val); } + void _M_fill_assign(size_type __n, const _Tp& __val); + + template<class _InputIterator> + void + 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); } + + template<class _InputIter> + void + _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) + { + 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); + + template <class _ForwardIterator> + 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 + * vector. + */ + reference front() { return *begin(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the vector. + */ + const_reference front() const { return *begin(); } + + /** + * Returns a read/write reference to the data at the last element of the + * vector. + */ + reference back() { return *(end() - 1); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the vector. + */ + const_reference back() const { return *(end() - 1); } + + /** + * @brief Add data to the end of the vector. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the end of the vector and assigns the given data to it. + * Due to the nature of a vector this operation can be done in constant + * time if the vector has preallocated space available. + */ + void + push_back(const _Tp& __x) + { + if (_M_finish != _M_end_of_storage) { + _Construct(_M_finish, __x); + ++_M_finish; + } + else + _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() + { + if (_M_finish != _M_end_of_storage) { + _Construct(_M_finish); + ++_M_finish; + } + else + _M_insert_aux(end()); + } +#endif + + void + swap(vector<_Tp, _Alloc>& __x) + { + std::swap(_M_start, __x._M_start); + std::swap(_M_finish, __x._M_finish); + std::swap(_M_end_of_storage, __x._M_end_of_storage); + } + + /** + * @brief Inserts given value into vector at specified element. + * @param position An iterator that points to the element where data + * should be inserted. + * @param x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert the given value into the specified location. + * Note that this kind of operation could be expensive for a vector and if + * it is frequently used the user should consider using std::list. + */ + iterator + insert(iterator __position, const _Tp& __x) + { + size_type __n = __position - begin(); + if (_M_finish != _M_end_of_storage && __position == end()) { + _Construct(_M_finish, __x); + ++_M_finish; + } + else + _M_insert_aux(iterator(__position), __x); + return begin() + __n; + } + + /** + * @brief Inserts an empty element into the vector. + * @param position An iterator that points to the element where empty + * element should be inserted. + * @param x Data to be inserted. + * @return An iterator that points to the inserted element. + * + * This function will insert an empty element into the specified location. + * Note that this kind of operation could be expensive for a vector and if + * it is frequently used the user should consider using std::list. + */ + iterator + insert(iterator __position) + { + size_type __n = __position - begin(); + if (_M_finish != _M_end_of_storage && __position == end()) { + _Construct(_M_finish); + ++_M_finish; + } + else + _M_insert_aux(iterator(__position)); + return begin() + __n; + } + + // Check whether it's an integral type. If so, it's not an iterator. + template<class _InputIterator> + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__pos, __first, __last, _Integral()); + } + + template <class _Integer> + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, __true_type) + { _M_fill_insert(__pos, static_cast<size_type>(__n), static_cast<_Tp>(__val)); } + + template<class _InputIterator> + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; + _M_range_insert(__pos, __first, __last, _IterCategory()); + } + + /** + * @brief Inserts a number of copies of given data into the vector. + * @param position An iterator that points to the element where data + * should be inserted. + * @param n Amount of elements to be inserted. + * @param x Data to be inserted. + * + * This function will insert a specified number of copies of the given data + * into the specified location. + * + * Note that this kind of operation could be expensive for a vector and if + * it is frequently used the user should consider using std::list. + */ + void insert (iterator __pos, size_type __n, const _Tp& __x) + { _M_fill_insert(__pos, __n, __x); } + + void _M_fill_insert (iterator __pos, size_type __n, const _Tp& __x); + + /** + * @brief Removes last element from vector. + * + * This is a typical stack operation. It allows us to shrink the vector by + * one. + * + * Note that no data is returned and if last element's data is needed it + * should be retrieved before pop_back() is called. + */ + void pop_back() { + --_M_finish; + _Destroy(_M_finish); + } + + /** + * @brief Remove element at given position + * @param position Iterator pointing to element to be erased. + * @return Doc Me! (Iterator pointing to new element at old location?) + * + * This function will erase the element at the given position and thus + * shorten the vector by one. + * + * Note This operation could be expensive and if it is frequently used the + * user should consider using std::list. The user is also cautioned that + * this function only erases the element, and that if the element is itself + * a pointer, the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibilty. + */ + iterator erase(iterator __position) { + if (__position + 1 != end()) + copy(__position + 1, end(), __position); + --_M_finish; + _Destroy(_M_finish); + return __position; + } + + /** + * @brief Remove a range of elements from a vector. + * @param first Iterator pointing to the first element to be erased. + * @param last Iterator pointing to the last element to be erased. + * @return Doc Me! (Iterator pointing to new element at old location?) + * + * This function will erase the elements in the given range and shorten the + * vector accordingly. + * + * Note This operation could be expensive and if it is frequently used the + * user should consider using std::list. The user is also cautioned that + * this function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + iterator erase(iterator __first, iterator __last) { + iterator __i(copy(__last, end(), __first)); + _Destroy(__i, end()); + _M_finish = _M_finish - (__last - __first); + return __first; + } + + /** + * @brief Resizes the vector to the specified number of elements. + * @param new_size Number of elements the vector should contain. + * @param x Data with which new elements should be populated. + * + * This function will resize the vector to the specified number of + * elements. If the number is smaller than the vector's current size the + * vector is truncated, otherwise the vector is extended and new elements + * are populated with given data. + */ + void resize(size_type __new_size, const _Tp& __x) { + if (__new_size < size()) + erase(begin() + __new_size, end()); + else + insert(end(), __new_size - size(), __x); + } + + /** + * @brief Resizes the vector to the specified number of elements. + * @param new_size Number of elements the vector should contain. + * + * This function will resize the vector to the specified number of + * elements. If the number is smaller than the vector's current size the + * vector is truncated, otherwise the vector is extended and new elements + * are left uninitialized. + */ + void resize(size_type __new_size) { resize(__new_size, _Tp()); } + + /** + * Erases all elements in vector. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void clear() { erase(begin(), end()); } + +protected: + + template <class _ForwardIterator> + pointer _M_allocate_and_copy(size_type __n, _ForwardIterator __first, + _ForwardIterator __last) + { + pointer __result = _M_allocate(__n); + try { + uninitialized_copy(__first, __last, __result); + return __result; + } + catch(...) + { + _M_deallocate(__result, __n); + __throw_exception_again; + } + } + + template <class _InputIterator> + void _M_range_initialize(_InputIterator __first, + _InputIterator __last, input_iterator_tag) + { + for ( ; __first != __last; ++__first) + push_back(*__first); + } + + // This function is only called by the constructor. + template <class _ForwardIterator> + void _M_range_initialize(_ForwardIterator __first, + _ForwardIterator __last, forward_iterator_tag) + { + size_type __n = distance(__first, __last); + _M_start = _M_allocate(__n); + _M_end_of_storage = _M_start + __n; + _M_finish = uninitialized_copy(__first, __last, _M_start); + } + + template <class _InputIterator> + void _M_range_insert(iterator __pos, + _InputIterator __first, _InputIterator __last, + input_iterator_tag); + + template <class _ForwardIterator> + void _M_range_insert(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); +}; + +template <class _Tp, class _Alloc> +inline bool +operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) +{ + return __x.size() == __y.size() && + equal(__x.begin(), __x.end(), __y.begin()); +} + +template <class _Tp, class _Alloc> +inline bool +operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) +{ + return lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); +} + +template <class _Tp, class _Alloc> +inline void swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) +{ + __x.swap(__y); +} + +template <class _Tp, class _Alloc> +inline bool +operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { + return !(__x == __y); +} + +template <class _Tp, class _Alloc> +inline bool +operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { + return __y < __x; +} + +template <class _Tp, class _Alloc> +inline bool +operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { + return !(__y < __x); +} + +template <class _Tp, class _Alloc> +inline bool +operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { + return !(__x < __y); +} + +template <class _Tp, class _Alloc> +vector<_Tp,_Alloc>& +vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x) +{ + if (&__x != this) { + const size_type __xlen = __x.size(); + if (__xlen > capacity()) { + pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end()); + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __tmp; + _M_end_of_storage = _M_start + __xlen; + } + else if (size() >= __xlen) { + iterator __i(copy(__x.begin(), __x.end(), begin())); + _Destroy(__i, end()); + } + else { + copy(__x.begin(), __x.begin() + size(), _M_start); + uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish); + } + _M_finish = _M_start + __xlen; + } + return *this; +} + +template <class _Tp, class _Alloc> +void vector<_Tp, _Alloc>::_M_fill_assign(size_t __n, const value_type& __val) +{ + if (__n > capacity()) { + vector<_Tp, _Alloc> __tmp(__n, __val, get_allocator()); + __tmp.swap(*this); + } + else if (__n > size()) { + fill(begin(), end(), __val); + _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val); + } + else + erase(fill_n(begin(), __n, __val), end()); +} + +template <class _Tp, class _Alloc> template <class _InputIter> +void vector<_Tp, _Alloc>::_M_assign_aux(_InputIter __first, _InputIter __last, + input_iterator_tag) { + iterator __cur(begin()); + for ( ; __first != __last && __cur != end(); ++__cur, ++__first) + *__cur = *__first; + if (__first == __last) + erase(__cur, end()); + else + insert(end(), __first, __last); +} + +template <class _Tp, class _Alloc> template <class _ForwardIter> +void +vector<_Tp, _Alloc>::_M_assign_aux(_ForwardIter __first, _ForwardIter __last, + forward_iterator_tag) { + size_type __len = distance(__first, __last); + + if (__len > capacity()) { + pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __tmp; + _M_end_of_storage = _M_finish = _M_start + __len; + } + else if (size() >= __len) { + iterator __new_finish(copy(__first, __last, _M_start)); + _Destroy(__new_finish, end()); + _M_finish = __new_finish.base(); + } + else { + _ForwardIter __mid = __first; + advance(__mid, size()); + copy(__first, __mid, _M_start); + _M_finish = uninitialized_copy(__mid, __last, _M_finish); + } +} + +template <class _Tp, class _Alloc> +void +vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x) +{ + if (_M_finish != _M_end_of_storage) { + _Construct(_M_finish, *(_M_finish - 1)); + ++_M_finish; + _Tp __x_copy = __x; + copy_backward(__position, iterator(_M_finish - 2), iterator(_M_finish- 1)); + *__position = __x_copy; + } + else { + const size_type __old_size = size(); + const size_type __len = __old_size != 0 ? 2 * __old_size : 1; + iterator __new_start(_M_allocate(__len)); + iterator __new_finish(__new_start); + try { + __new_finish = uninitialized_copy(iterator(_M_start), __position, + __new_start); + _Construct(__new_finish.base(), __x); + ++__new_finish; + __new_finish = uninitialized_copy(__position, iterator(_M_finish), + __new_finish); + } + catch(...) + { + _Destroy(__new_start,__new_finish); + _M_deallocate(__new_start.base(),__len); + __throw_exception_again; + } + _Destroy(begin(), end()); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __new_start.base(); + _M_finish = __new_finish.base(); + _M_end_of_storage = __new_start.base() + __len; + } +} + +template <class _Tp, class _Alloc> +void +vector<_Tp, _Alloc>::_M_insert_aux(iterator __position) +{ + if (_M_finish != _M_end_of_storage) { + _Construct(_M_finish, *(_M_finish - 1)); + ++_M_finish; + copy_backward(__position, iterator(_M_finish - 2), + iterator(_M_finish - 1)); + *__position = _Tp(); + } + else { + const size_type __old_size = size(); + const size_type __len = __old_size != 0 ? 2 * __old_size : 1; + pointer __new_start = _M_allocate(__len); + pointer __new_finish = __new_start; + try { + __new_finish = uninitialized_copy(iterator(_M_start), __position, + __new_start); + _Construct(__new_finish); + ++__new_finish; + __new_finish = uninitialized_copy(__position, iterator(_M_finish), + __new_finish); + } + catch(...) + { + _Destroy(__new_start,__new_finish); + _M_deallocate(__new_start,__len); + __throw_exception_again; + } + _Destroy(begin(), end()); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __new_start; + _M_finish = __new_finish; + _M_end_of_storage = __new_start + __len; + } +} + +template <class _Tp, class _Alloc> +void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n, + const _Tp& __x) +{ + if (__n != 0) { + if (size_type(_M_end_of_storage - _M_finish) >= __n) { + _Tp __x_copy = __x; + const size_type __elems_after = end() - __position; + iterator __old_finish(_M_finish); + if (__elems_after > __n) { + uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); + _M_finish += __n; + copy_backward(__position, __old_finish - __n, __old_finish); + fill(__position, __position + __n, __x_copy); + } + else { + uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); + _M_finish += __n - __elems_after; + uninitialized_copy(__position, __old_finish, _M_finish); + _M_finish += __elems_after; + fill(__position, __old_finish, __x_copy); + } + } + else { + const size_type __old_size = size(); + const size_type __len = __old_size + max(__old_size, __n); + iterator __new_start(_M_allocate(__len)); + iterator __new_finish(__new_start); + try { + __new_finish = uninitialized_copy(begin(), __position, __new_start); + __new_finish = uninitialized_fill_n(__new_finish, __n, __x); + __new_finish + = uninitialized_copy(__position, end(), __new_finish); + } + catch(...) + { + _Destroy(__new_start,__new_finish); + _M_deallocate(__new_start.base(),__len); + __throw_exception_again; + } + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __new_start.base(); + _M_finish = __new_finish.base(); + _M_end_of_storage = __new_start.base() + __len; + } + } +} + +template <class _Tp, class _Alloc> template <class _InputIterator> +void +vector<_Tp, _Alloc>::_M_range_insert(iterator __pos, + _InputIterator __first, + _InputIterator __last, + input_iterator_tag) +{ + for ( ; __first != __last; ++__first) { + __pos = insert(__pos, *__first); + ++__pos; + } +} + +template <class _Tp, class _Alloc> template <class _ForwardIterator> +void +vector<_Tp, _Alloc>::_M_range_insert(iterator __position, + _ForwardIterator __first, + _ForwardIterator __last, + forward_iterator_tag) +{ + if (__first != __last) { + size_type __n = distance(__first, __last); + if (size_type(_M_end_of_storage - _M_finish) >= __n) { + const size_type __elems_after = end() - __position; + iterator __old_finish(_M_finish); + if (__elems_after > __n) { + uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); + _M_finish += __n; + copy_backward(__position, __old_finish - __n, __old_finish); + copy(__first, __last, __position); + } + else { + _ForwardIterator __mid = __first; + advance(__mid, __elems_after); + uninitialized_copy(__mid, __last, _M_finish); + _M_finish += __n - __elems_after; + uninitialized_copy(__position, __old_finish, _M_finish); + _M_finish += __elems_after; + copy(__first, __mid, __position); + } + } + else { + const size_type __old_size = size(); + const size_type __len = __old_size + max(__old_size, __n); + iterator __new_start(_M_allocate(__len)); + iterator __new_finish(__new_start); + try { + __new_finish = uninitialized_copy(iterator(_M_start), + __position, __new_start); + __new_finish = uninitialized_copy(__first, __last, __new_finish); + __new_finish + = uninitialized_copy(__position, iterator(_M_finish), __new_finish); + } + catch(...) + { + _Destroy(__new_start,__new_finish); + _M_deallocate(__new_start.base(), __len); + __throw_exception_again; + } + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __new_start.base(); + _M_finish = __new_finish.base(); + _M_end_of_storage = __new_start.base() + __len; + } + } +} + +} // namespace std + +#endif /* __GLIBCPP_INTERNAL_VECTOR_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/stream_iterator.h b/contrib/libstdc++/include/bits/stream_iterator.h new file mode 100644 index 0000000000000..4897fc36fefb4 --- /dev/null +++ b/contrib/libstdc++/include/bits/stream_iterator.h @@ -0,0 +1,156 @@ +// Stream iterators + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file stream_iterator.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STREAM_ITERATOR_H +#define _CPP_BITS_STREAM_ITERATOR_H 1 + +#pragma GCC system_header + +namespace std +{ + template<typename _Tp, typename _CharT = char, + typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t> + class istream_iterator + : public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&> + { + public: + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_istream<_CharT, _Traits> istream_type; + + private: + istream_type* _M_stream; + _Tp _M_value; + bool _M_ok; + + public: + istream_iterator() : _M_stream(0), _M_ok(false) {} + + istream_iterator(istream_type& __s) : _M_stream(&__s) { _M_read(); } + + istream_iterator(const istream_iterator& __obj) + : _M_stream(__obj._M_stream), _M_value(__obj._M_value), + _M_ok(__obj._M_ok) + { } + + const _Tp& + operator*() const { return _M_value; } + + const _Tp* + operator->() const { return &(operator*()); } + + istream_iterator& + operator++() + { _M_read(); return *this; } + + istream_iterator + operator++(int) + { + istream_iterator __tmp = *this; + _M_read(); + return __tmp; + } + + bool + _M_equal(const istream_iterator& __x) const + { return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream);} + + private: + void + _M_read() + { + _M_ok = (_M_stream && *_M_stream) ? true : false; + if (_M_ok) + { + *_M_stream >> _M_value; + _M_ok = *_M_stream ? true : false; + } + } + }; + + template<typename _Tp, typename _CharT, typename _Traits, typename _Dist> + inline bool + operator==(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x, + const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y) + { return __x._M_equal(__y); } + + template <class _Tp, class _CharT, class _Traits, class _Dist> + inline bool + operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x, + const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y) + { return !__x._M_equal(__y); } + + + template<typename _Tp, typename _CharT = char, + typename _Traits = char_traits<_CharT> > + class ostream_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + public: + typedef _CharT char_type; + typedef _Traits traits_type; + typedef basic_ostream<_CharT, _Traits> ostream_type; + + private: + ostream_type* _M_stream; + const _CharT* _M_string; + + public: + ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {} + + ostream_iterator(ostream_type& __s, const _CharT* __c) + : _M_stream(&__s), _M_string(__c) { } + + ostream_iterator(const ostream_iterator& __obj) + : _M_stream(__obj._M_stream), _M_string(__obj._M_string) { } + + ostream_iterator& + operator=(const _Tp& __value) + { + *_M_stream << __value; + if (_M_string) *_M_stream << _M_string; + return *this; + } + + ostream_iterator& + operator*() { return *this; } + + ostream_iterator& + operator++() { return *this; } + + ostream_iterator& + operator++(int) { return *this; } + }; +} // namespace std +#endif diff --git a/contrib/libstdc++/include/bits/streambuf.tcc b/contrib/libstdc++/include/bits/streambuf.tcc new file mode 100644 index 0000000000000..292999cfba318 --- /dev/null +++ b/contrib/libstdc++/include/bits/streambuf.tcc @@ -0,0 +1,250 @@ +// Stream buffer classes -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 27.5 Stream buffers +// + +#ifndef _CPP_BITS_STREAMBUF_TCC +#define _CPP_BITS_STREAMBUF_TCC 1 + +#pragma GCC system_header + +namespace std +{ + template<typename _CharT, typename _Traits> + const typename basic_streambuf<_CharT, _Traits>::int_type + basic_streambuf<_CharT, _Traits>::_S_pback_size; + + template<typename _CharT, typename _Traits> + typename basic_streambuf<_CharT, _Traits>::int_type + basic_streambuf<_CharT, _Traits>:: + sbumpc() + { + int_type __ret; + if (_M_in_cur && _M_in_cur < _M_in_end) + { + char_type __c = *(this->gptr()); + _M_in_cur_move(1); + __ret = traits_type::to_int_type(__c); + } + else + __ret = this->uflow(); + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_streambuf<_CharT, _Traits>::int_type + basic_streambuf<_CharT, _Traits>:: + sputbackc(char_type __c) + { + int_type __ret; + 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)); + else + { + _M_in_cur_move(-1); + __ret = traits_type::to_int_type(*this->gptr()); + } + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_streambuf<_CharT, _Traits>::int_type + basic_streambuf<_CharT, _Traits>:: + sungetc() + { + int_type __ret; + if (_M_in_cur && _M_in_beg < _M_in_cur) + { + _M_in_cur_move(-1); + __ret = traits_type::to_int_type(*_M_in_cur); + } + else + __ret = this->pbackfail(); + return __ret; + } + + // Don't test against _M_buf + _M_buf_size, because _M_buf reflects + // allocated space, and on certain (rare but entirely legal) + // situations, there will be no allocated space yet the internal + // buffers will still be valid. (This happens if setp is used to set + // the internal buffer to say some externally-allocated sequence.) + template<typename _CharT, typename _Traits> + typename basic_streambuf<_CharT, _Traits>::int_type + basic_streambuf<_CharT, _Traits>:: + sputc(char_type __c) + { + int_type __ret; + if (_M_out_buf_size()) + { + *_M_out_cur = __c; + _M_out_cur_move(1); + __ret = traits_type::to_int_type(__c); + } + else + __ret = this->overflow(traits_type::to_int_type(__c)); + return __ret; + } + + template<typename _CharT, typename _Traits> + streamsize + basic_streambuf<_CharT, _Traits>:: + xsgetn(char_type* __s, streamsize __n) + { + streamsize __ret = 0; + while (__ret < __n) + { + size_t __buf_len = _M_in_end - _M_in_cur; + if (__buf_len > 0) + { + size_t __remaining = __n - __ret; + size_t __len = min(__buf_len, __remaining); + traits_type::copy(__s, _M_in_cur, __len); + __ret += __len; + __s += __len; + _M_in_cur_move(__len); + } + + if (__ret < __n) + { + int_type __c = this->uflow(); + if (__c != traits_type::eof()) + { + traits_type::assign(*__s++, traits_type::to_char_type(__c)); + ++__ret; + } + else + break; + } + } + return __ret; + } + + // Don't test against _M_buf + _M_buf_size, because _M_buf reflects + // allocated space, and on certain (rare but entirely legal) + // situations, there will be no allocated space yet the internal + // buffers will still be valid. (This happens if setp is used to set + // the internal buffer to say some externally-allocated sequence.) + template<typename _CharT, typename _Traits> + streamsize + basic_streambuf<_CharT, _Traits>:: + xsputn(const char_type* __s, streamsize __n) + { + streamsize __ret = 0; + while (__ret < __n) + { + off_type __buf_len = _M_out_buf_size(); + if (__buf_len > 0) + { + off_type __remaining = __n - __ret; + off_type __len = min(__buf_len, __remaining); + traits_type::copy(_M_out_cur, __s, __len); + __ret += __len; + __s += __len; + _M_out_cur_move(__len); + } + + if (__ret < __n) + { + int_type __c = this->overflow(traits_type::to_int_type(*__s)); + if (__c != traits_type::eof()) + { + ++__ret; + ++__s; + } + else + break; + } + } + return __ret; + } + + // Conceivably, this could be used to implement buffer-to-buffer + // copies, if this was ever desired in an un-ambiguous way by the + // standard. If so, then checks for __ios being zero would be + // necessary. + template<typename _CharT, typename _Traits> + streamsize + __copy_streambufs(basic_ios<_CharT, _Traits>& __ios, + basic_streambuf<_CharT, _Traits>* __sbin, + basic_streambuf<_CharT, _Traits>* __sbout) + { + typedef typename _Traits::int_type int_type; + + streamsize __ret = 0; + streamsize __bufsize = __sbin->in_avail(); + streamsize __xtrct; + bool __testput = __sbout->_M_mode & ios_base::out; + try + { + while (__testput && __bufsize != -1) + { + __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize); + __ret += __xtrct; + __sbin->_M_in_cur_move(__xtrct); + if (__xtrct == __bufsize) + { + if (__sbin->sgetc() == _Traits::eof()) + break; + __bufsize = __sbin->in_avail(); + } + else + break; + } + } + catch(exception& __fail) + { + __ios.setstate(ios_base::failbit); + if ((__ios.exceptions() & ios_base::failbit) != 0) + __throw_exception_again; + } + return __ret; + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. + extern template class basic_streambuf<char>; + extern template + streamsize + __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*, + basic_streambuf<char>*); + + extern template class basic_streambuf<wchar_t>; + extern template + streamsize + __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*, + basic_streambuf<wchar_t>*); +} // namespace std + +#endif diff --git a/contrib/libstdc++/include/bits/streambuf_iterator.h b/contrib/libstdc++/include/bits/streambuf_iterator.h new file mode 100644 index 0000000000000..659caecb2aff2 --- /dev/null +++ b/contrib/libstdc++/include/bits/streambuf_iterator.h @@ -0,0 +1,201 @@ +// Streambuf iterators + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// XXX Should specialize copy, find algorithms for streambuf iterators. + +/** @file streambuf_iterator.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STREAMBUF_ITERATOR_H +#define _CPP_BITS_STREAMBUF_ITERATOR_H 1 + +#pragma GCC system_header + +namespace std +{ + // 24.5.3 Template class istreambuf_iterator + template<typename _CharT, typename _Traits> + class istreambuf_iterator + : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type, + _CharT*, _CharT&> + { + public: + // Types: + typedef _CharT char_type; + typedef _Traits traits_type; + typedef typename _Traits::int_type int_type; + typedef basic_streambuf<_CharT, _Traits> streambuf_type; + typedef basic_istream<_CharT, _Traits> istream_type; + + private: + // 24.5.3 istreambuf_iterator + // p 1 + // If the end of stream is reached (streambuf_type::sgetc() + // returns traits_type::eof()), the iterator becomes equal to + // the "end of stream" iterator value. + // NB: This implementation assumes the "end of stream" value + // is EOF, or -1. + mutable streambuf_type* _M_sbuf; + int_type _M_c; + + public: + istreambuf_iterator() throw() + : _M_sbuf(0), _M_c(-2) { } + + istreambuf_iterator(istream_type& __s) throw() + : _M_sbuf(__s.rdbuf()), _M_c(-2) { } + + istreambuf_iterator(streambuf_type* __s) throw() + : _M_sbuf(__s), _M_c(-2) { } + + // NB: The result of operator*() on an end of stream is undefined. + char_type + operator*() const + { return traits_type::to_char_type(_M_get()); } + + istreambuf_iterator& + operator++() + { + if (_M_sbuf && _M_sbuf->sbumpc() == traits_type::eof()) + _M_sbuf = 0; + else + _M_c = -2; + return *this; + } + + istreambuf_iterator + operator++(int) + { + istreambuf_iterator __old = *this; + if (_M_sbuf && (__old._M_c = _M_sbuf->sbumpc()) == traits_type::eof()) + _M_sbuf = 0; + else + _M_c = -2; + return __old; + } + +#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 + { + const int_type __eof = traits_type::eof(); + bool __thiseof = _M_get() == __eof; + bool __beof = __b._M_get() == __eof; + return (__thiseof && __beof || (!__thiseof && !__beof)); + } +#endif + + private: + int_type + _M_get() const + { + int_type __ret = traits_type::eof(); + if (_M_sbuf) + { + if (_M_c != static_cast<int_type>(-2)) + __ret = _M_c; + else + if ((__ret = _M_sbuf->sgetc()) == traits_type::eof()) + _M_sbuf = 0; + } + return __ret; + } + }; + + template<typename _CharT, typename _Traits> + inline bool + operator==(const istreambuf_iterator<_CharT, _Traits>& __a, + const istreambuf_iterator<_CharT, _Traits>& __b) + { return __a.equal(__b); } + + template<typename _CharT, typename _Traits> + inline bool + 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/contrib/libstdc++/include/bits/stringfwd.h b/contrib/libstdc++/include/bits/stringfwd.h new file mode 100644 index 0000000000000..b7418a67a7ea1 --- /dev/null +++ b/contrib/libstdc++/include/bits/stringfwd.h @@ -0,0 +1,67 @@ +// String support -*- C++ -*- + +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: 21 Strings library +// + +/** @file stringfwd.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_STRINGFWD_H +#define _CPP_BITS_STRINGFWD_H 1 + +#pragma GCC system_header + +#include <bits/c++config.h> + +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<typename _CharT, typename _Traits = char_traits<_CharT>, + typename _Alloc = allocator<_CharT> > + class basic_string; + + typedef basic_string<char> string; + typedef basic_string<wchar_t> wstring; +} // namespace std + +#endif // _CPP_BITS_STRINGFWD_H diff --git a/contrib/libstdc++/include/bits/type_traits.h b/contrib/libstdc++/include/bits/type_traits.h new file mode 100644 index 0000000000000..61bc436927583 --- /dev/null +++ b/contrib/libstdc++/include/bits/type_traits.h @@ -0,0 +1,339 @@ +// Type traits implementation -*- C++ -*- + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file type_traits.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_TYPE_TRAITS_H +#define _CPP_BITS_TYPE_TRAITS_H 1 + +#pragma GCC system_header + +#include <bits/c++config.h> + +/* +This header file provides a framework for allowing compile time dispatch +based on type attributes. This is useful when writing template code. +For example, when making a copy of an array of an unknown type, it helps +to know if the type has a trivial copy constructor or not, to help decide +if a memcpy can be used. + +The class template __type_traits provides a series of typedefs each of +which is either __true_type or __false_type. The argument to +__type_traits can be any type. The typedefs within this template will +attain their correct values by one of these means: + 1. The general instantiation contain conservative values which work + for all types. + 2. Specializations may be declared to make distinctions between types. + 3. Some compilers (such as the Silicon Graphics N32 and N64 compilers) + will automatically provide the appropriate specializations for all + types. + +EXAMPLE: + +//Copy an array of elements which have non-trivial copy constructors +template <class _Tp> void + copy(_Tp* __source,_Tp* __destination,int __n,__false_type); +//Copy an array of elements which have trivial copy constructors. Use memcpy. +template <class _Tp> void + copy(_Tp* __source,_Tp* __destination,int __n,__true_type); + +//Copy an array of any type by using the most efficient copy mechanism +template <class _Tp> inline void copy(_Tp* __source,_Tp* __destination,int __n) { + copy(__source,__destination,__n, + typename __type_traits<_Tp>::has_trivial_copy_constructor()); +} +*/ + +struct __true_type {}; +struct __false_type {}; + +template <class _Tp> +struct __type_traits { + typedef __true_type this_dummy_member_must_be_first; + /* Do not remove this member. It informs a compiler which + automatically specializes __type_traits that this + __type_traits template is special. It just makes sure that + things work if an implementation is using a template + called __type_traits for something unrelated. */ + + /* The following restrictions should be observed for the sake of + compilers which automatically produce type specific specializations + of this class: + - You may reorder the members below if you wish + - You may remove any of the members below if you wish + - You must not rename members without making the corresponding + name change in the compiler + - Members you add will be treated like regular members unless + you add the appropriate support in the compiler. */ + + + typedef __false_type has_trivial_default_constructor; + typedef __false_type has_trivial_copy_constructor; + typedef __false_type has_trivial_assignment_operator; + typedef __false_type has_trivial_destructor; + typedef __false_type is_POD_type; +}; + + +// Provide some specializations. + +template<> struct __type_traits<bool> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<signed char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<unsigned char> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<wchar_t> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<short> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<unsigned short> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<int> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<unsigned int> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<unsigned long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<long long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<unsigned long long> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<float> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<double> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template<> struct __type_traits<long double> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + +template <class _Tp> +struct __type_traits<_Tp*> { + typedef __true_type has_trivial_default_constructor; + typedef __true_type has_trivial_copy_constructor; + typedef __true_type has_trivial_assignment_operator; + typedef __true_type has_trivial_destructor; + typedef __true_type is_POD_type; +}; + + +// The following could be written in terms of numeric_limits. +// We're doing it separately to reduce the number of dependencies. + +template <class _Tp> struct _Is_integer { + typedef __false_type _Integral; +}; + +template<> struct _Is_integer<bool> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<char> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<signed char> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<unsigned char> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<wchar_t> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<short> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<unsigned short> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<int> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<unsigned int> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<long> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<unsigned long> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<long long> { + typedef __true_type _Integral; +}; + +template<> struct _Is_integer<unsigned long long> { + typedef __true_type _Integral; +}; + +template<typename _Tp> struct _Is_normal_iterator { + typedef __false_type _Normal; +}; + +// Forward declaration hack, should really include this from somewhere. +namespace __gnu_cxx +{ + template<typename _Iterator, typename _Container> class __normal_iterator; +} + +template<typename _Iterator, typename _Container> +struct _Is_normal_iterator< __gnu_cxx::__normal_iterator<_Iterator, _Container> > { + typedef __true_type _Normal; +}; + +#endif /* _CPP_BITS_TYPE_TRAITS_H */ + +// Local Variables: +// mode:C++ +// End: diff --git a/contrib/libstdc++/include/bits/valarray_array.h b/contrib/libstdc++/include/bits/valarray_array.h new file mode 100644 index 0000000000000..48dd2aa4d835f --- /dev/null +++ b/contrib/libstdc++/include/bits/valarray_array.h @@ -0,0 +1,630 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +/** @file valarray_array.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_BITS_ARRAY_H +#define _CPP_BITS_ARRAY_H 1 + +#pragma GCC system_header + +#include <bits/c++config.h> +#include <bits/cpp_type_traits.h> +#include <cstdlib> +#include <cstring> +#include <new> + +namespace std +{ + // + // Helper functions on raw pointers + // + + // We get memory by the old fashion way + inline void* + __valarray_get_memory(size_t __n) + { return operator new(__n); } + + template<typename _Tp> + inline _Tp*__restrict__ + __valarray_get_storage(size_t __n) + { + return static_cast<_Tp*__restrict__> + (__valarray_get_memory(__n * sizeof(_Tp))); + } + + // Return memory to the system + inline void + __valarray_release_memory(void* __p) + { operator delete(__p); } + + // Turn a raw-memory into an array of _Tp filled with _Tp() + // This is required in 'valarray<T> v(n);' + template<typename _Tp, bool> + struct _Array_default_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + { while (__b != __e) new(__b++) _Tp(); } + }; + + template<typename _Tp> + struct _Array_default_ctor<_Tp, true> + { + // For fundamental types, it suffices to say 'memset()' + inline static void + _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + { memset(__b, 0, (__e - __b)*sizeof(_Tp)); } + }; + + template<typename _Tp> + inline void + __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + { + _Array_default_ctor<_Tp, __is_fundamental<_Tp>::_M_type>:: + _S_do_it(__b, __e); + } + + // Turn a raw-memory into an array of _Tp filled with __t + // This is the required in valarray<T> v(n, t). Also + // used in valarray<>::resize(). + template<typename _Tp, bool> + struct _Array_init_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t) + { while (__b != __e) new(__b++) _Tp(__t); } + }; + + template<typename _Tp> + struct _Array_init_ctor<_Tp, true> + { + inline static void + _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t) + { while (__b != __e) *__b++ = __t; } + }; + + template<typename _Tp> + inline void + __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e, + const _Tp __t) + { + _Array_init_ctor<_Tp, __is_fundamental<_Tp>::_M_type>:: + _S_do_it(__b, __e, __t); + } + + // + // copy-construct raw array [__o, *) from plain array [__b, __e) + // We can't just say 'memcpy()' + // + template<typename _Tp, bool> + struct _Array_copy_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e, + _Tp* __restrict__ __o) + { while (__b != __e) new(__o++) _Tp(*__b++); } + }; + + template<typename _Tp> + struct _Array_copy_ctor<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e, + _Tp* __restrict__ __o) + { memcpy(__o, __b, (__e - __b)*sizeof(_Tp)); } + }; + + template<typename _Tp> + inline void + __valarray_copy_construct(const _Tp* __restrict__ __b, + const _Tp* __restrict__ __e, + _Tp* __restrict__ __o) + { + _Array_copy_ctor<_Tp, __is_fundamental<_Tp>::_M_type>:: + _S_do_it(__b, __e, __o); + } + + // copy-construct raw array [__o, *) from strided array __a[<__n : __s>] + template<typename _Tp> + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n, + size_t __s, _Tp* __restrict__ __o) + { + if (__is_fundamental<_Tp>::_M_type) + while (__n--) { *__o++ = *__a; __a += __s; } + else + while (__n--) { new(__o++) _Tp(*__a); __a += __s; } + } + + // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]] + template<typename _Tp> + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __o, size_t __n) + { + if (__is_fundamental<_Tp>::_M_type) + while (__n--) *__o++ = __a[*__i++]; + else + while (__n--) new (__o++) _Tp(__a[*__i++]); + } + + // Do the necessary cleanup when we're done with arrays. + template<typename _Tp> + inline void + __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + { + if (!__is_fundamental<_Tp>::_M_type) + while (__b != __e) { __b->~_Tp(); ++__b; } + } + + // Fill a plain array __a[<__n>] with __t + template<typename _Tp> + inline void + __valarray_fill (_Tp* __restrict__ __a, size_t __n, const _Tp& __t) + { while (__n--) *__a++ = __t; } + + // fill strided array __a[<__n-1 : __s>] with __t + template<typename _Tp> + inline void + __valarray_fill (_Tp* __restrict__ __a, size_t __n, + size_t __s, const _Tp& __t) + { for (size_t __i=0; __i<__n; ++__i, __a+=__s) *__a = __t; } + + // fill indir ect array __a[__i[<__n>]] with __i + template<typename _Tp> + inline void + __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i, + size_t __n, const _Tp& __t) + { for (size_t __j=0; __j<__n; ++__j, ++__i) __a[*__i] = __t; } + + // copy plain array __a[<__n>] in __b[<__n>] + // For non-fundamental types, it is wrong to say 'memcpy()' + template<typename _Tp, bool> + struct _Array_copier + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { while (__n--) *__b++ = *__a++; } + }; + + template<typename _Tp> + struct _Array_copier<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { memcpy (__b, __a, __n * sizeof (_Tp)); } + }; + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template<typename _Tp> + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b) + { + _Array_copier<_Tp, __is_fundamental<_Tp>::_M_type>:: + _S_do_it(__a, __n, __b); + } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template<typename _Tp> + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s, + _Tp* __restrict__ __b) + { for (size_t __i=0; __i<__n; ++__i, ++__b, __a += __s) *__b = *__a; } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template<typename _Tp> + inline void + __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b, + size_t __n, size_t __s) + { for (size_t __i=0; __i<__n; ++__i, ++__a, __b+=__s) *__b = *__a; } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template<typename _Tp> + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1, + _Tp* __restrict__ __dst, size_t __s2) + { + for (size_t __i = 0; __i < __n; ++__i) + __dst[__i * __s2] = __src [ __i * __s1]; + } + + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template<typename _Tp> + inline void + __valarray_copy (const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __b, size_t __n) + { for (size_t __j=0; __j<__n; ++__j, ++__b, ++__i) *__b = __a[*__i]; } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template<typename _Tp> + inline void + __valarray_copy (const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b, const size_t* __restrict__ __i) + { for (size_t __j=0; __j<__n; ++__j, ++__a, ++__i) __b[*__i] = *__a; } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template<typename _Tp> + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, + const size_t* __restrict__ __i, + _Tp* __restrict__ __dst, const size_t* __restrict__ __j) + { + for (size_t __k = 0; __k < __n; ++__k) + __dst[*__j++] = __src[*__i++]; + } + + // + // Compute the sum of elements in range [__f, __l) + // This is a naive algorithm. It suffers from cancelling. + // In the future try to specialize + // for _Tp = float, double, long double using a more accurate + // algorithm. + // + template<typename _Tp> + inline _Tp + __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l) + { + _Tp __r = _Tp(); + while (__f != __l) __r += *__f++; + return __r; + } + + // Compute the product of all elements in range [__f, __l) + template<typename _Tp> + inline _Tp + __valarray_product(const _Tp* __restrict__ __f, + const _Tp* __restrict__ __l) + { + _Tp __r = _Tp(1); + while (__f != __l) __r = __r * *__f++; + return __r; + } + + // Compute the min/max of an array-expression + template<typename _Ta> + inline typename _Ta::value_type + __valarray_min(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t < __r) + __r = __t; + } + return __r; + } + + template<typename _Ta> + inline typename _Ta::value_type + __valarray_max(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t > __r) + __r = __t; + } + return __r; + } + + // + // Helper class _Array, first layer of valarray abstraction. + // All operations on valarray should be forwarded to this class + // whenever possible. -- gdr + // + + template<typename _Tp> + struct _Array + { + explicit _Array (size_t); + explicit _Array (_Tp* const __restrict__); + explicit _Array (const valarray<_Tp>&); + _Array (const _Tp* __restrict__, size_t); + + _Tp* begin () const; + + _Tp* const __restrict__ _M_data; + }; + + template<typename _Tp> + inline void + __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t) + { __valarray_fill (__a._M_data, __n, __t); } + + template<typename _Tp> + inline void + __valarray_fill (_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t) + { __valarray_fill (__a._M_data, __n, __s, __t); } + + template<typename _Tp> + inline void + __valarray_fill (_Array<_Tp> __a, _Array<size_t> __i, + size_t __n, const _Tp& __t) + { __valarray_fill (__a._M_data, __i._M_data, __n, __t); } + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) + { __valarray_copy(__a._M_data, __n, __b._M_data); } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b) + { __valarray_copy(__a._M_data, __n, __s, __b._M_data); } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s) + { __valarray_copy(__a._M_data, __b._M_data, __n, __s); } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1, + _Array<_Tp> __b, size_t __s2) + { __valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); } + + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, _Array<size_t> __i, + _Array<_Tp> __b, size_t __n) + { __valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, + _Array<size_t> __i) + { __valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template<typename _Tp> + inline void + __valarray_copy(_Array<_Tp> __src, size_t __n, _Array<size_t> __i, + _Array<_Tp> __dst, _Array<size_t> __j) + { + __valarray_copy(__src._M_data, __n, __i._M_data, + __dst._M_data, __j._M_data); + } + + template<typename _Tp> + inline + _Array<_Tp>::_Array (size_t __n) + : _M_data(__valarray_get_storage<_Tp>(__n)) + { __valarray_default_construct(_M_data, _M_data + __n); } + + template<typename _Tp> + inline + _Array<_Tp>::_Array (_Tp* const __restrict__ __p) : _M_data (__p) {} + + template<typename _Tp> + inline _Array<_Tp>::_Array (const valarray<_Tp>& __v) + : _M_data (__v._M_data) {} + + template<typename _Tp> + inline + _Array<_Tp>::_Array (const _Tp* __restrict__ __b, size_t __s) + : _M_data(__valarray_get_storage<_Tp>(__s)) + { __valarray_copy_construct(__b, __s, _M_data); } + + template<typename _Tp> + inline _Tp* + _Array<_Tp>::begin () const + { return _M_data; } + +#define _DEFINE_ARRAY_FUNCTION(_Op, _Name) \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, const _Tp& __t) \ +{ \ + for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p) \ + *__p _Op##= __t; \ +} \ + \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \ +{ \ + _Tp* __p = __a._M_data; \ + for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__p, ++__q) \ + *__p _Op##= *__q; \ +} \ + \ +template<typename _Tp, class _Dom> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, \ + const _Expr<_Dom,_Tp>& __e, size_t __n) \ +{ \ + _Tp* __p (__a._M_data); \ + for (size_t __i=0; __i<__n; ++__i, ++__p) *__p _Op##= __e[__i]; \ +} \ + \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, size_t __s, \ + _Array<_Tp> __b) \ +{ \ + _Tp* __q (__b._M_data); \ + for (_Tp* __p=__a._M_data; __p<__a._M_data+__s*__n; __p+=__s, ++__q) \ + *__p _Op##= *__q; \ +} \ + \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, _Array<_Tp> __b, \ + size_t __n, size_t __s) \ +{ \ + _Tp* __q (__b._M_data); \ + for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p, __q+=__s) \ + *__p _Op##= *__q; \ +} \ + \ +template<typename _Tp, class _Dom> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __s, \ + const _Expr<_Dom,_Tp>& __e, size_t __n) \ +{ \ + _Tp* __p (__a._M_data); \ + for (size_t __i=0; __i<__n; ++__i, __p+=__s) *__p _Op##= __e[__i]; \ +} \ + \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, _Array<size_t> __i, \ + _Array<_Tp> __b, size_t __n) \ +{ \ + _Tp* __q (__b._M_data); \ + for (size_t* __j=__i._M_data; __j<__i._M_data+__n; ++__j, ++__q) \ + __a._M_data[*__j] _Op##= *__q; \ +} \ + \ +template<typename _Tp> \ +inline void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array<size_t> __i) \ +{ \ + _Tp* __p (__a._M_data); \ + for (size_t* __j=__i._M_data; __j<__i._M_data+__n; ++__j, ++__p) \ + *__p _Op##= __b._M_data[*__j]; \ +} \ + \ +template<typename _Tp, class _Dom> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, _Array<size_t> __i, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ +{ \ + size_t* __j (__i._M_data); \ + for (size_t __k=0; __k<__n; ++__k, ++__j) \ + __a._M_data[*__j] _Op##= __e[__k]; \ +} \ + \ +template<typename _Tp> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, _Array<bool> __m, \ + _Array<_Tp> __b, size_t __n) \ +{ \ + bool* ok (__m._M_data); \ + _Tp* __p (__a._M_data); \ + for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__q, ++ok, ++__p) { \ + while (! *ok) { \ + ++ok; \ + ++__p; \ + } \ + *__p _Op##= *__q; \ + } \ +} \ + \ +template<typename _Tp> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array<bool> __m) \ +{ \ + bool* ok (__m._M_data); \ + _Tp* __q (__b._M_data); \ + for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p, ++ok, ++__q) { \ + while (! *ok) { \ + ++ok; \ + ++__q; \ + } \ + *__p _Op##= *__q; \ + } \ +} \ + \ +template<typename _Tp, class _Dom> \ +void \ +_Array_augmented_##_Name (_Array<_Tp> __a, _Array<bool> __m, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ +{ \ + bool* ok(__m._M_data); \ + _Tp* __p (__a._M_data); \ + for (size_t __i=0; __i<__n; ++__i, ++ok, ++__p) { \ + while (! *ok) { \ + ++ok; \ + ++__p; \ + } \ + *__p _Op##= __e[__i]; \ + } \ +} + + _DEFINE_ARRAY_FUNCTION(+, plus) + _DEFINE_ARRAY_FUNCTION(-, minus) + _DEFINE_ARRAY_FUNCTION(*, multiplies) + _DEFINE_ARRAY_FUNCTION(/, divides) + _DEFINE_ARRAY_FUNCTION(%, modulus) + _DEFINE_ARRAY_FUNCTION(^, xor) + _DEFINE_ARRAY_FUNCTION(|, or) + _DEFINE_ARRAY_FUNCTION(&, and) + _DEFINE_ARRAY_FUNCTION(<<, shift_left) + _DEFINE_ARRAY_FUNCTION(>>, shift_right) + +#undef _DEFINE_VALARRAY_FUNCTION + +} // std:: + +#ifdef _GLIBCPP_NO_TEMPLATE_EXPORT +# define export +# include <bits/valarray_array.tcc> +#endif + +#endif /* _CPP_BITS_ARRAY_H */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/valarray_array.tcc b/contrib/libstdc++/include/bits/valarray_array.tcc new file mode 100644 index 0000000000000..ba4b0830a47ef --- /dev/null +++ b/contrib/libstdc++/include/bits/valarray_array.tcc @@ -0,0 +1,161 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr> + +#ifndef _CPP_BITS_VALARRAY_ARRAY_TCC +#define _CPP_BITS_VALARRAY_ARRAY_TCC 1 + +namespace std +{ + +export template<typename _Tp> +void +__valarray_fill (_Array<_Tp> __a, size_t __n, _Array<bool> __m, const _Tp& __t) +{ + _Tp* __p = __a._M_data; + bool* __ok (__m._M_data); + for (size_t __i=0; __i<__n; ++__i, ++__ok, ++__p) { + while (! *__ok) { + ++__ok; + ++__p; + } + *__p = __t; + } +} + +export template<typename _Tp> +void +__valarray_copy (_Array<_Tp> __a, _Array<bool> __m, _Array<_Tp> __b, size_t __n) +{ + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__q, ++__ok, ++__p) { + while (! *__ok) { + ++__ok; + ++__p; + } + *__q = *__p; + } +} + +export template<typename _Tp> +void +__valarray_copy (_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, _Array<bool> __m) +{ + _Tp* __q (__b._M_data); + bool* __ok (__m._M_data); + for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p, ++__ok, ++__q) { + while (! *__ok) { + ++__ok; + ++__q; + } + *__q = *__p; + } +} + +export template<typename _Tp, class _Dom> +void +__valarray_copy (const _Expr<_Dom, _Tp>& __e, size_t __n, _Array<_Tp> __a) +{ + _Tp* __p (__a._M_data); + for (size_t __i=0; __i<__n; ++__i, ++__p) *__p = __e[__i]; +} + +export template<typename _Tp, class _Dom> +void +__valarray_copy (const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, size_t __s) +{ + _Tp* __p (__a._M_data); + for (size_t __i=0; __i<__n; ++__i, __p+=__s) *__p = __e[__i]; +} + +export template<typename _Tp, class _Dom> +void +__valarray_copy (const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array<size_t> __i) +{ + size_t* __j (__i._M_data); + for (size_t __k=0; __k<__n; ++__k, ++__j) __a._M_data[*__j] = __e[__k]; +} + +export template<typename _Tp, class _Dom> +void +__valarray_copy (const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array<bool> __m) +{ + bool* __ok (__m._M_data); + _Tp* __p (__a._M_data); + for (size_t __i=0; __i<__n; ++__i, ++__ok, ++__p) { + while (! *__ok) { + ++__ok; + ++__p; + } + *__p = __e[__i]; + } +} + + +export template<typename _Tp, class _Dom> +void +__valarray_copy_construct (const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a) +{ + _Tp* __p (__a._M_data); + for (size_t __i=0; __i<__n; ++__i, ++__p) new (__p) _Tp(__e[__i]); +} + + +export template<typename _Tp> +void +__valarray_copy_construct (_Array<_Tp> __a, _Array<bool> __m, + _Array<_Tp> __b, size_t __n) +{ + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__q, ++__ok, ++__p) { + while (! *__ok) { + ++__ok; + ++__p; + } + new (__q) _Tp(*__p); + } +} + + + + +} // std:: + +#endif /* _CPP_BITS_VALARRAY_ARRAY_TCC */ + +// Local Variables: +// mode:c++ +// End: diff --git a/contrib/libstdc++/include/bits/valarray_meta.h b/contrib/libstdc++/include/bits/valarray_meta.h new file mode 100644 index 0000000000000..f2926c0903535 --- /dev/null +++ b/contrib/libstdc++/include/bits/valarray_meta.h @@ -0,0 +1,1075 @@ +// The template and inlines for the -*- C++ -*- internal _Meta class. + +// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr> + +/** @file valarray_meta.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _CPP_VALARRAY_META_H +#define _CPP_VALARRAY_META_H 1 + +#pragma GCC system_header + +namespace std +{ + + // + // Implementing a loosened valarray return value is tricky. + // First we need to meet 26.3.1/3: we should not add more than + // two levels of template nesting. Therefore we resort to template + // template to "flatten" loosened return value types. + // At some point we use partial specialization to remove one level + // template nesting due to _Expr<> + // + + + // This class is NOT defined. It doesn't need to. + template<typename _Tp1, typename _Tp2> class _Constant; + + // + // Unary function application closure. + // + template<class _Dom> class _UnFunBase { + public: + typedef typename _Dom::value_type value_type; + typedef value_type _Vt; + + _UnFunBase (const _Dom& __e, _Vt __f(_Vt)) + : _M_expr(__e), _M_func(__f) {} + + _Vt operator[] (size_t __i) const { return _M_func(_M_expr[__i]); } + size_t size () const { return _M_expr.size(); } + + private: + const _Dom& _M_expr; + _Vt (*_M_func)(_Vt); + }; + + template<template<class, class> class _Meta, class _Dom> + class _UnFunClos; + + template<class _Dom> + struct _UnFunClos<_Expr,_Dom> : _UnFunBase<_Dom> { + typedef _UnFunBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _UnFunClos (const _Dom& __e, value_type __f(value_type)) + : _Base (__e, __f) {} + }; + + template<typename _Tp> + struct _UnFunClos<_ValArray,_Tp> : _UnFunBase<valarray<_Tp> > { + typedef _UnFunBase<valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _UnFunClos (const valarray<_Tp>& __v, _Tp __f(_Tp)) + : _Base (__v, __f) {} + }; + + // + // Binary function application closure. + // + template<template<class, class> class _Meta1, + template<class, class> class Meta2, + class _Dom1, class _Dom2> class _BinFunClos; + + template<class _Dom1, class _Dom2> class _BinFunBase { + public: + typedef typename _Dom1::value_type value_type; + typedef value_type _Vt; + + _BinFunBase (const _Dom1& __e1, const _Dom2& __e2, + _Vt __f (_Vt, _Vt)) + : _M_expr1 (__e1), _M_expr2 (__e2), _M_func (__f) {} + + value_type operator[] (size_t __i) const + { return _M_func (_M_expr1[__i], _M_expr2[__i]); } + size_t size () const { return _M_expr1.size (); } + + private: + const _Dom1& _M_expr1; + const _Dom2& _M_expr2; + _Vt (*_M_func)(_Vt, _Vt); + }; + + template<class _Dom> class _BinFunBase1 { + public: + typedef typename _Dom::value_type value_type ; + typedef value_type _Vt; + + _BinFunBase1 (const _Vt& __c, const _Dom& __e, _Vt __f(_Vt, _Vt)) + : _M_expr1 (__c), _M_expr2 (__e), _M_func (__f) {} + + value_type operator[] (size_t __i) const + { return _M_func (_M_expr1, _M_expr2[__i]); } + size_t size () const { return _M_expr2.size (); } + + private: + const _Vt& _M_expr1; + const _Dom& _M_expr2; + _Vt (*_M_func)(_Vt, _Vt); + }; + + template<class _Dom> class _BinFunBase2 { + public: + typedef typename _Dom::value_type value_type; + typedef value_type _Vt; + + _BinFunBase2 (const _Dom& __e, const _Vt& __c, _Vt __f(_Vt, _Vt)) + : _M_expr1 (__e), _M_expr2 (__c), _M_func (__f) {} + + value_type operator[] (size_t __i) const + { return _M_func (_M_expr1[__i], _M_expr2); } + size_t size () const { return _M_expr1.size (); } + + private: + const _Dom& _M_expr1; + const _Vt& _M_expr2; + _Vt (*_M_func)(_Vt, _Vt); + }; + + template<class _Dom1, class _Dom2> + struct _BinFunClos<_Expr,_Expr,_Dom1,_Dom2> : _BinFunBase<_Dom1,_Dom2> { + typedef _BinFunBase<_Dom1,_Dom2> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _BinFunClos (const _Dom1& __e1, const _Dom2& __e2, + _Tp __f(_Tp, _Tp)) + : _Base (__e1, __e2, __f) {} + }; + + template<typename _Tp> + struct _BinFunClos<_ValArray,_ValArray,_Tp,_Tp> + : _BinFunBase<valarray<_Tp>, valarray<_Tp> > { + typedef _BinFunBase<valarray<_Tp>, valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinFunClos (const valarray<_Tp>& __v, const valarray<_Tp>& __w, + _Tp __f(_Tp, _Tp)) + : _Base (__v, __w, __f) {} + }; + + template<class _Dom> + struct _BinFunClos<_Expr,_ValArray,_Dom,typename _Dom::value_type> + : _BinFunBase<_Dom,valarray<typename _Dom::value_type> > { + typedef typename _Dom::value_type _Tp; + typedef _BinFunBase<_Dom,valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinFunClos (const _Dom& __e, const valarray<_Tp>& __v, + _Tp __f(_Tp, _Tp)) + : _Base (__e, __v, __f) {} + }; + + template<class _Dom> + struct _BinFunClos<_ValArray,_Expr,typename _Dom::value_type,_Dom> + : _BinFunBase<valarray<typename _Dom::value_type>,_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _BinFunBase<_Dom,valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinFunClos (const valarray<_Tp>& __v, const _Dom& __e, + _Tp __f(_Tp, _Tp)) + : _Base (__v, __e, __f) {} + }; + + template<class _Dom> + struct _BinFunClos<_Expr,_Constant,_Dom,typename _Dom::value_type> + : _BinFunBase2<_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _Tp value_type; + typedef _BinFunBase2<_Dom> _Base; + + _BinFunClos (const _Dom& __e, const _Tp& __t, _Tp __f (_Tp, _Tp)) + : _Base (__e, __t, __f) {} + }; + + template<class _Dom> + struct _BinFunClos<_Constant,_Expr,_Dom,typename _Dom::value_type> + : _BinFunBase1<_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _Tp value_type; + typedef _BinFunBase1<_Dom> _Base; + + _BinFunClos (const _Tp& __t, const _Dom& __e, _Tp __f (_Tp, _Tp)) + : _Base (__t, __e, __f) {} + }; + + template<typename _Tp> + struct _BinFunClos<_ValArray,_Constant,_Tp,_Tp> + : _BinFunBase2<valarray<_Tp> > { + typedef _BinFunBase2<valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinFunClos (const valarray<_Tp>& __v, const _Tp& __t, + _Tp __f(_Tp, _Tp)) + : _Base (__v, __t, __f) {} + }; + + template<typename _Tp> + struct _BinFunClos<_Constant,_ValArray,_Tp,_Tp> + : _BinFunBase1<valarray<_Tp> > { + typedef _BinFunBase1<valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinFunClos (const _Tp& __t, const valarray<_Tp>& __v, + _Tp __f (_Tp, _Tp)) + : _Base (__t, __v, __f) {} + }; + + // + // Apply function taking a value/const reference closure + // + + template<typename _Dom, typename _Arg> class _FunBase { + public: + typedef typename _Dom::value_type value_type; + + _FunBase (const _Dom& __e, value_type __f(_Arg)) + : _M_expr (__e), _M_func (__f) {} + + value_type operator[] (size_t __i) const + { return _M_func (_M_expr[__i]); } + size_t size() const { return _M_expr.size ();} + + private: + const _Dom& _M_expr; + value_type (*_M_func)(_Arg); + }; + + template<class _Dom> + struct _ValFunClos<_Expr,_Dom> + : _FunBase<_Dom, typename _Dom::value_type> { + typedef _FunBase<_Dom, typename _Dom::value_type> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _ValFunClos (const _Dom& __e, _Tp __f (_Tp)) : _Base (__e, __f) {} + }; + + template<typename _Tp> + struct _ValFunClos<_ValArray,_Tp> + : _FunBase<valarray<_Tp>, _Tp> { + typedef _FunBase<valarray<_Tp>, _Tp> _Base; + typedef _Tp value_type; + + _ValFunClos (const valarray<_Tp>& __v, _Tp __f(_Tp)) + : _Base (__v, __f) {} + }; + + template<class _Dom> + struct _RefFunClos<_Expr,_Dom> : + _FunBase<_Dom, const typename _Dom::value_type&> { + typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _RefFunClos (const _Dom& __e, _Tp __f (const _Tp&)) + : _Base (__e, __f) {} + }; + + template<typename _Tp> + struct _RefFunClos<_ValArray,_Tp> + : _FunBase<valarray<_Tp>, const _Tp&> { + typedef _FunBase<valarray<_Tp>, const _Tp&> _Base; + typedef _Tp value_type; + + _RefFunClos (const valarray<_Tp>& __v, _Tp __f(const _Tp&)) + : _Base (__v, __f) {} + }; + + // + // Unary expression closure. + // + + template<template<class> class _Oper, typename _Arg> + class _UnBase { + public: + typedef _Oper<typename _Arg::value_type> _Op; + typedef typename _Op::result_type value_type; + + _UnBase (const _Arg& __e) : _M_expr(__e) {} + value_type operator[] (size_t) const; + size_t size () const { return _M_expr.size (); } + + private: + const _Arg& _M_expr; + }; + + template<template<class> class _Oper, typename _Arg> + inline typename _UnBase<_Oper, _Arg>::value_type + _UnBase<_Oper, _Arg>::operator[] (size_t __i) const + { return _Op() (_M_expr[__i]); } + + template<template<class> class _Oper, class _Dom> + struct _UnClos<_Oper, _Expr, _Dom> : _UnBase<_Oper, _Dom> { + typedef _Dom _Arg; + typedef _UnBase<_Oper, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _UnClos (const _Arg& __e) : _Base(__e) {} + }; + + template<template<class> class _Oper, typename _Tp> + struct _UnClos<_Oper, _ValArray, _Tp> : _UnBase<_Oper, valarray<_Tp> > { + typedef valarray<_Tp> _Arg; + typedef _UnBase<_Oper, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _UnClos (const _Arg& __e) : _Base(__e) {} + }; + + + // + // Binary expression closure. + // + + template<template<class> class _Oper, + typename _FirstArg, typename _SecondArg> + class _BinBase { + public: + typedef _Oper<typename _FirstArg::value_type> _Op; + typedef typename _Op::result_type value_type; + + _BinBase (const _FirstArg& __e1, const _SecondArg& __e2) + : _M_expr1 (__e1), _M_expr2 (__e2) {} + value_type operator[] (size_t) const; + size_t size () const { return _M_expr1.size (); } + + private: + const _FirstArg& _M_expr1; + const _SecondArg& _M_expr2; + }; + + template<template<class> class _Oper, + typename _FirstArg, typename _SecondArg> + inline typename _BinBase<_Oper,_FirstArg,_SecondArg>::value_type + _BinBase<_Oper,_FirstArg,_SecondArg>::operator[] (size_t __i) const + { return _Op() (_M_expr1[__i], _M_expr2[__i]); } + + + template<template<class> class _Oper, class _Clos> + class _BinBase2 { + public: + typedef typename _Clos::value_type _Vt; + typedef _Oper<_Vt> _Op; + typedef typename _Op::result_type value_type; + + _BinBase2 (const _Clos& __e, const _Vt& __t) + : _M_expr1 (__e), _M_expr2 (__t) {} + value_type operator[] (size_t) const; + size_t size () const { return _M_expr1.size (); } + + private: + const _Clos& _M_expr1; + const _Vt& _M_expr2; + }; + + template<template<class> class _Oper, class _Clos> + inline typename _BinBase2<_Oper,_Clos>::value_type + _BinBase2<_Oper,_Clos>::operator[] (size_t __i) const + { return _Op() (_M_expr1[__i], _M_expr2); } + + + template<template<class> class _Oper, class _Clos> + class _BinBase1 { + public: + typedef typename _Clos::value_type _Vt; + typedef _Oper<_Vt> _Op; + typedef typename _Op::result_type value_type; + + _BinBase1 (const _Vt& __t, const _Clos& __e) + : _M_expr1 (__t), _M_expr2 (__e) {} + value_type operator[] (size_t) const; + size_t size () const { return _M_expr2.size (); } + + private: + const _Vt& _M_expr1; + const _Clos& _M_expr2; + }; + + template<template<class> class _Oper, class _Clos> + inline typename + _BinBase1<_Oper,_Clos>::value_type + _BinBase1<_Oper,_Clos>:: operator[] (size_t __i) const + { return _Op() (_M_expr1, _M_expr2[__i]); } + + + template<template<class> class _Oper, class _Dom1, class _Dom2> + struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2> + : _BinBase<_Oper,_Dom1,_Dom2> { + typedef _BinBase<_Oper,_Dom1,_Dom2> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {} + }; + + template<template<class> class _Oper, typename _Tp> + struct _BinClos<_Oper,_ValArray,_ValArray,_Tp,_Tp> + : _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > { + typedef _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > _Base; + typedef _Tp value_type; + + _BinClos (const valarray<_Tp>& __v, const valarray<_Tp>& __w) + : _Base (__v, __w) {} + }; + + template<template<class> class _Oper, class _Dom> + struct _BinClos<_Oper,_Expr,_ValArray,_Dom,typename _Dom::value_type> + : _BinBase<_Oper,_Dom,valarray<typename _Dom::value_type> > { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2) + : _Base (__e1, __e2) {} + }; + + template<template<class> class _Oper, class _Dom> + struct _BinClos<_Oper,_ValArray,_Expr,typename _Dom::value_type,_Dom> + : _BinBase<_Oper,valarray<typename _Dom::value_type>,_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos (const valarray<_Tp>& __e1, const _Dom& __e2) + : _Base (__e1, __e2) {} + }; + + template<template<class> class _Oper, class _Dom> + struct _BinClos<_Oper,_Expr,_Constant,_Dom,typename _Dom::value_type> + : _BinBase2<_Oper,_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _BinBase2<_Oper,_Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos (const _Dom& __e1, const _Tp& __e2) : _Base (__e1, __e2) {} + }; + + template<template<class> class _Oper, class _Dom> + struct _BinClos<_Oper,_Constant,_Expr,typename _Dom::value_type,_Dom> + : _BinBase1<_Oper,_Dom> { + typedef typename _Dom::value_type _Tp; + typedef _BinBase1<_Oper,_Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos (const _Tp& __e1, const _Dom& __e2) : _Base (__e1, __e2) {} + }; + + template<template<class> class _Oper, typename _Tp> + struct _BinClos<_Oper,_ValArray,_Constant,_Tp,_Tp> + : _BinBase2<_Oper,valarray<_Tp> > { + typedef _BinBase2<_Oper,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos (const valarray<_Tp>& __v, const _Tp& __t) + : _Base (__v, __t) {} + }; + + template<template<class> class _Oper, typename _Tp> + struct _BinClos<_Oper,_Constant,_ValArray,_Tp,_Tp> + : _BinBase1<_Oper,valarray<_Tp> > { + typedef _BinBase1<_Oper,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos (const _Tp& __t, const valarray<_Tp>& __v) + : _Base (__t, __v) {} + }; + + + // + // slice_array closure. + // + template<typename _Dom> class _SBase { + public: + typedef typename _Dom::value_type value_type; + + _SBase (const _Dom& __e, const slice& __s) + : _M_expr (__e), _M_slice (__s) {} + value_type operator[] (size_t __i) const + { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; } + size_t size() const { return _M_slice.size (); } + + private: + const _Dom& _M_expr; + const slice& _M_slice; + }; + + template<typename _Tp> class _SBase<_Array<_Tp> > { + public: + typedef _Tp value_type; + + _SBase (_Array<_Tp> __a, const slice& __s) + : _M_array (__a._M_data+__s.start()), _M_size (__s.size()), + _M_stride (__s.stride()) {} + value_type operator[] (size_t __i) const + { return _M_array._M_data[__i * _M_stride]; } + size_t size() const { return _M_size; } + + private: + const _Array<_Tp> _M_array; + const size_t _M_size; + const size_t _M_stride; + }; + + template<class _Dom> struct _SClos<_Expr,_Dom> : _SBase<_Dom> { + typedef _SBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {} + }; + + template<typename _Tp> + struct _SClos<_ValArray,_Tp> : _SBase<_Array<_Tp> > { + typedef _SBase<_Array<_Tp> > _Base; + typedef _Tp value_type; + + _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {} + }; + + // + // gslice_array closure. + // + template<class _Dom> class _GBase { + public: + typedef typename _Dom::value_type value_type; + + _GBase (const _Dom& __e, const valarray<size_t>& __i) + : _M_expr (__e), _M_index(__i) {} + value_type operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + size_t size () const { return _M_index.size(); } + + private: + const _Dom& _M_expr; + const valarray<size_t>& _M_index; + }; + + template<typename _Tp> class _GBase<_Array<_Tp> > { + public: + typedef _Tp value_type; + + _GBase (_Array<_Tp> __a, const valarray<size_t>& __i) + : _M_array (__a), _M_index(__i) {} + value_type operator[] (size_t __i) const + { return _M_array._M_data[_M_index[__i]]; } + size_t size () const { return _M_index.size(); } + + private: + const _Array<_Tp> _M_array; + const valarray<size_t>& _M_index; + }; + + template<class _Dom> struct _GClos<_Expr,_Dom> : _GBase<_Dom> { + typedef _GBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _GClos (const _Dom& __e, const valarray<size_t>& __i) + : _Base (__e, __i) {} + }; + + template<typename _Tp> + struct _GClos<_ValArray,_Tp> : _GBase<_Array<_Tp> > { + typedef _GBase<_Array<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _GClos (_Array<_Tp> __a, const valarray<size_t>& __i) + : _Base (__a, __i) {} + }; + + // + // indirect_array closure + // + + template<class _Dom> class _IBase { + public: + typedef typename _Dom::value_type value_type; + + _IBase (const _Dom& __e, const valarray<size_t>& __i) + : _M_expr (__e), _M_index (__i) {} + value_type operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + size_t size() const { return _M_index.size(); } + + private: + const _Dom& _M_expr; + const valarray<size_t>& _M_index; + }; + + template<class _Dom> struct _IClos<_Expr,_Dom> : _IBase<_Dom> { + typedef _IBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _IClos (const _Dom& __e, const valarray<size_t>& __i) + : _Base (__e, __i) {} + }; + + template<typename _Tp> + struct _IClos<_ValArray,_Tp> : _IBase<valarray<_Tp> > { + typedef _IBase<valarray<_Tp> > _Base; + typedef _Tp value_type; + + _IClos (const valarray<_Tp>& __a, const valarray<size_t>& __i) + : _Base (__a, __i) {} + }; + + // + // class _Expr + // + template<class _Clos, typename _Tp> class _Expr { + public: + typedef _Tp value_type; + + _Expr (const _Clos&); + + const _Clos& operator() () const; + + value_type operator[] (size_t) const; + valarray<value_type> operator[] (slice) const; + valarray<value_type> operator[] (const gslice&) const; + valarray<value_type> operator[] (const valarray<bool>&) const; + valarray<value_type> operator[] (const valarray<size_t>&) const; + + _Expr<_UnClos<_Unary_plus,std::_Expr,_Clos>, value_type> + operator+ () const; + + _Expr<_UnClos<negate,std::_Expr,_Clos>, value_type> + operator- () const; + + _Expr<_UnClos<_Bitwise_not,std::_Expr,_Clos>, value_type> + operator~ () const; + + _Expr<_UnClos<logical_not,std::_Expr,_Clos>, bool> + operator! () const; + + size_t size () const; + value_type sum () const; + + valarray<value_type> shift (int) const; + valarray<value_type> cshift (int) const; + + value_type min() const; + value_type max() const; + + valarray<value_type> apply(value_type (*) (const value_type&)) const; + valarray<value_type> apply(value_type (*) (value_type)) const; + + private: + const _Clos _M_closure; + }; + + template<class _Clos, typename _Tp> + inline + _Expr<_Clos,_Tp>::_Expr (const _Clos& __c) : _M_closure(__c) {} + + template<class _Clos, typename _Tp> + inline const _Clos& + _Expr<_Clos,_Tp>::operator() () const + { return _M_closure; } + + template<class _Clos, typename _Tp> + inline _Tp + _Expr<_Clos,_Tp>::operator[] (size_t __i) const + { return _M_closure[__i]; } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos,_Tp>::operator[] (slice __s) const + { return _M_closure[__s]; } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos,_Tp>::operator[] (const gslice& __gs) const + { return _M_closure[__gs]; } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos,_Tp>::operator[] (const valarray<bool>& __m) const + { return _M_closure[__m]; } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos,_Tp>::operator[] (const valarray<size_t>& __i) const + { return _M_closure[__i]; } + + template<class _Clos, typename _Tp> + inline size_t + _Expr<_Clos,_Tp>::size () const { return _M_closure.size (); } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos, _Tp>::shift(int __n) const + { return valarray<_Tp>(_M_closure).shift(__n); } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos, _Tp>::cshift(int __n) const + { return valarray<_Tp>(_M_closure).cshift(__n); } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const + { return valarray<_Tp>(_M_closure).apply(__f); } + + template<class _Clos, typename _Tp> + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const + { return valarray<_Tp>(_M_closure).apply(__f); } + + // XXX: replace this with a more robust summation algorithm. + template<class _Clos, typename _Tp> + inline _Tp + _Expr<_Clos,_Tp>::sum () const + { + size_t __n = _M_closure.size(); + if (__n == 0) return _Tp(); + else { + _Tp __s = _M_closure[--__n]; + while (__n != 0) __s += _M_closure[--__n]; + return __s; + } + } + + template<class _Clos, typename _Tp> + inline _Tp + _Expr<_Clos, _Tp>::min() const + { return __valarray_min(_M_closure); } + + template<class _Clos, typename _Tp> + inline _Tp + _Expr<_Clos, _Tp>::max() const + { return __valarray_max(_M_closure); } + + template<class _Dom, typename _Tp> + inline _Expr<_UnClos<logical_not,_Expr,_Dom>, bool> + _Expr<_Dom,_Tp>::operator! () const + { + typedef _UnClos<logical_not,std::_Expr,_Dom> _Closure; + return _Expr<_Closure,_Tp> (_Closure(this->_M_closure)); + } + +#define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name) \ +template<class _Dom, typename _Tp> \ +inline _Expr<_UnClos<_Name,std::_Expr,_Dom>,_Tp> \ +_Expr<_Dom,_Tp>::operator _Op () const \ +{ \ + typedef _UnClos<_Name,std::_Expr,_Dom> _Closure; \ + return _Expr<_Closure,_Tp> (_Closure (this->_M_closure)); \ +} + + _DEFINE_EXPR_UNARY_OPERATOR(+, _Unary_plus) + _DEFINE_EXPR_UNARY_OPERATOR(-, negate) + _DEFINE_EXPR_UNARY_OPERATOR(~, _Bitwise_not) + +#undef _DEFINE_EXPR_UNARY_OPERATOR + + +#define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name) \ +template<class _Dom1, class _Dom2> \ +inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>, \ + typename _Name<typename _Dom1::value_type>::result_type> \ +operator _Op (const _Expr<_Dom1,typename _Dom1::value_type>& __v, \ + const _Expr<_Dom2,typename _Dom2::value_type>& __w) \ +{ \ + typedef typename _Dom1::value_type _Arg; \ + typedef typename _Name<_Arg>::result_type _Value; \ + typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure; \ + return _Expr<_Closure,_Value> (_Closure (__v (), __w ())); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>, \ + typename _Name<typename _Dom::value_type>::result_type> \ +operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __v, \ + const typename _Dom::value_type& __t) \ +{ \ + typedef typename _Dom::value_type _Arg; \ + typedef typename _Name<_Arg>::result_type _Value; \ + typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure; \ + return _Expr<_Closure,_Value> (_Closure (__v (), __t)); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>, \ + typename _Name<typename _Dom::value_type>::result_type> \ +operator _Op (const typename _Dom::value_type& __t, \ + const _Expr<_Dom,typename _Dom::value_type>& __v) \ +{ \ + typedef typename _Dom::value_type _Arg; \ + typedef typename _Name<_Arg>::result_type _Value; \ + typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure; \ + return _Expr<_Closure,_Value> (_Closure (__t, __v ())); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>, \ + typename _Name<typename _Dom::value_type>::result_type> \ +operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __e, \ + const valarray<typename _Dom::value_type>& __v) \ +{ \ + typedef typename _Dom::value_type _Arg; \ + typedef typename _Name<_Arg>::result_type _Value; \ + typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Arg> _Closure; \ + return _Expr<_Closure,_Value> (_Closure (__e (), __v)); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>, \ + typename _Name<typename _Dom::value_type>::result_type> \ +operator _Op (const valarray<typename _Dom::value_type>& __v, \ + const _Expr<_Dom,typename _Dom::value_type>& __e) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef typename _Name<_Tp>::result_type _Value; \ + typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure; \ + return _Expr<_Closure,_Value> (_Closure (__v, __e ())); \ +} + + _DEFINE_EXPR_BINARY_OPERATOR(+, plus) + _DEFINE_EXPR_BINARY_OPERATOR(-, minus) + _DEFINE_EXPR_BINARY_OPERATOR(*, multiplies) + _DEFINE_EXPR_BINARY_OPERATOR(/, divides) + _DEFINE_EXPR_BINARY_OPERATOR(%, modulus) + _DEFINE_EXPR_BINARY_OPERATOR(^, _Bitwise_xor) + _DEFINE_EXPR_BINARY_OPERATOR(&, _Bitwise_and) + _DEFINE_EXPR_BINARY_OPERATOR(|, _Bitwise_or) + _DEFINE_EXPR_BINARY_OPERATOR(<<, _Shift_left) + _DEFINE_EXPR_BINARY_OPERATOR(>>, _Shift_right) + +#undef _DEFINE_EXPR_BINARY_OPERATOR + +#define _DEFINE_EXPR_RELATIONAL_OPERATOR(_Op, _Name) \ +template<class _Dom1, class _Dom2> \ +inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>, bool> \ +operator _Op (const _Expr<_Dom1,typename _Dom1::value_type>& __v, \ + const _Expr<_Dom2,typename _Dom2::value_type>& __w) \ +{ \ + typedef typename _Dom1::value_type _Arg; \ + typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure; \ + return _Expr<_Closure,bool> (_Closure (__v (), __w ())); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>, \ + bool> \ +operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __v, \ + const typename _Dom::value_type& __t) \ +{ \ + typedef typename _Dom::value_type _Arg; \ + typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure; \ + return _Expr<_Closure,bool> (_Closure (__v (), __t)); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>, \ + bool> \ +operator _Op (const typename _Dom::value_type& __t, \ + const _Expr<_Dom,typename _Dom::value_type>& __v) \ +{ \ + typedef typename _Dom::value_type _Arg; \ + typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure; \ + return _Expr<_Closure,bool> (_Closure (__t, __v ())); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>, \ + bool> \ +operator _Op (const _Expr<_Dom,typename _Dom::value_type>& __e, \ + const valarray<typename _Dom::value_type>& __v) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Tp> _Closure; \ + return _Expr<_Closure,bool> (_Closure (__e (), __v)); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>, \ + bool> \ +operator _Op (const valarray<typename _Dom::value_type>& __v, \ + const _Expr<_Dom,typename _Dom::value_type>& __e) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure; \ + return _Expr<_Closure,bool> (_Closure (__v, __e ())); \ +} + + _DEFINE_EXPR_RELATIONAL_OPERATOR(&&, logical_and) + _DEFINE_EXPR_RELATIONAL_OPERATOR(||, logical_or) + _DEFINE_EXPR_RELATIONAL_OPERATOR(==, equal_to) + _DEFINE_EXPR_RELATIONAL_OPERATOR(!=, not_equal_to) + _DEFINE_EXPR_RELATIONAL_OPERATOR(<, less) + _DEFINE_EXPR_RELATIONAL_OPERATOR(>, greater) + _DEFINE_EXPR_RELATIONAL_OPERATOR(<=, less_equal) + _DEFINE_EXPR_RELATIONAL_OPERATOR(>=, greater_equal) + +#undef _DEFINE_EXPR_RELATIONAL_OPERATOR + + + +#define _DEFINE_EXPR_UNARY_FUNCTION(_Name) \ +template<class _Dom> \ +inline _Expr<_UnFunClos<_Expr,_Dom>,typename _Dom::value_type> \ +_Name(const _Expr<_Dom,typename _Dom::value_type>& __e) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _UnFunClos<_Expr,_Dom> _Closure; \ + return _Expr<_Closure,_Tp>(_Closure(__e(), (_Tp(*)(_Tp))(&_Name))); \ +} \ + \ +template<typename _Tp> \ +inline _Expr<_UnFunClos<_ValArray,_Tp>,_Tp> \ +_Name(const valarray<_Tp>& __v) \ +{ \ + typedef _UnFunClos<_ValArray,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> (_Closure (__v, (_Tp(*)(_Tp))(&_Name))); \ +} + + + _DEFINE_EXPR_UNARY_FUNCTION(abs) + _DEFINE_EXPR_UNARY_FUNCTION(cos) + _DEFINE_EXPR_UNARY_FUNCTION(acos) + _DEFINE_EXPR_UNARY_FUNCTION(cosh) + _DEFINE_EXPR_UNARY_FUNCTION(sin) + _DEFINE_EXPR_UNARY_FUNCTION(asin) + _DEFINE_EXPR_UNARY_FUNCTION(sinh) + _DEFINE_EXPR_UNARY_FUNCTION(tan) + _DEFINE_EXPR_UNARY_FUNCTION(tanh) + _DEFINE_EXPR_UNARY_FUNCTION(atan) + _DEFINE_EXPR_UNARY_FUNCTION(exp) + _DEFINE_EXPR_UNARY_FUNCTION(log) + _DEFINE_EXPR_UNARY_FUNCTION(log10) + _DEFINE_EXPR_UNARY_FUNCTION(sqrt) + +#undef _DEFINE_EXPR_UNARY_FUNCTION + + +#define _DEFINE_EXPR_BINARY_FUNCTION(_Name) \ +template<class _Dom1, class _Dom2> \ +inline _Expr<_BinFunClos<_Expr,_Expr,_Dom1,_Dom2>,typename _Dom1::value_type>\ +_Name (const _Expr<_Dom1,typename _Dom1::value_type>& __e1, \ + const _Expr<_Dom2,typename _Dom2::value_type>& __e2) \ +{ \ + typedef typename _Dom1::value_type _Tp; \ + typedef _BinFunClos<_Expr,_Expr,_Dom1,_Dom2> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__e1 (), __e2 (), (_Tp(*)(_Tp, _Tp))(&_Name))); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinFunClos<_Expr,_ValArray,_Dom,typename _Dom::value_type>, \ + typename _Dom::value_type> \ +_Name (const _Expr<_Dom,typename _Dom::value_type>& __e, \ + const valarray<typename _Dom::value_type>& __v) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinFunClos<_Expr,_ValArray,_Dom,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__e (), __v, (_Tp(*)(_Tp, _Tp))(&_Name))); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinFunClos<_ValArray,_Expr,typename _Dom::value_type,_Dom>, \ + typename _Dom::value_type> \ +_Name (const valarray<typename _Dom::valarray>& __v, \ + const _Expr<_Dom,typename _Dom::value_type>& __e) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinFunClos<_ValArray,_Expr,_Tp,_Dom> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__v, __e (), (_Tp(*)(_Tp, _Tp))(&_Name))); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinFunClos<_Expr,_Constant,_Dom,typename _Dom::value_type>, \ + typename _Dom::value_type> \ +_Name (const _Expr<_Dom, typename _Dom::value_type>& __e, \ + const typename _Dom::value_type& __t) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinFunClos<_Expr,_Constant,_Dom,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__e (), __t, (_Tp(*)(_Tp, _Tp))(&_Name))); \ +} \ + \ +template<class _Dom> \ +inline _Expr<_BinFunClos<_Constant,_Expr,typename _Dom::value_type,_Dom>, \ + typename _Dom::value_type> \ +_Name (const typename _Dom::value_type& __t, \ + const _Expr<_Dom,typename _Dom::value_type>& __e) \ +{ \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinFunClos<_Constant,_Expr,_Tp,_Dom> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__t, __e (), (_Tp(*)(_Tp, _Tp))(&_Name))); \ +} \ + \ +template<typename _Tp> \ +inline _Expr<_BinFunClos<_ValArray,_ValArray,_Tp,_Tp>, _Tp> \ +_Name (const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ +{ \ + typedef _BinFunClos<_ValArray,_ValArray,_Tp,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__v, __w, (_Tp(*)(_Tp,_Tp))(&_Name))); \ +} \ + \ +template<typename _Tp> \ +inline _Expr<_BinFunClos<_ValArray,_Constant,_Tp,_Tp>,_Tp> \ +_Name (const valarray<_Tp>& __v, const _Tp& __t) \ +{ \ + typedef _BinFunClos<_ValArray,_Constant,_Tp,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__v, __t, (_Tp(*)(_Tp,_Tp))(&_Name))); \ +} \ + \ +template<typename _Tp> \ +inline _Expr<_BinFunClos<_Constant,_ValArray,_Tp,_Tp>,_Tp> \ +_Name (const _Tp& __t, const valarray<_Tp>& __v) \ +{ \ + typedef _BinFunClos<_Constant,_ValArray,_Tp,_Tp> _Closure; \ + return _Expr<_Closure,_Tp> \ + (_Closure (__t, __v, (_Tp(*)(_Tp,_Tp))(&_Name))); \ +} + +_DEFINE_EXPR_BINARY_FUNCTION(atan2) +_DEFINE_EXPR_BINARY_FUNCTION(pow) + +#undef _DEFINE_EXPR_BINARY_FUNCTION + +} // std:: + + +#endif /* _CPP_VALARRAY_META_H */ + +// Local Variables: +// mode:c++ +// End: |
