1    	// Temporary buffer implementation -*- C++ -*-
2    	
3    	// Copyright (C) 2001-2013 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