_s1, __b._M_data, __s2); } // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] template inline void __valarray_copy(_Array<_Tp> __a, _Array __i, _Array<_Tp> __b, size_t __n) { std::__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 inline void __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, _Array __i) { std::__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 inline void __valarray_copy(_Array<_Tp> __src, size_t __n, _Array __i, _Array<_Tp> __dst, _Array __j) { std::__valarray_copy(__src._M_data, __n, __i._M_data, __dst._M_data, __j._M_data); } template inline _Array<_Tp>::_Array(size_t __n) : _M_data(__valarray_get_storage<_Tp>(__n)) { std::__valarray_default_construct(_M_data, _M_data + __n); } template inline _Array<_Tp>::_Array(_Tp* const __restrict__ __p) : _M_data (__p) {} template inline _Array<_Tp>::_Array(const valarray<_Tp>& __v) : _M_data (__v._M_data) {} template inline _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s) : _M_data(__valarray_get_storage<_Tp>(__s)) { std::__valarray_copy_construct(__b, __s, _M_data); } template inline _Tp* _Array<_Tp>::begin () const { return _M_data; } #define _DEFINE_ARRAY_FUNCTION(_Op, _Name) \ template \ 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 \ 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 \ 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 \ 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 \ 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 \ 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 \ inline void \ _Array_augmented_##_Name(_Array<_Tp> __a, _Array __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 \ inline void \ _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ _Array<_Tp> __b, _Array __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 \ void \ _Array_augmented_##_Name(_Array<_Tp> __a, _Array __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 \ void \ _Array_augmented_##_Name(_Array<_Tp> __a, _Array __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 \ void \ _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ _Array<_Tp> __b, _Array __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 \ void \ _Array_augmented_##_Name(_Array<_Tp> __a, _Array __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(^, __bitwise_xor) _DEFINE_ARRAY_FUNCTION(|, __bitwise_or) _DEFINE_ARRAY_FUNCTION(&, __bitwise_and) _DEFINE_ARRAY_FUNCTION(<<, __shift_left) _DEFINE_ARRAY_FUNCTION(>>, __shift_right) #undef _DEFINE_ARRAY_FUNCTION _GLIBCXX_END_NAMESPACE #ifndef _GLIBCXX_EXPORT_TEMPLATE # include #endif #endif /* _ARRAY_H */ // nonstandard construct and destroy functions -*- C++ -*- // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 // 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, // 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 _STL_CONSTRUCT_H #define _STL_CONSTRUCT_H 1 #include _GLIBCXX_BEGIN_NAMESPACE(std) /** * Constructs an object in existing memory by invoking an allocated * object's constructor with an initializer. */ template inline void _Construct(_T1* __p, const _T2& __value) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_]allocator::construct ::new(static_cast(__p)) _T1(__value); } /** * Destroy the object pointed to by a pointer type. */ template inline void _Destroy(_Tp* __pointer) { __pointer->~_Tp(); } /** * 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. */ template inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type _Value_type; if (!__has_trivial_destructor(_Value_type)) for (; __first != __last; ++__first) std::_Destroy(&*__first); } /** * Destroy a range of objects using the supplied allocator. For * nondefault allocators we do not optimize away invocation of * destroy() even if _Tp has a trivial destructor. */ template class allocator; template void _Destroy(_ForwardIterator __first, _ForwardIterator __last, _Allocator& __alloc) { for (; __first != __last; ++__first) __alloc.destroy(&*__first); } template inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last, allocator<_Tp>&) { _Destroy(__first, __last); } _GLIBCXX_END_NAMESPACE #endif /* _STL_CONSTRUCT_H */ // File based streams -*- C++ -*- // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, // 2007 // 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, // 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 fstream.tcc * This is an internal header file, included by other library headers. * You should not attempt to use it directly. */ // // ISO C++ 14882: 27.8 File-based streams // #ifndef _FSTREAM_TCC #define _FSTREAM_TCC 1 #pragma GCC system_header #include _GLIBCXX_BEGIN_NAMESPACE(std) template void basic_filebuf<_CharT, _Traits>:: _M_allocate_internal_buffer() { // Allocate internal buffer only if one doesn't already exist // (either allocated or provided by the user via setbuf). if (!_M_buf_allocated && !_M_buf) { _M_buf = new char_type[_M_buf_size]; _M_buf_allocated = true; } } template void basic_filebuf<_CharT, _Traits>:: _M_destroy_internal_buffer() throw() { if (_M_buf_allocated) { delete [] _M_buf; _M_buf = NULL; _M_buf_allocated = false; } delete [] _M_ext_buf; _M_ext_buf = NULL; _M_ext_buf_size = 0; _M_ext_next = NULL; _M_ext_end = NULL; } template basic_filebuf<_CharT, _Traits>:: basic_filebuf() : __streambuf_type(), _M_lock(), _M_file(&_M_lock), _M_mode(ios_base::openmode(0)), _M_state_beg(), _M_state_cur(), _M_state_last(), _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false), _M_reading(false), _M_writing(false), _M_pback(), _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0), _M_ext_end(0) { if (has_facet<__codecvt_type>(this->_M_buf_locale)) _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale); } template 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; // Setup initial buffer to 'uncommitted' mode. _M_reading = false; _M_writing = false; _M_set_buffer(-1); // Reset to initial state. _M_state_last = _M_state_cur = _M_state_beg; // 27.8.1.3,4 if ((__mode & ios_base::ate) && this->seekoff(0, ios_base::end, __mode) == pos_type(off_type(-1))) this->close(); else __ret = this; } } return __ret; } template typename basic_filebuf<_CharT, _Traits>::__filebuf_type* basic_filebuf<_CharT, _Traits>:: close() { if (!this->is_open()) return NULL; bool __testfail = false; { // NB: Do this here so that re-opened filebufs will be cool... struct __close_sentry { basic_filebuf *__fb; __close_sentry (basic_filebuf *__fbi): __fb(__fbi) { } ~__close_sentry () { __fb->_M_mode = ios_base::openmode(0); __fb->_M_pback_init = false; __fb->_M_destroy_internal_buffer(); __fb->_M_reading = false; __fb->_M_writing = false; __fb->_M_set_buffer(-1); __fb->_M_state_last = __fb->_M_state_cur = __fb->_M_state_beg; } } __cs (this); try { if (!_M_terminate_output()) __testfail = true; } catch(__cxxabiv1::__forced_unwind&) { _M_file.close(); __throw_exception_again; } catch(...) { __testfail = true; } } if (!_M_file.close()) __testfail = true; if (__testfail) return NULL; else return this; } template streamsize basic_filebuf<_CharT, _Traits>:: showmanyc() { streamsize __ret = -1; const bool __testin = _M_mode & ios_base::in; if (__testin && this->is_open()) { // For a stateful encoding (-1) the pending sequence might be just // shift and unshift prefixes with no actual character. __ret = this->egptr() - this->gptr(); #if _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM // About this workaround, see libstdc++/20806. const bool __testbinary = _M_mode & ios_base::binary; if (__check_facet(_M_codecvt).encoding() >= 0 && __testbinary) #else if (__check_facet(_M_codecvt).encoding() >= 0) #endif __ret += _M_file.showmanyc() / _M_codecvt->max_length(); } return __ret; } template typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>:: underflow() { int_type __ret = traits_type::eof(); const bool __testin = _M_mode & ios_base::in; if (__testin && !_M_writing) { // Check for pback madness, and if so switch back to the // normal buffers and jet outta here before expensive // fileops happen... _M_destroy_pback(); if (this->gptr() < this->egptr()) return traits_type::to_int_type(*this->gptr()); // Get and convert input sequence. const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; // Will be set to true if ::read() returns 0 indicating EOF. bool __got_eof = false; // Number of internal characters produced. streamsize __ilen = 0; codecvt_base::result __r = codecvt_base::ok; if (__check_facet(_M_codecvt).always_noconv()) { __ilen = _M_file.xsgetn(reinterpret_cast(this->eback()), __buflen); if (__ilen == 0) __got_eof = true; } else { // Worst-case number of external bytes. // XXX Not done encoding() == -1. const int __enc = _M_codecvt->encoding(); streamsize __blen; // Minimum buffer size. streamsize __rlen; // Number of chars to read. if (__enc > 0) __blen = __rlen = __buflen * __enc; else { __blen = __buflen + _M_codecvt->max_length() - 1; __rlen = __buflen; } const streamsize __remainder = _M_ext_end - _M_ext_next; __rlen = __rlen > __remainder ? __rlen - __remainder : 0; // An imbue in 'read' mode implies first converting the external // chars already present. if (_M_reading && this->egptr() == this->eback() && __remainder) __rlen = 0; // Allocate buffer if necessary and move unconverted // bytes to front. if (_M_ext_buf_size < __blen) { char* __buf = new char[__blen]; if (__remainder) __builtin_memcpy(__buf, _M_ext_next, __remainder); delete [] _M_ext_buf; _M_ext_buf = __buf; _M_ext_buf_size = __blen; } else if (__remainder) __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); _M_ext_next = _M_ext_buf; _M_ext_end = _M_ext_buf + __remainder; _M_state_last = _M_state_cur; do { if (__rlen > 0) { // Sanity check! // This may fail if the return value of // codecvt::max_length() is bogus. if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size) { __throw_ios_failure(__N("basic_filebuf::underflow " "codecvt::max_length() " "is not valid")); } streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen); if (__elen == 0) __got_eof = true; else if (__elen == -1) break; _M_ext_end += __elen; } char_type* __iend = this->eback(); if (_M_ext_next < _M_ext_end) __r = _M_codecvt->in(_M_state_cur, _M_ext_next, _M_ext_end, _M_ext_next, this->eback(), this->eback() + __buflen, __iend); if (__r == codecvt_base::noconv) { size_t __avail = _M_ext_end - _M_ext_buf; __ilen = std::min(__avail, __buflen); traits_type::copy(this->eback(), reinterpret_cast (_M_ext_buf), __ilen); _M_ext_next = _M_ext_buf + __ilen; } else __ilen = __iend - this->eback(); // _M_codecvt->in may return error while __ilen > 0: this is // ok, and actually occurs in case of mixed encodings (e.g., // XML files). if (__r == codecvt_base::error) break; __rlen = 1; } while (__ilen == 0 && !__got_eof); } if (__ilen > 0) { _M_set_buffer(__ilen); _M_reading = true; __ret = traits_type::to_int_type(*this->gptr()); } else if (__got_eof) { // If the actual end of file is reached, set 'uncommitted' // mode, thus allowing an immediate write without an // intervening seek. _M_set_buffer(-1); _M_reading = false; // However, reaching it while looping on partial means that // the file has got an incomplete character. if (__r == codecvt_base::partial) __throw_ios_failure(__N("basic_filebuf::underflow " "incomplete character in file")); } else if (__r == codecvt_base::error) __throw_ios_failure(__N("basic_filebuf::underflow " "invalid byte sequence in file")); else __throw_ios_failure(__N("basic_filebuf::underflow " "error reading the file")); } return __ret; } template typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>:: pbackfail(int_type __i) { int_type __ret = traits_type::eof(); const bool __testin = _M_mode & ios_base::in; if (__testin && !_M_writing) { // Remember whether the pback buffer is active, otherwise below // we may try to store in it a second char (libstdc++/9761). const bool __testpb = _M_pback_init; const bool __testeof = traits_type::eq_int_type(__i, __ret); int_type __tmp; if (this->eback() < this->gptr()) { this->gbump(-1); __tmp = traits_type::to_int_type(*this->gptr()); } else if (this->seekoff(-1, ios_base::cur) != pos_type(off_type(-1))) { __tmp = this->underflow(); if (traits_type::eq_int_type(__tmp, __ret)) return __ret; } else { // At the beginning of the buffer, need to make a // putback position available. But the seek may fail // (f.i., at the beginning of a file, see // libstdc++/9439) and in that case we return // traits_type::eof(). return __ret; } // Try to put back __i into input sequence in one of three ways. // Order these tests done in is unspecified by the standard. if (!__testeof && traits_type::eq_int_type(__i, __tmp)) __ret = __i; else if (__testeof) __ret = traits_type::not_eof(__i); else if (!__testpb) { _M_create_pback(); _M_reading = true; *this->gptr() = traits_type::to_char_type(__i); __ret = __i; } } return __ret; } template typename basic_filebuf<_CharT, _Traits>::int_type Ú+Û+Ü+Ý+Þ+ß+à+á+â+ã+ä+å+æ+ç+è+ basic_filebuf<_CharT, _Traits>:: overflow(int_type __c) { int_type __ret = traits_type::eof(); const bool __testeof = traits_type::eq_int_type(__c, __ret); const bool __testout = _M_mode & ios_base::out; if (__testout && !_M_reading) { if (this->pbase() < this->pptr()) { // If appropriate, append the overflow char. if (!__testeof) { *this->pptr() = traits_type::to_char_type(__c); this->pbump(1); } // Convert pending sequence to external representation, // and output. if (_M_convert_to_external(this->pbase(), this->pptr() - this->pbase())) { _M_set_buffer(0); __ret = traits_type::not_eof(__c); } } else if (_M_buf_size > 1) { // Overflow in 'uncommitted' mode: set _M_writing, set // the buffer to the initial 'write' mode, and put __c // into the buffer. _M_set_buffer(0); _M_writing = true; if (!__testeof) { *this->pptr() = traits_type::to_char_type(__c); this->pbump(1); } __ret = traits_type::not_eof(__c); } else { // Unbuffered. char_type __conv = traits_type::to_char_type(__c); if (__testeof || _M_convert_to_external(&__conv, 1)) { _M_writing = true; __ret = traits_type::not_eof(__c); } } } return __ret; } template bool basic_filebuf<_CharT, _Traits>:: _M_convert_to_external(_CharT* __ibuf, streamsize __ilen) { // Sizes of external and pending output. streamsize __elen; streamsize __plen; if (__check_facet(_M_codecvt).always_noconv()) { __elen = _M_file.xsputn(reinterpret_cast(__ibuf), __ilen); __plen = __ilen; } else { // Worst-case number of external bytes needed. // XXX Not done encoding() == -1. streamsize __blen = __ilen * _M_codecvt->max_length(); char* __buf = static_cast(__builtin_alloca(__blen)); char* __bend; const char_type* __iend; codecvt_base::result __r; __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, __iend, __buf, __buf + __blen, __bend); if (__r == codecvt_base::ok || __r == codecvt_base::partial) __blen = __bend - __buf; else if (__r == codecvt_base::noconv) { // Same as the always_noconv case above. __buf = reinterpret_cast(__ibuf); __blen = __ilen; } else __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external " "conversion error")); __elen = _M_file.xsputn(__buf, __blen); __plen = __blen; // Try once more for partial conversions. if (__r == codecvt_base::partial && __elen == __plen) { const char_type* __iresume = __iend; streamsize __rlen = this->pptr() - __iend; __r = _M_codecvt->out(_M_state_cur, __iresume, __iresume + __rlen, __iend, __buf, __buf + __blen, __bend); if (__r != codecvt_base::error) { __rlen = __bend - __buf; __elen = _M_file.xsputn(__buf, __rlen); __plen = __rlen; } else __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external " "conversion error")); } } return __elen == __plen; } template streamsize basic_filebuf<_CharT, _Traits>:: xsgetn(_CharT* __s, streamsize __n) { // Clear out pback buffer before going on to the real deal... streamsize __ret = 0; if (_M_pback_init) { if (__n > 0 && this->gptr() == this->eback()) { *__s++ = *this->gptr(); this->gbump(1); __ret = 1; --__n; } _M_destroy_pback(); } // Optimization in the always_noconv() case, to be generalized in the // future: when __n > __buflen we read directly instead of using the // buffer repeatedly. const bool __testin = _M_mode & ios_base::in; const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; if (__n > __buflen && __check_facet(_M_codecvt).always_noconv() && __testin && !_M_writing) { // First, copy the chars already present in the buffer. const streamsize __avail = this->egptr() - this->gptr(); if (__avail != 0) { if (__avail == 1) *__s = *this->gptr(); else traits_type::copy(__s, this->gptr(), __avail); __s += __avail; this->gbump(__avail); __ret += __avail; __n -= __avail; } // Need to loop in case of short reads (relatively common // with pipes). streamsize __len; for (;;) { __len = _M_file.xsgetn(reinterpret_cast(__s), __n); if (__len == -1) __throw_ios_failure(__N("basic_filebuf::xsgetn " "error reading the file")); if (__len == 0) break; __n -= __len; __ret += __len; if (__n == 0) break; __s += __len; } if (__n == 0) { _M_set_buffer(0); _M_reading = true; } else if (__len == 0) { // If end of file is reached, set 'uncommitted' // mode, thus allowing an immediate write without // an intervening seek. _M_set_buffer(-1); _M_reading = false; } } else __ret += __streambuf_type::xsgetn(__s, __n); return __ret; } template streamsize basic_filebuf<_CharT, _Traits>:: xsputn(const _CharT* __s, streamsize __n) { // Optimization in the always_noconv() case, to be generalized in the // future: when __n is sufficiently large we write directly instead of // using the buffer. streamsize __ret = 0; const bool __testout = _M_mode & ios_base::out; if (__check_facet(_M_codecvt).always_noconv() && __testout && !_M_reading) { // Measurement would reveal the best choice. const streamsize __chunk = 1ul << 10; streamsize __bufavail = this->epptr() - this->pptr(); // Don't mistake 'uncommitted' mode buffered with unbuffered. if (!_M_writing && _M_buf_size > 1) __bufavail = _M_buf_size - 1; const streamsize __limit = std::min(__chunk, __bufavail); if (__n >= __limit) { const streamsize __buffill = this->pptr() - this->pbase(); const char* __buf = reinterpret_cast(this->pbase()); __ret = _M_file.xsputn_2(__buf, __buffill, reinterpret_cast(__s), __n); if (__ret == __buffill + __n) { _M_set_buffer(0); _M_writing = true; } if (__ret > __buffill) __ret -= __buffill; else __ret = 0; } else __ret = __streambuf_type::xsputn(__s, __n); } else __ret = __streambuf_type::xsputn(__s, __n); return __ret; } template typename basic_filebuf<_CharT, _Traits>::__streambuf_type* basic_filebuf<_CharT, _Traits>:: setbuf(char_type* __s, streamsize __n) { if (!this->is_open()) if (__s == 0 && __n == 0) _M_buf_size = 1; else if (__s && __n > 0) { // This is implementation-defined behavior, and assumes that // an external char_type array of length __n exists and has // been pre-allocated. If this is not the case, things will // quickly blow up. When __n > 1, __n - 1 positions will be // used for the get area, __n - 1 for the put area and 1 // position to host the overflow char of a full put area. // When __n == 1, 1 position will be used for the get area // and 0 for the put area, as in the unbuffered case above. _M_buf = __s; _M_buf_size = __n; } return this; } // According to 27.8.1.4 p11 - 13, seekoff should ignore the last // argument (of type openmode). template typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>:: seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode) { int __width = 0; if (_M_codecvt) __width = _M_codecvt->encoding(); if (__width < 0) __width = 0; pos_type __ret = pos_type(off_type(-1)); const bool __testfail = __off != 0 && __width <= 0; if (this->is_open() && !__testfail) { // Ditch any pback buffers to avoid confusion. _M_destroy_pback(); // Correct state at destination. Note that this is the correct // state for the current position during output, because // codecvt::unshift() returns the state to the initial state. // This is also the correct state at the end of the file because // an unshift sequence should have been written at the end. __state_type __state = _M_state_beg; off_type __computed_off = __off * __width; if (_M_reading && __way == ios_base::cur) { if (_M_codecvt->always_noconv()) __computed_off += this->gptr() - this->egptr(); else { // Calculate offset from _M_ext_buf that corresponds // to gptr(). Note: uses _M_state_last, which // corresponds to eback(). const int __gptr_off = _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next, this->gptr() - this->eback()); __computed_off += _M_ext_buf + __gptr_off - _M_ext_end; // _M_state_last is modified by codecvt::length() so // it now corresponds to gptr(). __state = _M_state_last; } } __ret = _M_seek(__computed_off, __way, __state); } return __ret; } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 171. Strange seekpos() semantics due to joint position // According to the resolution of DR 171, seekpos should ignore the last // argument (of type openmode). template typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>:: seekpos(pos_type __pos, ios_base::openmode) { pos_type __ret = pos_type(off_type(-1)); if (this->is_open()) { // Ditch any pback buffers to avoid confusion. _M_destroy_pback(); __ret = _M_seek(off_type(__pos), ios_base::beg, __pos.state()); } return __ret; } template typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>:: _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state) { pos_type __ret = pos_type(off_type(-1)); if (_M_terminate_output()) { // Returns pos_type(off_type(-1)) in case of failure. __ret = pos_type(_M_file.seekoff(__off, __way)); if (__ret != pos_type(off_type(-1))) { _M_reading = false; _M_writing = false; _M_ext_next = _M_ext_end = _M_ext_buf; _M_set_buffer(-1); _M_state_cur = __state; __ret.state(_M_state_cur); } } return __ret; } template bool basic_filebuf<_CharT, _Traits>:: _M_terminate_output() { // Part one: update the output sequence. bool __testvalid = true; if (this->pbase() < this->pptr()) { const int_type __tmp = this->overflow(); if (traits_type::eq_int_type(__tmp, traits_type::eof())) __testvalid = false; } // Part two: output unshift sequence. if (_M_writing && !__check_facet(_M_codecvt).always_noconv() && __testvalid) { // Note: this value is arbitrary, since there is no way to // get the length of the unshift sequence from codecvt, // without calling unshift. const size_t __blen = 128; char __buf[__blen]; codecvt_base::result __r; streamsize __ilen = 0; do { char* __next; __r = _M_codecvt->unshift(_M_state_cur, __buf, __buf + __blen, __next); if (__r == codecvt_base::error) __testvalid = false; else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { __ilen = __next - __buf; if (__ilen > 0) { const streamsize __elen = _M_file.xsputn(__buf, __ilen); if (__elen != __ilen) __testvalid = false; } } } while (__r == codecvt_base::partial && __ilen > 0 && __testvalid); if (__testvalid) { // This second call to overflow() is required by the standard, // but it's not clear why it's needed, since the output buffer // should be empty by this point (it should have been emptied // in the first call to overflow()). const int_type __tmp = this->overflow(); if (traits_type::eq_int_type(__tmp, traits_type::eof())) __testvalid = false; } } return __testvalid; } template int basic_filebuf<_CharT, _Traits>:: sync() { // Make sure that the internal buffer resyncs its idea of // the file position with the external file. int __ret = 0; if (this->pbase() < this->pptr()) { const int_type __tmp = this->overflow(); if (traits_type::eq_int_type(__tmp, traits_type::eof())) __ret = -1; } return __ret; } template void basic_filebuf<_CharT, _Traits>:: imbue(const locale& __loc) { bool __testvalid = true; const __codecvt_type* _M_codecvt_tmp = 0; if (__builtin_expect(has_facet<__codecvt_type>(__loc), true)) _M_codecvt_tmp = &use_facet<__codecvt_type>(__loc); if (this->is_open()) { // encoding() == -1 is ok only at the beginning. if ((_M_reading || _M_writing) && __check_facet(_M_codecvt).encoding() == -1) __testvalid = false; else { if (_M_reading) { if (__check_facet(_M_codecvt).always_noconv()) { if (_M_codecvt_tmp && !__check_facet(_M_codecvt_tmp).always_noconv()) __testvalid = this->seekoff(0, ios_base::cur, _M_mode) != pos_type(off_type(-1)); } else { // External position corresponding to gptr(). _M_ext_next = _M_ext_buf + _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next, this->gptr() - this->eback()); const streamsize __remainder = _M_ext_end - _M_ext_next; if (__remainder) __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); _M_ext_next = _M_ext_buf; _M_ext_end = _M_ext_buf + __remainder; _M_set_buffer(-1); _M_state_last = _M_state_cur = _M_state_beg; } } else if (_M_writing && (__testvalid = _M_terminate_output())) _M_set_buffer(-1); } } if (__testvalid) _M_codecvt = _M_codecvt_tmp; else _M_codecvt = 0; } // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. #if _GLIBCXX_EXTERN_TEMPLATE extern template class basic_filebuf; extern template class basic_ifstream; extern template class basic_ofstream; extern template class basic_fstream; #ifdef _GLIBCXX_USE_WCHAR_T extern template class basic_filebuf; extern template class basic_ifstream; extern template class basic_ofstream; extern template class basic_fstream; #endif #endif _GLIBCXX_END_NAMESPACE #endif // Core algorithmic facilities -*- C++ -*- // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 // 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, // 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 _STL_ALGOBASE_H #define _STL_ALGOBASE_H 1 #include #include #include #include #include #include #include #include #include #include #include #include #include // For std::swap and _GLIBCXX_MOVE _GLIBCXX_BEGIN_NAMESPACE(std) // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a // nutshell, we are partially implementing the resolution of DR 187, // when it's safe, i.e., the value_types are equal. template struct __iter_swap { template static void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType1; _ValueType1 __tmp = _GLIBCXX_MOVE(*__a); *__a = _GLIBCXX_MOVE(*__b); *__b = _GLIBCXX_MOVE(__tmp); } }; template<> struct __iter_swap { template static void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { swap(*__a, *__b); } }; /** * @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 inline void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) { typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType1; typedef typename iterator_traits<_ForwardIterator2>::value_type _ValueType2; // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator1>) __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator2>) __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, _ValueType2>) __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, _ValueType1>) typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2; std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value && __are_same<_ValueType1&, _ReferenceType1>::__value && __are_same<_ValueType2&, _ReferenceType2>::__value>:: iter_swap(__a, __b); } /** * @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 _ForwardIterator2 swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator1>) __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< _ForwardIterator2>) __glibcxx_requires_valid_range(__first1, __last1); for (; __first1 != __last1; ++__first1, ++__first2) std::iter_swap(__first1, __first2); return __first2; } /** * @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 inline const _Tp& min(const _Tp& __a, const _Tp& __b) { // concept requirements __glibcxx_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 inline const _Tp& max(const _Tp& __a, const _Tp& __b) { // concept requirements __glibcxx_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 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 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; } // If _Iterator is a __normal_iterator return its base (a plain pointer, // normally) otherwise return it untouched. See copy, fill, ... template::__value> struct __niter_base { static _Iterator __b(_Iterator __it) { return __it; } }; template struct __niter_base<_Iterator, true> { static typename _Iterator::iterator_type __b(_Iterator __it) { return __it.base(); } }; // Likewise, for move_iterator. template::__value> struct __miter_base { static _Iterator __b(_Iterator __it) { return __it; } }; template struct __miter_base<_Iterator, true> { static typename _Iterator::iterator_type __b(_Iterator __it) { return __it.base(); } }; // All of these auxiliary structs 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 struct __copy_move { template static _OI __copy_m(_II __first, _II __last, _OI __result) { for (; __first != __last; ++__result, ++__first) *__result = *__first; return __result; } }; #ifdef __GXX_EXPERIMENTAL_CXX0X__ template struct __copy_move { template static _OI __copy_m(_II __first, _II __last, _OI __result) { for (; __first != __last; ++__result, ++__first) *__result = std::move(*__first); return __result; } }; #endif template<> struct __copy_move { template static _OI __copy_m(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::difference_type _Distance; for(_Distance __n = __last - __first; __n > 0; --__n) { *__result = *__first; ++__first; ++__result; } return __result; } }; #ifdef __GXX_EXPERIMENTAL_CXX0X__ template<> struct __copy_move { template static _OI __copy_m(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::difference_type _Distance; for(_Distance __n = __last - __first; __n > 0; --__n) { *__result = std::move(*__first); ++__first; ++__result; } return __result; } }; #endif template struct __copy_move<_IsMove, true, random_access_iterator_tag> { template static _Tp* __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) { __builtin_memmove(__ö+÷+ø+ù+ú+û+ü+ý+þ+ÿ+,,,,,,,,, , , , , ,,,,result, __first, sizeof(_Tp) * (__last - __first)); return __result + (__last - __first); } }; template inline _OI __copy_move_a(_II __first, _II __last, _OI __result) { typedef typename iterator_traits<_II>::value_type _ValueTypeI; typedef typename iterator_traits<_OI>::value_type _ValueTypeO; typedef typename iterator_traits<_II>::iterator_category _Category; const bool __simple = (__is_pod(_ValueTypeI) && __is_pointer<_II>::__value && __is_pointer<_OI>::__value && __are_same<_ValueTypeI, _ValueTypeO>::__value); return std::__copy_move<_IsMove, __simple, _Category>::__copy_m(__first, __last, __result); } // Helpers for streambuf iterators (either istream or ostream). // NB: avoid including , relatively large. template struct char_traits; template class istreambuf_iterator; template class ostreambuf_iterator; template typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type __copy_move_a2(_CharT*, _CharT*, ostreambuf_iterator<_CharT, char_traits<_CharT> >); template typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type __copy_move_a2(const _CharT*, const _CharT*, ostreambuf_iterator<_CharT, char_traits<_CharT> >); template typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, _CharT*>::__type __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >, istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*); template inline _OI __copy_move_a2(_II __first, _II __last, _OI __result) { return _OI(std::__copy_move_a<_IsMove> (std::__niter_base<_II>::__b(__first), std::__niter_base<_II>::__b(__last), std::__niter_base<_OI>::__b(__result))); } /** * @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). Result may not be contained within * [first,last); the copy_backward function should be used instead. * * Note that the end of the output range is permitted to be contained * within [first,last). */ template inline _OI copy(_II __first, _II __last, _OI __result) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II>) __glibcxx_function_requires(_OutputIteratorConcept<_OI, typename iterator_traits<_II>::value_type>) __glibcxx_requires_valid_range(__first, __last); return (std::__copy_move_a2<__is_move_iterator<_II>::__value> (std::__miter_base<_II>::__b(__first), std::__miter_base<_II>::__b(__last), __result)); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ /** * @brief Moves 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). Result may not be contained within * [first,last); the move_backward function should be used instead. * * Note that the end of the output range is permitted to be contained * within [first,last). */ template inline _OI move(_II __first, _II __last, _OI __result) { // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_II>) __glibcxx_function_requires(_OutputIteratorConcept<_OI, typename iterator_traits<_II>::value_type>) __glibcxx_requires_valid_range(__first, __last); return (std::__copy_move_a2 (std::__miter_base<_II>::__b(__first), std::__miter_base<_II>::__b(__last), __result)); } #define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) #else #define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) #endif template struct __copy_move_backward { template static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { while (__first != __last) *--__result = *--__last; return __result; } }; #ifdef __GXX_EXPERIMENTAL_CXX0X__ template struct __copy_move_backward { template static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { while (__first != __last) *--__result = std::move(*--__last); return __result; } }; #endif template<> struct __copy_move_backward { template static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { typename iterator_traits<_BI1>::difference_type __n; for (__n = __last - __first; __n > 0; --__n) *--__result = *--__last; return __result; } }; #ifdef __GXX_EXPERIMENTAL_CXX0X__ template<> struct __copy_move_backward { template static _BI2 __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) { typename iterator_traits<_BI1>::difference_type __n; for (__n = __last - __first; __n > 0; --__n) *--__result = std::move(*--__last); return __result; } }; #endif template struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> { template static _Tp* __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) { const ptrdiff_t _Num = __last - __first; __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); return __result - _Num; } }; template inline _BI2 __copy_move_backward_a(_BI1 __first, _BI1 __last, _BI2 __result) { typedef typename iterator_traits<_BI1>::value_type _ValueType1; typedef typename iterator_traits<_BI2>::value_type _ValueType2; typedef typename iterator_traits<_BI1>::iterator_category _Category; const bool __simple = (__is_pod(_ValueType1) && __is_pointer<_BI1>::__value && __is_pointer<_BI2>::__value && __are_same<_ValueType1, _ValueType2>::__value); return std::__copy_move_backward<_IsMove, __simple, _Category>::__copy_move_b(__first, __last, __result); } template inline _BI2 __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) { return _BI2(std::__copy_move_backward_a<_IsMove> (std::__niter_base<_BI1>::__b(__first), std::__niter_base<_BI1>::__b(__last), std::__niter_base<_BI2>::__b(__result))); } /** * @brief Copies the range [first,last) into result. * @param first A bidirectional iterator. * @param last A bidirectional iterator. * @param result A bidirectional 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). * * Result may not be in the range [first,last). Use copy instead. Note * that the start of the output range may overlap [first,last). */ template inline _BI2 copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) { // concept requirements __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) __glibcxx_function_requires(_ConvertibleConcept< typename iterator_traits<_BI1>::value_type, typename iterator_traits<_BI2>::value_type>) __glibcxx_requires_valid_range(__first, __last); return (std::__copy_move_backward_a2<__is_move_iterator<_BI1>::__value> (std::__miter_base<_BI1>::__b(__first), std::__miter_base<_BI1>::__b(__last), __result)); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ /** * @brief Moves the range [first,last) into result. * @param first A bidirectional iterator. * @param last A bidirectional iterator. * @param result A bidirectional iterator. * @return result - (first - last) * * The function has the same effect as move, 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). * * Result may not be in the range [first,last). Use move instead. Note * that the start of