///////////////////////////////////////////////////////////////////////////
// FILE: memory (Utilities for manipulating memory)
//
//                          Open Watcom Project
//
//    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
//
//  ========================================================================
//
//    This file contains Original Code and/or Modifications of Original
//    Code as defined in and that are subject to the Sybase Open Watcom
//    Public License version 1.0 (the 'License'). You may not use this file
//    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
//    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
//    provided with the Original Code and Modifications, and is also
//    available at www.sybase.com/developer/opensource.
//
//    The Original Code and all software distributed under the License are
//    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
//    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
//    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
//    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
//    NON-INFRINGEMENT. Please see the License for the specific language
//    governing rights and limitations under the License.
//
//  ========================================================================
//
// Description: This header is part of the C++ standard library. It
//              defines a number of helper templates to simplify the
//              handling of raw memory.
///////////////////////////////////////////////////////////////////////////
#ifndef _MEMORY_INCLUDED
#define _MEMORY_INCLUDED

#if !defined(_ENABLE_AUTODEPEND)
  #pragma read_only_file;
#endif


#ifndef __cplusplus
#error The header memory requires C++
#endif

#include <cstddef>
#include <iterator>
#include <new.h>

#define typename

#ifndef _WC_EXCEPTION_MACROS_
  #define _WC_EXCEPTION_MACROS_
  #ifdef _CPPUNWIND
    #define _WCTHROWS( __t )  throw( __t ) // Use for exception specifications.
    #define _WCTHROW( __t )   throw( __t ) // Use for throw statements.
    #define _WCTRY            try
    #define _WCHANDLERS       1
  #else
    #define _WCTHROWS( __t )
    #define _WCTHROW( __t )
    #define _WCTRY
  #endif
#endif

template<class Iterator, class T>
inline void _RawConstruct( Iterator ptr, const T &value )
{
    typedef typename iterator_traits<Iterator>::value_type value_type;
    new ( static_cast<void *>( &*ptr ) ) value_type( value );
}

template<class Iterator>
inline void _RawDestroy( Iterator ptr )
{
    typedef typename iterator_traits<Iterator>::value_type value_type;
    ptr->~value_type();
}

namespace std {

  template<class T> class allocator;

  // Allocator specialization for void.
  // template<>
  class allocator<void> {
  public:
    typedef void       *pointer;
    typedef const void *const_pointer;
    typedef void        value_type;
  };

  // Default allocator template.
  template<class T>
  class allocator {
  public:
    typedef       std::size_t    size_type;
    typedef       std::ptrdiff_t difference_type;
    typedef       T             *pointer;
    typedef const T             *const_pointer;
    typedef       T             &reference;
    typedef const T             &const_reference;
    typedef       T              value_type;
    // template<class U> struct rebind { typedef allocator<U> other; };

    allocator( )
      { }

    allocator( const allocator & )
      { }

    // template<class U> allocator( const allocator<U> & )

   ~allocator( )
      { }

    pointer address( reference r ) const
      { return( &r ); }

    const_pointer address( const_reference r ) const
      { return( &r ); }

    pointer allocate( size_type n, allocator<void>::const_pointer = 0 )
      { return( reinterpret_cast<T *>(new unsigned char[n * sizeof(T)]) ); }

    void deallocate( pointer p, size_type )
      { delete [] (unsigned char *)p; }

    size_type max_size() const
      { return 0; }  // FIX ME

    void construct( pointer p, const T &value )
      { new ((void *)p) T(value); }

    void destroy( pointer p )
      { ((T *)p)->~T(); }
  };

  // Templates for initializing blocks of uninitialized memory.

  template<class ForwardIterator, class T>
  void uninitialized_fill(
      ForwardIterator first,
      ForwardIterator last,
      const T &value )
  {
      typedef typename iterator_traits<ForwardIterator>::value_type value_type;
      ForwardIterator bookmark( first );

      _WCTRY {
          // Construct copies of value in the raw storage.
          while( first != last ) {
              _RawConstruct( first, value );
              ++first;
          }
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != first ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  template<class ForwardIterator, class Size, class T>
  void uninitialized_fill_n(
      ForwardIterator first,
      Size n,
      const T &value )
  {
      typedef typename iterator_traits<ForwardIterator>::value_type value_type;
      ForwardIterator bookmark( first );

      _WCTRY {
          // Construct n copies of value in raw storage.
          while( n-- ) {
              _RawConstruct( first, value );
              ++first;
          }
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != first ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  template<class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_copy(
      InputIterator first,
      InputIterator last,
      ForwardIterator dest )
  {
      typedef typename iterator_traits<ForwardIterator>::value_type value_type;
      ForwardIterator bookmark( dest );

      _WCTRY {
          // Copy objects from input sequence to raw storage.
          while( first != last ) {
              _RawConstruct( dest, *first );
              ++first;
              ++dest;
          }
          return( dest );
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != dest ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  // Auto_ptr template.
  template<class T>
  class auto_ptr {
    // template<class U> struct auto_ptr_ref { };
  public:
    typedef T element_type;

    explicit auto_ptr( T *p = 0 ) : ptr( p )
      { }

    auto_ptr( auto_ptr &other ) : ptr( other.release() )
      { }

    // template<class U> auto_ptr( auto_ptr<U> & );

    auto_ptr &operator=( auto_ptr &other )
      { reset( other.release() ); return( *this ); }

    // template<class U> auto_ptr &operator=( auto_ptr<U> & );

   ~auto_ptr( ) _WCTHROWS()
      { delete ptr; }

    T &operator*( ) const
      { return( *ptr ); }

    T *operator->( ) const
      { return( ptr ); }

    T *get( ) const
      { return( ptr ); }

    T *release( )
      { T *tmp = ptr; ptr = 0; return( tmp ); }

    void reset( T *p = 0 ) _WCTHROWS()
      { if (ptr != p) delete ptr; ptr = p; }

    // auto_ptr( auto_ptr_ref<T> ) _WCTHROWS();

    // template<class U> operator auto_ptr_ref<U>( ) _WCTHROWS();

    // template<class U> operator auto_ptr<U>( ) _WCTHROWS();

  private:
    T *ptr;
  };

} // namespace std.

#endif
