1 // Temporary buffer implementation -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 4 // 2010, 2011 5 // Free Software Foundation, Inc. 6 // 7 // This file is part of the GNU ISO C++ Library. This library is free 8 // software; you can redistribute it and/or modify it under the 9 // terms of the GNU General Public License as published by the 10 // Free Software Foundation; either version 3, or (at your option) 11 // any later version. 12 13 // This library is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 18 // Under Section 7 of GPL version 3, you are granted additional 19 // permissions described in the GCC Runtime Library Exception, version 20 // 3.1, as published by the Free Software Foundation. 21 22 // You should have received a copy of the GNU General Public License and 23 // a copy of the GCC Runtime Library Exception along with this program; 24 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25 // <http://www.gnu.org/licenses/>. 26 27 /* 28 * 29 * Copyright (c) 1994 30 * Hewlett-Packard Company 31 * 32 * Permission to use, copy, modify, distribute and sell this software 33 * and its documentation for any purpose is hereby granted without fee, 34 * provided that the above copyright notice appear in all copies and 35 * that both that copyright notice and this permission notice appear 36 * in supporting documentation. Hewlett-Packard Company makes no 37 * representations about the suitability of this software for any 38 * purpose. It is provided "as is" without express or implied warranty. 39 * 40 * 41 * Copyright (c) 1996,1997 42 * Silicon Graphics Computer Systems, Inc. 43 * 44 * Permission to use, copy, modify, distribute and sell this software 45 * and its documentation for any purpose is hereby granted without fee, 46 * provided that the above copyright notice appear in all copies and 47 * that both that copyright notice and this permission notice appear 48 * in supporting documentation. Silicon Graphics makes no 49 * representations about the suitability of this software for any 50 * purpose. It is provided "as is" without express or implied warranty. 51 */ 52 53 /** @file bits/stl_tempbuf.h 54 * This is an internal header file, included by other library headers. 55 * Do not attempt to use it directly. @headername{memory} 56 */ 57 58 #ifndef _STL_TEMPBUF_H 59 #define _STL_TEMPBUF_H 1 60 61 #include <bits/stl_algobase.h> 62 #include <bits/stl_construct.h> 63 64 namespace std _GLIBCXX_VISIBILITY(default) 65 { 66 _GLIBCXX_BEGIN_NAMESPACE_VERSION 67 68 /** 69 * @brief Allocates a temporary buffer. 70 * @param __len The number of objects of type Tp. 71 * @return See full description. 72 * 73 * Reinventing the wheel, but this time with prettier spokes! 74 * 75 * This function tries to obtain storage for @c __len adjacent Tp 76 * objects. The objects themselves are not constructed, of course. 77 * A pair<> is returned containing <em>the buffer s address and 78 * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if 79 * no storage can be obtained.</em> Note that the capacity obtained 80 * may be less than that requested if the memory is unavailable; 81 * you should compare len with the .second return value. 82 * 83 * Provides the nothrow exception guarantee. 84 */ 85 template<typename _Tp> 86 pair<_Tp*, ptrdiff_t> 87 get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT 88 { 89 const ptrdiff_t __max = 90 __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp); 91 if (__len > __max) 92 __len = __max; 93 94 while (__len > 0) 95 { 96 _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), 97 std::nothrow)); 98 if (__tmp != 0) 99 return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); 100 __len /= 2; 101 } 102 return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); 103 } 104 105 /** 106 * @brief The companion to get_temporary_buffer(). 107 * @param __p A buffer previously allocated by get_temporary_buffer. 108 * @return None. 109 * 110 * Frees the memory pointed to by __p. 111 */ 112 template<typename _Tp> 113 inline void 114 return_temporary_buffer(_Tp* __p) 115 { ::operator delete(__p, std::nothrow); } 116 117 118 /** 119 * This class is used in two places: stl_algo.h and ext/memory, 120 * where it is wrapped as the temporary_buffer class. See 121 * temporary_buffer docs for more notes. 122 */ 123 template<typename _ForwardIterator, typename _Tp> 124 class _Temporary_buffer 125 { 126 // concept requirements 127 __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept) 128 129 public: 130 typedef _Tp value_type; 131 typedef value_type* pointer; 132 typedef pointer iterator; 133 typedef ptrdiff_t size_type; 134 135 protected: 136 size_type _M_original_len; 137 size_type _M_len; 138 pointer _M_buffer; 139 140 public: 141 /// As per Table mumble. 142 size_type 143 size() const 144 { return _M_len; } 145 146 /// Returns the size requested by the constructor; may be >size(). 147 size_type 148 requested_size() const 149 { return _M_original_len; } 150 151 /// As per Table mumble. 152 iterator 153 begin() 154 { return _M_buffer; } 155 156 /// As per Table mumble. 157 iterator 158 end() 159 { return _M_buffer + _M_len; } 160 161 /** 162 * Constructs a temporary buffer of a size somewhere between 163 * zero and the size of the given range. 164 */ 165 _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last); 166 167 ~_Temporary_buffer() 168 { 169 std::_Destroy(_M_buffer, _M_buffer + _M_len); 170 std::return_temporary_buffer(_M_buffer); 171 } 172 173 private: 174 // Disable copy constructor and assignment operator. 175 _Temporary_buffer(const _Temporary_buffer&); 176 177 void 178 operator=(const _Temporary_buffer&); 179 }; 180 181 182 template<bool> 183 struct __uninitialized_construct_buf_dispatch 184 { 185 template<typename _ForwardIterator, typename _Tp> 186 static void 187 __ucr(_ForwardIterator __first, _ForwardIterator __last, 188 _Tp& __value) 189 { 190 if(__first == __last) 191 return; 192 193 _ForwardIterator __cur = __first; 194 __try 195 { 196 std::_Construct(std::__addressof(*__first), 197 _GLIBCXX_MOVE(__value)); 198 _ForwardIterator __prev = __cur; 199 ++__cur; 200 for(; __cur != __last; ++__cur, ++__prev) 201 std::_Construct(std::__addressof(*__cur), 202 _GLIBCXX_MOVE(*__prev)); 203 __value = _GLIBCXX_MOVE(*__prev); 204 } 205 __catch(...) 206 { 207 std::_Destroy(__first, __cur); 208 __throw_exception_again; 209 } 210 } 211 }; 212 213 template<> 214 struct __uninitialized_construct_buf_dispatch<true> 215 { 216 template<typename _ForwardIterator, typename _Tp> 217 static void 218 __ucr(_ForwardIterator, _ForwardIterator, _Tp&) { } 219 }; 220 221 // Constructs objects in the range [first, last). 222 // Note that while these new objects will take valid values, 223 // their exact value is not defined. In particular they may 224 // be 'moved from'. 225 // 226 // While __value may altered during this algorithm, it will have 227 // the same value when the algorithm finishes, unless one of the 228 // constructions throws. 229 // 230 // Requirements: _ForwardIterator::value_type(_Tp&&) is valid. 231 template<typename _ForwardIterator, typename _Tp> 232 inline void 233 __uninitialized_construct_buf(_ForwardIterator __first, 234 _ForwardIterator __last, 235 _Tp& __value) 236 { 237 typedef typename std::iterator_traits<_ForwardIterator>::value_type 238 _ValueType; 239 240 std::__uninitialized_construct_buf_dispatch< 241 __has_trivial_constructor(_ValueType)>:: 242 __ucr(__first, __last, __value); 243 } 244 245 template<typename _ForwardIterator, typename _Tp> 246 _Temporary_buffer<_ForwardIterator, _Tp>:: 247 _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) 248 : _M_original_len(std::distance(__first, __last)), 249 _M_len(0), _M_buffer(0) 250 { 251 __try 252 { 253 std::pair<pointer, size_type> __p(std::get_temporary_buffer< 254 value_type>(_M_original_len)); 255 _M_buffer = __p.first; 256 _M_len = __p.second; 257 if(_M_buffer) 258 std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len, 259 *__first); 260 } 261 __catch(...) 262 { 263 std::return_temporary_buffer(_M_buffer); 264 _M_buffer = 0; 265 _M_len = 0; 266 __throw_exception_again; 267 } 268 } 269 270 _GLIBCXX_END_NAMESPACE_VERSION 271 } // namespace 272 273 #endif /* _STL_TEMPBUF_H */ 274 275