// debug heap support header for Microsoft
#pragma once
#ifndef _XDEBUG_
#define _XDEBUG_
#include <yvals.h>

#pragma pack(push,8)
#pragma warning(push,3)

		// SUPPORT FOR DEBUG HEAP

 #if !defined(_DEBUG)
  #define _NEW_CRT				new
  #define _DELETE_CRT(_P)		delete (_P)
  #define _DELETE_CRT_VEC(_P)	delete[] (_P)
  #define _STRING_CRT			string

 #else /* !defined(_DEBUG) */
  #include <xmemory>
  #include <xstring>

_STD_BEGIN
struct _DebugHeapTag_t
	{	// placement new tag type to select debug CRT heap
	int _Type;
	};
_STD_END

_CRTIMP2 void * __cdecl operator new(size_t,
	const std::_DebugHeapTag_t&, char *, int)
		_THROW1(std::bad_alloc);	// allocate from the debug CRT heap

_CRTIMP2 void * __cdecl operator new[](size_t,
	const std::_DebugHeapTag_t&, char *, int)
		_THROW1(std::bad_alloc);	// allocate array from the debug CRT heap

_CRTIMP2 void __cdecl operator delete(void *,
	const std::_DebugHeapTag_t&, char *, int)
		_THROW0();	// delete if new for debug CRT heap fails

_CRTIMP2 void __cdecl operator delete[](void *,
	const std::_DebugHeapTag_t&, char *, int)
		_THROW0();	// delete if array new for debug CRT heap fails

_STD_BEGIN

  #define _NEW_CRT				new(std::_DebugHeapTag, __FILE__, __LINE__)
  #define _DELETE_CRT(_P)		std::_DebugHeapDelete(_P)
  #define _DELETE_CRT_VEC(_P)	std::_DebugHeapDelete((void *)_P)
  #define _STRING_CRT			_DebugHeapString

extern _CRTIMP2 const _DebugHeapTag_t _DebugHeapTag;

		// TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
	void _DebugHeapDelete(_Ty *_Ptr)
	{	// delete from the debug CRT heap even if operator delete exists
	if (_Ptr != 0)
		{	// worth deleting
		_Ptr->~_Ty();
		// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
		// facets allocated by normal new.
		free(_Ptr);
		}
	}

		// TEMPLATE CLASS _DebugHeapAllocator
template<class _Ty>
	class _DebugHeapAllocator
	: public allocator<_Ty>
	{	// an allocator which uses the debug CRT heap
public:

	template<class _Other>
		struct rebind
		{	// convert _DebugHeapAllocator<_Ty> to _DebugHeapAllocator<_Other>
		typedef typename _DebugHeapAllocator<_Other> other;
		};

	allocator<_Ty>::pointer allocate(allocator<_Ty>::size_type _Count, const void *)
		{	// allocate array of _Count elements, ignore hint
		return ((_Ty *)_NEW_CRT char[_Count * sizeof(_Ty)]);
		}

	allocator<_Ty>::pointer allocate(allocator<_Ty>::size_type _Count)
		{	// allocate array of _Count elements
		return ((_Ty *)_NEW_CRT char[_Count * sizeof(_Ty)]);
		}

	void deallocate(allocator<_Ty>::pointer _Ptr, allocator<_Ty>::size_type)
		{	// deallocate object at _Ptr, ignore size
		_DELETE_CRT_VEC(_Ptr);
		}
	};

		// CLASS _DebugHeapString
class _DebugHeapString
	: public basic_string<char, char_traits<char>, _DebugHeapAllocator<char> >
	{	// a version of std::string allocated on the debug CRT heap
public:
	typedef _DebugHeapString _Myt;
	typedef basic_string<char, char_traits<char>, _DebugHeapAllocator<char> >
		_Mybase;
	typedef char _Elem;

	_DebugHeapString()
		: _Mybase()
		{	// construct empty string
		}

	_DebugHeapString(const _Myt& _Right)
		: _Mybase(_Right)
		{	// construct by copying _Right
		}

	_DebugHeapString(const _Elem *_Ptr)
		: _Mybase(_Ptr)
		{	// construct from [_Ptr, <null>)
		}

	_DebugHeapString(const string &_Str)
		: _Mybase(_Str.c_str())
		{	// construct from std::string
		}

	operator string() const
		{	// convert to a string
		return (string(c_str()));
		}
	};
_STD_END
 #endif  /* !defined(_DEBUG) */

#pragma warning(pop)
#pragma pack(pop)


#endif  /* _XDEBUG_ */

/*
 * Copyright (c) 1992-2002 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V3.13:0009 */
