// Memory extensions -*- C++ -*-

// Copyright (C) 2002-2021 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 3, 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.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/*
 *
 * 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
 * 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 ext/memory
 *  This file is a GNU extension to the Standard C++ Library (possibly
 *  containing extensions from the HP/SGI STL subset).
 */

#ifndef _EXT_MEMORY
#define _EXT_MEMORY 1

#pragma GCC system_header

#include <memory>
#include <bits/stl_tempbuf.h>

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  using std::_Temporary_buffer;

  template<typename _InputIter, typename _Size, typename _ForwardIter>
    std::pair<_InputIter, _ForwardIter>
    __uninitialized_copy_n(_InputIter __first, _Size __count,
			   _ForwardIter __result, std::input_iterator_tag)
    {
      _ForwardIter __cur = __result;
      __try
	{
	  for (; __count > 0 ; --__count, ++__first, ++__cur)
	    std::_Construct(&*__cur, *__first);
	  return std::pair<_InputIter, _ForwardIter>(__first, __cur);
	}
      __catch(...)
	{
	  std::_Destroy(__result, __cur);
	  __throw_exception_again;
	}
    }

  template<typename _RandomAccessIter, typename _Size, typename _ForwardIter>
    inline std::pair<_RandomAccessIter, _ForwardIter>
    __uninitialized_copy_n(_RandomAccessIter __first, _Size __count,
			   _ForwardIter __result,
			   std::random_access_iterator_tag)
    {
      _RandomAccessIter __last = __first + __count;
      return (std::pair<_RandomAccessIter, _ForwardIter>
	      (__last, std::uninitialized_copy(__first, __last, __result)));
    }

  template<typename _InputIter, typename _Size, typename _ForwardIter>
    inline std::pair<_InputIter, _ForwardIter>
    __uninitialized_copy_n(_InputIter __first, _Size __count,
			   _ForwardIter __result)
    {
      return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result,
	  std::__iterator_category(__first));
    }

  /**
   *  @brief Copies the range [first,last) into result.
   *  @param  __first  An input iterator.
   *  @param  __count  Length
   *  @param  __result An output iterator.
   *  @return   __result + (__first + __count)
   *  @ingroup SGIextensions
   *
   *  Like copy(), but does not require an initialized output range.
  */
  template<typename _InputIter, typename _Size, typename _ForwardIter>
    inline std::pair<_InputIter, _ForwardIter>
    uninitialized_copy_n(_InputIter __first, _Size __count,
			 _ForwardIter __result)
    {
      return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result,
	  std::__iterator_category(__first));
    }


  // An alternative version of uninitialized_copy_n that constructs
  // and destroys objects with a user-provided allocator.
  template<typename _InputIter, typename _Size, typename _ForwardIter,
           typename _Allocator>
    std::pair<_InputIter, _ForwardIter>
    __uninitialized_copy_n_a(_InputIter __first, _Size __count,
			     _ForwardIter __result,
			     _Allocator __alloc)
    {
      _ForwardIter __cur = __result;
      __try
	{
	  for (; __count > 0 ; --__count, ++__first, ++__cur)
	    __alloc.construct(&*__cur, *__first);
	  return std::pair<_InputIter, _ForwardIter>(__first, __cur);
	}
      __catch(...)
	{
	  std::_Destroy(__result, __cur, __alloc);
	  __throw_exception_again;
	}
    }

  template<typename _InputIter, typename _Size, typename _ForwardIter,
           typename _Tp>
    inline std::pair<_InputIter, _ForwardIter>
    __uninitialized_copy_n_a(_InputIter __first, _Size __count,
			     _ForwardIter __result,
			     std::allocator<_Tp>)
    {
      return __gnu_cxx::uninitialized_copy_n(__first, __count, __result);
    }

  /**
   *  This class provides similar behavior and semantics of the standard
   *  functions get_temporary_buffer() and return_temporary_buffer(), but
   *  encapsulated in a type vaguely resembling a standard container.
   *
   *  By default, a temporary_buffer<Iter> stores space for objects of
   *  whatever type the Iter iterator points to.  It is constructed from a
   *  typical [first,last) range, and provides the begin(), end(), size()
   *  functions, as well as requested_size().  For non-trivial types, copies
   *  of *first will be used to initialize the storage.
   *
   *  @c malloc is used to obtain underlying storage.
   *
   *  Like get_temporary_buffer(), not all the requested memory may be
   *  available.  Ideally, the created buffer will be large enough to hold a
   *  copy of [first,last), but if size() is less than requested_size(),
   *  then this didn't happen.
   *
   *  @ingroup SGIextensions
  */
  template <class _ForwardIterator, class _Tp
	    = typename std::iterator_traits<_ForwardIterator>::value_type >
    struct temporary_buffer : public _Temporary_buffer<_ForwardIterator, _Tp>
    {
      /// Requests storage large enough to hold a copy of [first,last).
      temporary_buffer(_ForwardIterator __first, _ForwardIterator __last)
      : _Temporary_buffer<_ForwardIterator, _Tp>(__first,
						 std::distance(__first, __last))
      { }
      
      /// Destroys objects and frees storage.
      ~temporary_buffer() { }
    };

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif

