libstdc++
|
00001 // Temporary buffer implementation -*- C++ -*- 00002 00003 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 00004 // 2010, 2011 00005 // Free Software Foundation, Inc. 00006 // 00007 // This file is part of the GNU ISO C++ Library. This library is free 00008 // software; you can redistribute it and/or modify it under the 00009 // terms of the GNU General Public License as published by the 00010 // Free Software Foundation; either version 3, or (at your option) 00011 // any later version. 00012 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 00018 // Under Section 7 of GPL version 3, you are granted additional 00019 // permissions described in the GCC Runtime Library Exception, version 00020 // 3.1, as published by the Free Software Foundation. 00021 00022 // You should have received a copy of the GNU General Public License and 00023 // a copy of the GCC Runtime Library Exception along with this program; 00024 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00025 // <http://www.gnu.org/licenses/>. 00026 00027 /* 00028 * 00029 * Copyright (c) 1994 00030 * Hewlett-Packard Company 00031 * 00032 * Permission to use, copy, modify, distribute and sell this software 00033 * and its documentation for any purpose is hereby granted without fee, 00034 * provided that the above copyright notice appear in all copies and 00035 * that both that copyright notice and this permission notice appear 00036 * in supporting documentation. Hewlett-Packard Company makes no 00037 * representations about the suitability of this software for any 00038 * purpose. It is provided "as is" without express or implied warranty. 00039 * 00040 * 00041 * Copyright (c) 1996,1997 00042 * Silicon Graphics Computer Systems, Inc. 00043 * 00044 * Permission to use, copy, modify, distribute and sell this software 00045 * and its documentation for any purpose is hereby granted without fee, 00046 * provided that the above copyright notice appear in all copies and 00047 * that both that copyright notice and this permission notice appear 00048 * in supporting documentation. Silicon Graphics makes no 00049 * representations about the suitability of this software for any 00050 * purpose. It is provided "as is" without express or implied warranty. 00051 */ 00052 00053 /** @file bits/stl_tempbuf.h 00054 * This is an internal header file, included by other library headers. 00055 * Do not attempt to use it directly. @headername{memory} 00056 */ 00057 00058 #ifndef _STL_TEMPBUF_H 00059 #define _STL_TEMPBUF_H 1 00060 00061 #include <bits/stl_algobase.h> 00062 #include <bits/stl_construct.h> 00063 00064 namespace std _GLIBCXX_VISIBILITY(default) 00065 { 00066 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00067 00068 /** 00069 * @brief Allocates a temporary buffer. 00070 * @param __len The number of objects of type Tp. 00071 * @return See full description. 00072 * 00073 * Reinventing the wheel, but this time with prettier spokes! 00074 * 00075 * This function tries to obtain storage for @c __len adjacent Tp 00076 * objects. The objects themselves are not constructed, of course. 00077 * A pair<> is returned containing <em>the buffer s address and 00078 * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if 00079 * no storage can be obtained.</em> Note that the capacity obtained 00080 * may be less than that requested if the memory is unavailable; 00081 * you should compare len with the .second return value. 00082 * 00083 * Provides the nothrow exception guarantee. 00084 */ 00085 template<typename _Tp> 00086 pair<_Tp*, ptrdiff_t> 00087 get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT 00088 { 00089 const ptrdiff_t __max = 00090 __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp); 00091 if (__len > __max) 00092 __len = __max; 00093 00094 while (__len > 0) 00095 { 00096 _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), 00097 std::nothrow)); 00098 if (__tmp != 0) 00099 return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); 00100 __len /= 2; 00101 } 00102 return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); 00103 } 00104 00105 /** 00106 * @brief The companion to get_temporary_buffer(). 00107 * @param __p A buffer previously allocated by get_temporary_buffer. 00108 * @return None. 00109 * 00110 * Frees the memory pointed to by __p. 00111 */ 00112 template<typename _Tp> 00113 inline void 00114 return_temporary_buffer(_Tp* __p) 00115 { ::operator delete(__p, std::nothrow); } 00116 00117 00118 /** 00119 * This class is used in two places: stl_algo.h and ext/memory, 00120 * where it is wrapped as the temporary_buffer class. See 00121 * temporary_buffer docs for more notes. 00122 */ 00123 template<typename _ForwardIterator, typename _Tp> 00124 class _Temporary_buffer 00125 { 00126 // concept requirements 00127 __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept) 00128 00129 public: 00130 typedef _Tp value_type; 00131 typedef value_type* pointer; 00132 typedef pointer iterator; 00133 typedef ptrdiff_t size_type; 00134 00135 protected: 00136 size_type _M_original_len; 00137 size_type _M_len; 00138 pointer _M_buffer; 00139 00140 public: 00141 /// As per Table mumble. 00142 size_type 00143 size() const 00144 { return _M_len; } 00145 00146 /// Returns the size requested by the constructor; may be >size(). 00147 size_type 00148 requested_size() const 00149 { return _M_original_len; } 00150 00151 /// As per Table mumble. 00152 iterator 00153 begin() 00154 { return _M_buffer; } 00155 00156 /// As per Table mumble. 00157 iterator 00158 end() 00159 { return _M_buffer + _M_len; } 00160 00161 /** 00162 * Constructs a temporary buffer of a size somewhere between 00163 * zero and the size of the given range. 00164 */ 00165 _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last); 00166 00167 ~_Temporary_buffer() 00168 { 00169 std::_Destroy(_M_buffer, _M_buffer + _M_len); 00170 std::return_temporary_buffer(_M_buffer); 00171 } 00172 00173 private: 00174 // Disable copy constructor and assignment operator. 00175 _Temporary_buffer(const _Temporary_buffer&); 00176 00177 void 00178 operator=(const _Temporary_buffer&); 00179 }; 00180 00181 00182 template<bool> 00183 struct __uninitialized_construct_buf_dispatch 00184 { 00185 template<typename _ForwardIterator, typename _Tp> 00186 static void 00187 __ucr(_ForwardIterator __first, _ForwardIterator __last, 00188 _Tp& __value) 00189 { 00190 if(__first == __last) 00191 return; 00192 00193 _ForwardIterator __cur = __first; 00194 __try 00195 { 00196 std::_Construct(std::__addressof(*__first), 00197 _GLIBCXX_MOVE(__value)); 00198 _ForwardIterator __prev = __cur; 00199 ++__cur; 00200 for(; __cur != __last; ++__cur, ++__prev) 00201 std::_Construct(std::__addressof(*__cur), 00202 _GLIBCXX_MOVE(*__prev)); 00203 __value = _GLIBCXX_MOVE(*__prev); 00204 } 00205 __catch(...) 00206 { 00207 std::_Destroy(__first, __cur); 00208 __throw_exception_again; 00209 } 00210 } 00211 }; 00212 00213 template<> 00214 struct __uninitialized_construct_buf_dispatch<true> 00215 { 00216 template<typename _ForwardIterator, typename _Tp> 00217 static void 00218 __ucr(_ForwardIterator, _ForwardIterator, _Tp&) { } 00219 }; 00220 00221 // Constructs objects in the range [first, last). 00222 // Note that while these new objects will take valid values, 00223 // their exact value is not defined. In particular they may 00224 // be 'moved from'. 00225 // 00226 // While __value may altered during this algorithm, it will have 00227 // the same value when the algorithm finishes, unless one of the 00228 // constructions throws. 00229 // 00230 // Requirements: _ForwardIterator::value_type(_Tp&&) is valid. 00231 template<typename _ForwardIterator, typename _Tp> 00232 inline void 00233 __uninitialized_construct_buf(_ForwardIterator __first, 00234 _ForwardIterator __last, 00235 _Tp& __value) 00236 { 00237 typedef typename std::iterator_traits<_ForwardIterator>::value_type 00238 _ValueType; 00239 00240 std::__uninitialized_construct_buf_dispatch< 00241 __has_trivial_constructor(_ValueType)>:: 00242 __ucr(__first, __last, __value); 00243 } 00244 00245 template<typename _ForwardIterator, typename _Tp> 00246 _Temporary_buffer<_ForwardIterator, _Tp>:: 00247 _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) 00248 : _M_original_len(std::distance(__first, __last)), 00249 _M_len(0), _M_buffer(0) 00250 { 00251 __try 00252 { 00253 std::pair<pointer, size_type> __p(std::get_temporary_buffer< 00254 value_type>(_M_original_len)); 00255 _M_buffer = __p.first; 00256 _M_len = __p.second; 00257 if(_M_buffer) 00258 std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len, 00259 *__first); 00260 } 00261 __catch(...) 00262 { 00263 std::return_temporary_buffer(_M_buffer); 00264 _M_buffer = 0; 00265 _M_len = 0; 00266 __throw_exception_again; 00267 } 00268 } 00269 00270 _GLIBCXX_END_NAMESPACE_VERSION 00271 } // namespace 00272 00273 #endif /* _STL_TEMPBUF_H */ 00274