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