Files
FC1/CryCommon/StlDbgAlloc.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

429 lines
12 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////////////////
// Debug allocator and common STL classes using the allocator.
// Provides the MSVC heap runtime with the information about the source of allocation:
// prevents NO_SOURCE_0 for the allocation source for STL classes.
// USAGE:
// Include vector, string, set, map
// Include crtdbg
// inlcude this file
// Use cry::vector instead of std::vector,
// cry::string instead of string,
// cry::set instead of std::set
// cry::map instead of std::map
//
// In order to specify your own source of allocation, in the constructor specify one or two parameters
// like:
// ...
// cry::map<int,cry::string> m_mapSomething;
// ...
// (in the constructor initializer list:)
// ...
// m_mapSomething ("My class.mapSomething", 0),
// ...
// This works for vector, set and map. For string, specify:
// cry::string strMyString ("Your string", cry::string::_Allocator("My Source.strMyString", 0));
//
// NOTE:
// You MUST include the map, string, vector and set in order to cry:: classes to be defined here.
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _CRY_DBG_ALLOCATOR_HDR_
#define _CRY_DBG_ALLOCATOR_HDR_
#include <string>
#include <set>
#include <vector>
#include <map>
#include <iterator>
#ifdef WIN32
#include <xmemory>
#endif
#include "TAlloc.h"
namespace cry
{
#if defined(_DEBUG) && defined(_INC_CRTDBG) && defined(WIN32)
// This is just a debug mode build allocator. In release mode build it just defaults to the std::allocator
// The szSource is the actual reason for this class - it will call operator new using this as the source file allocating the block
// (of course this can be any name). THe number is just because the std lib interface already accepts line number
// This allocator has static fields, meaning that copying it won't copy the szSource and nSource properties
template<class T>
class dbg_allocator: public TSimpleAllocator<T>
{ // generic allocator for objects of class T
public:
typedef _SIZT size_type;
typedef _PDFT difference_type;
typedef T _FARQ *pointer;
typedef const T _FARQ *const_pointer;
typedef T _FARQ& reference;
typedef const T _FARQ& const_reference;
typedef T value_type;
template<class _Other>
struct rebind
{ // convert an allocator<T> to an allocator <_Other>
typedef dbg_allocator<_Other> other;
};
pointer address(reference _Val) const
{ // return address of mutable _Val
return (&_Val);
}
const_pointer address(const_reference _Val) const
{ // return address of nonmutable _Val
return (&_Val);
}
dbg_allocator<T>(const char* szParentObject = "cry_dbg_alloc", int nParentIndex = 0):
m_szParentObject(szParentObject),
m_nParentIndex (nParentIndex)
{ // construct default allocator (do nothing)
}
dbg_allocator(const dbg_allocator<T>& rThat)
{ // construct by copying (do nothing)
m_szParentObject = rThat.m_szParentObject;
m_nParentIndex = rThat.m_nParentIndex;
}
template<class _Other>
dbg_allocator(const dbg_allocator<_Other>&rThat)
{ // construct from a related allocator (do nothing)
m_szParentObject = rThat.m_szParentObject;
m_nParentIndex = rThat.m_nParentIndex;
}
template<class _Other>
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat)
{ // assign from a related allocator (do nothing)
m_szParentObject = rThat.m_szParentObject;
m_nParentIndex = rThat.m_nParentIndex;
return (*this);
}
pointer allocate(size_type _Count, const void *)
{ // allocate array of _Count elements, ignore hint
return allocate (_Count);
}
pointer allocate(size_type _Count)
{ // allocate array of _Count elements
return (pointer)_malloc_dbg(_Count * sizeof(T), _NORMAL_BLOCK, m_szParentObject, m_nParentIndex);
}
void deallocate(pointer _Ptr, size_type)
{ // deallocate object at _Ptr, ignore size
_free_dbg(_Ptr, _NORMAL_BLOCK);
}
void construct(pointer _Ptr, const T& _Val)
{ // construct object at _Ptr with value _Val
std::_Construct(_Ptr, _Val);
}
void destroy(pointer _Ptr)
{ // destroy object at _Ptr
_Ptr->~T();
}
_SIZT max_size() const
{ // estimate maximum array size
_SIZT _Count = (_SIZT)(-1) / sizeof (T);
return (0 < _Count ? _Count : 1);
}
// the parent object (on behalf of which to call the new operator)
const char* m_szParentObject; // the file name
int m_nParentIndex; // the file line number
};
template<class _Ty,
class _Other> inline
bool operator==(const dbg_allocator<_Ty>&rLeft, const dbg_allocator<_Other>&rRight)
{ // test for allocator equality (always true)
return rLeft.m_szParentObject == rRight.m_szParentObject && rLeft.m_nParentIndex == rRight.m_nParentIndex;
}
template<class _Ty,
class _Other> inline
bool operator!=(const dbg_allocator<_Ty>&, const dbg_allocator<_Other>&)
{ // test for allocator inequality (always false)
return rLeft.m_szParentObject != rRight.m_szParentObject && rLeft.m_nParentIndex != rRight.m_nParentIndex;
}
/*
template<class T>
class dbg_allocator: public TSimpleAllocator<T>
{ // generic allocator for objects of class T
public:
dbg_allocator<T>()
{
}
dbg_allocator<T>(const char* szParentObject, int nParentIndex = 0):
TSimpleAllocator<T>(szParentObject, nParentIndex)
{ // construct default allocator (do nothing)
}
dbg_allocator<T>(const dbg_allocator<T>& rThat):
TSimpleAllocator<T>(rThat)
{ // construct by copying (do nothing)
}
template<class _Other>
dbg_allocator(const dbg_allocator<_Other>&rThat):
TSimpleAllocator<T>(rThat)
{ // construct from a related allocator (do nothing)
}
template<class _Other>
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat)
{ // assign from a related allocator (do nothing)
*static_cast<TSimpleAllocator<T>*>(this) = rThat;
return (*this);
}
};
*/
template<class T>
class dbg_struct_allocator: public TSimpleStructAllocator<T>
{ // generic allocator for objects of class T
public:
dbg_struct_allocator<T>()
{
}
dbg_struct_allocator<T>(const char* szParentObject, int nParentIndex = 0):
TSimpleStructAllocator<T>(szParentObject, nParentIndex)
{ // construct default allocator (do nothing)
}
dbg_struct_allocator<T>(const dbg_struct_allocator<T>& rThat):
TSimpleStructAllocator<T>(rThat)
{ // construct by copying (do nothing)
}
template<class _Other>
dbg_struct_allocator(const dbg_struct_allocator<_Other>&rThat):
TSimpleStructAllocator<T>(rThat)
{ // construct from a related allocator (do nothing)
}
template<class _Other>
dbg_struct_allocator<T>& operator=(const dbg_struct_allocator<_Other>&rThat)
{ // assign from a related allocator (do nothing)
*static_cast<TSimpleStructAllocator<T>*>(this) = rThat;
return (*this);
}
};
#else
template<class T>
class dbg_allocator: public std::allocator<T>
{
public:
dbg_allocator(const char* szSource = "CryDbgAlloc", int nSource = 0)
{ // construct default allocator (do nothing)
}
dbg_allocator(const dbg_allocator<T>& rThat):
std::allocator<T> (rThat)
{ // construct by copying (do nothing)
}
/*
template<class _Other>
dbg_allocator(const dbg_allocator<_Other>&rThat):
std::allocator<T>(rThat)
{ // construct from a related allocator (do nothing)
}
template<class _Other>
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat):
std::allocator<T>(rThat)
{ // assign from a related allocator (do nothing)
return (*this);
}
dbg_allocator(const std::allocator<T>& rThat):
std::allocator<T> (rThat)
{ // construct by copying (do nothing)
}
*/
template<class _Other>
dbg_allocator(const std::allocator<_Other>&rThat):
std::allocator<T>(rThat)
{ // construct from a related allocator (do nothing)
}
template<class _Other>
dbg_allocator<T>& operator=(const std::allocator<_Other>&rThat):
std::allocator<T>(rThat)
{ // assign from a related allocator (do nothing)
return (*this);
}
};
#endif
#if defined(_DEBUG) && defined(WIN32)
#if _MSC_VER >= 1300 && defined(_MAP_)
template <class Key, class Type, class Traits = std::less<Key> >
class map: public std::map <Key, Type, Traits, dbg_allocator<std::pair<Key, Type> > >
{
public:
typedef dbg_allocator<std::pair<Key, Type> > _Allocator;
typedef std::map <Key, Type, Traits, _Allocator > _Base;
map (const char* szParentObject = "STL map", int nParentIndex = 0):
_Base (_Base::key_compare(), _Base::allocator_type(szParentObject, nParentIndex))
{
}
};
#endif
#if (_MSC_VER >= 1300) && defined(_SET_)
template <class Key, class Traits = std::less<Key> >
class set: public std::set <Key, Traits, dbg_allocator<Key> >
{
public:
typedef dbg_allocator<Key> _Allocator;
typedef std::set <Key, Traits, _Allocator> _Base;
set (const char* szParentObject = "STL set", int nParentIndex = 0):
_Base (_Base::key_compare(), _Allocator(szParentObject, nParentIndex))
{
}
};
#endif
#if (_MSC_VER >= 1300) && defined(_VECTOR_)
template <class Type>
class vector: public std::vector <Type, dbg_allocator<Type> >
{
public:
typedef dbg_allocator<Type> _Allocator;
typedef std::vector <Type, _Allocator> _Base;
typedef vector<Type> _Myt;
vector (const char* szParentObject = "STL vector", int nParentIndex = 0):
_Base (_Allocator(szParentObject, nParentIndex))
{
}
vector (const _Myt& that): _Base (that)
{
}
};
#endif
#if (_MSC_VER >= 1300) && defined(_STRING_)
class string: public std::basic_string<char, std::char_traits<char>, dbg_allocator<char> >
{
public:
typedef dbg_allocator<char> _Allocator;
typedef std::basic_string<char, std::char_traits<char>, _Allocator> _Base;
explicit string (const _Allocator allocator = _Allocator("STL string", 0)):
_Base (allocator)
{
}
string (const char* szThat, const _Allocator allocator = _Allocator("STL string", 0)):
_Base (szThat, 0, _Base::npos, allocator)
{
}
string (const char* szBegin, const char* szEnd, const _Allocator allocator = _Allocator("STL string", 0)):
_Base (szBegin, szEnd, allocator)
{
}
string (const _Base& strRight, const _Allocator allocator = _Allocator("STL string", 0)):
_Base (strRight, 0, npos, allocator)
{
}
};
#endif
#else
//#if _MSC_VER >= 1300 && defined(_MAP_)
template <class Key, class Type, class Traits = std::less<Key> >
class map: public std::map <Key, Type, Traits >
{
public:
typedef std::map <Key, Type, Traits> _Base;
map ()
{
}
map (const char* szParentObject, int nParentIndex = 0)
{
}
};
//#endif
//#if (_MSC_VER >= 1300) && defined(_SET_)
template <class Key, class Traits = std::less<Key> >
class set: public std::set <Key, Traits>
{
public:
typedef std::set <Key, Traits> _Base;
set ()
{
}
set (const char* szParentObject , int nParentIndex = 0)
{
}
};
//#endif
//#if (_MSC_VER >= 1300) && defined(_VECTOR_)
template <class Type>
class vector: public std::vector <Type>
{
public:
typedef std::vector <Type> _Base;
vector ()
{
}
vector (const char* szParentObject, int nParentIndex = 0)
{
}
};
//#endif
//#if (_MSC_VER >= 1300) && defined(_STRING_)
class string: public string
{
public:
typedef dbg_allocator<char> _Allocator;
typedef string _Base;
string ()
{
}
explicit string (const _Allocator allocator)
{
}
string (const char* szThat):
_Base (szThat)
{
}
string (const char* szThat, const _Allocator allocator):
_Base (szThat)
{
}
string (const char* szBegin, const char* szEnd):
_Base (szBegin, szEnd)
{
}
string (const char* szBegin, const char* szEnd, const _Allocator allocator):
_Base (szBegin, szEnd)
{
}
string (const _Base& strRight):
_Base (strRight)
{
}
string (const _Base& strRight, const _Allocator allocator):
_Base (strRight)
{
}
};
//#endif
#endif
}
#endif