/*
 * Copyright (c) 1999
 * Boris Fomitchev
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 */

#ifndef _STLP_INTERNAL_NEW
#define _STLP_INTERNAL_NEW

#ifndef _STLP_INTERNAL_CSTDDEF
// size_t
#  include <stl/_cstddef.h>
#endif

#if defined (__BORLANDC__) && (__BORLANDC__ < 0x580)
// new.h uses ::malloc ;(
#  include _STLP_NATIVE_CPP_C_HEADER(cstdlib)
using _STLP_VENDOR_CSTD::malloc;
#endif

#if !defined (_STLP_NO_NEW_NEW_HEADER)
#  if defined (_STLP_BROKEN_BAD_ALLOC_CLASS)
#    define bad_alloc _STLP_NULLIFIED_BROKEN_BAD_ALLOC_CLASS
#    define nothrow_t _STLP_NULLIFIED_BROKEN_BAD_NOTHROW_T_CLASS
#    define nothrow _STLP_NULLIFIED_BROKEN_BAD_NOTHROW
#  endif

// eMbedded Visual C++ .NET unfortunately uses _INC_NEW for both <new.h> and <new>
// we undefine the symbol to get the stuff in the SDK's <new>
#  if defined (_STLP_WCE_NET) && defined (_INC_NEW)
#    undef _INC_NEW
#  endif

#  if defined (new)
/* STLport cannot replace native Std library new header if new is a macro,
 * please define new macro after <new> header inclusion.
 */
#    error Cannot include native new header as new is a macro.
#  endif

#  include _STLP_NATIVE_CPP_RUNTIME_HEADER(new)

#  if defined (_STLP_BROKEN_BAD_ALLOC_CLASS)
#    undef bad_alloc
#    undef nothrow_t
#    undef nothrow
#    undef _STLP_NULLIFIED_BROKEN_BAD_ALLOC_CLASS
#    undef _STLP_NULLIFIED_BROKEN_BAD_NOTHROW_T_CLASS
#    undef _STLP_NULLIFIED_BROKEN_BAD_NOTHROW
#  endif
#else
#  include <new.h>
#endif

#if defined (_STLP_NO_BAD_ALLOC) && !defined (_STLP_NEW_DONT_THROW_BAD_ALLOC)
#  define _STLP_NEW_DONT_THROW_BAD_ALLOC 1
#endif

#if defined (_STLP_USE_EXCEPTIONS) && defined (_STLP_NEW_DONT_THROW_BAD_ALLOC)

#  ifndef _STLP_INTERNAL_EXCEPTION
#    include <stl/_exception.h>
#  endif

_STLP_BEGIN_NAMESPACE

#  if defined (_STLP_NO_BAD_ALLOC)
struct nothrow_t {};
#    define nothrow nothrow_t()
#  endif

/*
 * STLport own bad_alloc exception to be used if the native C++ library
 * do not define it or when the new operator do not throw it to avoid
 * a useless library dependency.
 */
class bad_alloc : public exception {
public:
  bad_alloc () _STLP_NOTHROW_INHERENTLY { }
  bad_alloc(const bad_alloc&) _STLP_NOTHROW_INHERENTLY { }
  bad_alloc& operator=(const bad_alloc&) _STLP_NOTHROW_INHERENTLY {return *this;}
  ~bad_alloc () _STLP_NOTHROW_INHERENTLY { }
  const char* what() const _STLP_NOTHROW_INHERENTLY { return "bad alloc"; }
};

_STLP_END_NAMESPACE

#endif /* _STLP_USE_EXCEPTIONS && (_STLP_NO_BAD_ALLOC || _STLP_NEW_DONT_THROW_BAD_ALLOC) */

#if defined (_STLP_RTTI_BUG)
_STLP_BEGIN_NAMESPACE

inline void* _STLP_CALL __stl_new(size_t __n)
{ return ::malloc(__n); }

inline void _STLP_CALL __stl_delete(void* __p)
{ ::free(__p); }
_STLP_END_NAMESPACE

#else /* _STLP_RTTI_BUG */

#  if defined (_STLP_USE_OWN_NAMESPACE)

_STLP_BEGIN_NAMESPACE

#    if !defined (_STLP_NEW_DONT_THROW_BAD_ALLOC)
using _STLP_VENDOR_EXCEPT_STD::bad_alloc;
#    endif

#    if !defined (_STLP_NO_BAD_ALLOC)
using _STLP_VENDOR_EXCEPT_STD::nothrow_t;
using _STLP_VENDOR_EXCEPT_STD::nothrow;
#      if defined (_STLP_GLOBAL_NEW_HANDLER)
using ::new_handler;
using ::set_new_handler;
#      else
using _STLP_VENDOR_EXCEPT_STD::new_handler;
using _STLP_VENDOR_EXCEPT_STD::set_new_handler;
#      endif
#    endif /* !_STLP_NO_BAD_ALLOC */

_STLP_END_NAMESPACE
#  endif /* _STLP_USE_OWN_NAMESPACE */

#  if defined (_STLP_USE_EXCEPTIONS) && \
     (defined (_STLP_NO_NEW_NEW_HEADER) || defined (_STLP_NEW_DONT_THROW_BAD_ALLOC))
#    define _STLP_CHECK_NULL_ALLOC(__x) void* __y = __x; if (__y == 0) { _STLP_THROW(_STLP_STD::bad_alloc()); } return __y
#  else
#    define _STLP_CHECK_NULL_ALLOC(__x) return __x
#  endif

_STLP_BEGIN_NAMESPACE

#  if ((defined (__IBMCPP__) || defined (__OS400__) || defined (__xlC__) || defined (qTidyHeap)) && defined (__DEBUG_ALLOC__))
inline void* _STLP_CALL __stl_new(size_t __n)   { _STLP_CHECK_NULL_ALLOC(::operator _STLP_NEW(__n, __FILE__, __LINE__)); }
inline void  _STLP_CALL __stl_delete(void* __p) { ::operator delete(__p, __FILE__, __LINE__); }
#  else
inline void* _STLP_CALL __stl_new(size_t __n)   { _STLP_CHECK_NULL_ALLOC(::operator _STLP_NEW(__n)); }
inline void  _STLP_CALL __stl_delete(void* __p) { ::operator delete(__p); }
#  endif
_STLP_END_NAMESPACE

#endif /* _STLP_RTTI_BUG */

#endif /* _STLP_INTERNAL_NEW */


/*
 * Local Variables:
 * mode:C++
 * End:
 */
