// typed_mem.h
//
// (C) 2002 - 2007 by hersto, Herbert Stocker
//
// You can redistribute, modify or use this file in your own
// projects as long as you keep this comment block intact. This
// requirement does not apply if you make very major changes
// to the file.
// The above statements apply to this file only, not to the whole
// program, should you have found this file as a part of such.
//
// This file 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.
//
// The original can be found at http://www.hersto.net/SwEngineering/
//
//
// This file (original name typed_mem.h) provides some template
// functions that wrap around malloc(.) and friends in a type save
// way using C++ templates.
//
// Thus the programmer gets type safety and better readable code because
// only essential information is in the code and type casting
// noise is off.
//
#if 0
write pFoo= Malloc<foo>();
instead of pFoo= (foo*)malloc(sizeof(foo));
write pFoo= Malloc<foo>(5);
instead of pFoo= (foo*)malloc(sizeof(foo) * 5);
write pFoo= Realloc(pFoo, 5);
instead of pFoo= (foo*)realloc(pFoo, 5 * sizeof(foo));
write Free(pFoo);
instead of free((void*)pFoo);
write ZeroMem(pFoo);
instead of memset(pFoo, 0, sizeof(*pFoo));
write ZeroMem(pFoo, 5);
instead of memset(pFoo, 0, 5 * sizeof(foo));
write MemCpy(pDest, pSrc);
instead of memcpy(pDest, pSrc, sizeof(*pDest));
write MemCpy(pDest, pSrc, 5);
instead of memcpy(pDest, pSrc, 5 * sizeof(*pDest));
write MemMove(pDest, pSrc);
instead of memmove(pDest, pSrc, sizeof(*pDest));
write MemMove(pDest, pSrc, 5);
instead of memmove(pDest, pSrc, 5 * sizeof(*pDest));
write MemCmp(&A, &B);
instead of memcmp(&A, &B, sizeof(A)); // hope that A will allways be the same size of B.
write MemCmp(pA, pB, 5);
instead of memcmp(pA, pB, 5 * sizeof(*pA));
after e.g. DWORD X= 0x12345678;
write FWrite(F, &X);
instead of fwrite(&X, sizeof(X), 1, F);
after e.g. typedef struct { short Left; short Right; } tSample; // holds a 44.1 kHz/16 bit/stereo sample of audio data.
tSample* aBuffer= ...;
int NumSamples= 1234;
write FWrite(F, aBuffer, NumSamples);
instead of fwrite(aBuffer, sizeof(*aBuffer), NumSamples, F);
dito for FRead(.) and fread(.) .
And last but not least:
write foo pSomething[5];
for(size_t C= 0; C<SizeOf(pSomething); C++ )
instead of foo pSomething[5];
for(size_t C= 0; C<5; C++ )
which is unsafe, because when you change the array
definition you may forget to change it in all dependent
statements.
And if you want to check the validity of a pointer in Win32,
write AssertMemObj(pFoo);
or AssertMemObj(pFoo, 5);
instead ASSERT(!IsBadReadPtr ((void*)pObject, Count * sizeof(*pObject)));
or ASSERT(!IsBadWritePtr((void*)pObject, Count * sizeof(*pObject)));
and you'll get a distinction between read access and write access for free.
#endif
//
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include "string.h" // for memcpy, etc.
#define SizeOf(ary) (sizeof(ary) / sizeof(*ary))
// This is much more general than the other functions.
// Therefore if you don't want to include this file (don't want to have pointer
// stuff available in your C++ file),
// then you can comment this out here and insert it in some StdAfx.h or other
// general include file.
template<class Type>
void ZeroMem(Type* pData, size_t Count= 1)
{
memset(pData, 0, sizeof(*pData) * Count);
}
template<class Type>
Type* MemCpy(Type* pDest, const Type* pSrc, size_t Count= 1)
{
return (Type*)memcpy(pDest, pSrc, Count*sizeof(*pDest));
}
template<class Type>
Type* MemMove(Type* pDest, const Type* pSrc, size_t Count= 1)
{
return (Type*)memmove(pDest, pSrc, Count*sizeof(*pDest));
}
template<class Type>
size_t MemCmp(Type* pA, const Type* pB, size_t Count= 1)
{
return memcmp(pA, pB, sizeof(*pA) * Count);
}
template<class Type>
Type* Malloc(size_t Count= 1)
{
return (Type*)malloc(Count * sizeof(Type));
}
template<class Type>
void Free(Type* pData)
{
free((void*)pData);
}
template<class Type>
Type* Realloc(Type* pData, size_t NewCount)
{
return (Type*)realloc(pData, NewCount * sizeof(*pData));
}
#ifdef WIN32
template<class Type>
void AssertMemObj(Type* pObject, size_t Count= 1)
{
// first asserts a read pointer, and then a write pointer. This way
// when the assertion fires, one can see if it's because the memory
// is read-only or not accessible at all.
ASSERT(!IsBadReadPtr( (void*)pObject, Count * sizeof(*pObject)));
ASSERT(!IsBadWritePtr((void*)pObject, Count * sizeof(*pObject)));
}
#endif
template<class Type>
size_t FWrite(FILE* F, const Type* pData, size_t Count= 1)
{
return fwrite(pData, sizeof(*pData), Count, F);
}
template<class Type>
size_t FRead(FILE* F, Type* pData, size_t Count= 1)
{
return fread(pData, sizeof(*pData), Count, F);
}
// MemCpy for Ringbuffers:
template<class Type>
void MemCpyToRingBuffer( Type* aDestBuffer, size_t DestBufferSize, size_t DestStartIdx
, const Type* aSource
, size_t Length
)
{
DestStartIdx= DestStartIdx % DestBufferSize;
if( DestStartIdx < 0) // The % operator is mathematically correct,
// but less usefull for programmers.
DestStartIdx+= DestBufferSize;
if(Length > DestBufferSize)
{
// In a ring buffer only the youngest data survives.
aSource+= Length;
aSource-= DestBufferSize;
Length= DestBufferSize;
}
Type* aDest1= aDestBuffer+ DestStartIdx;
ptrdiff_t Length1= min(Length, DestBufferSize - DestStartIdx); // TBD: can Length1 become negative?
Type* aDest2= aDestBuffer;
ptrdiff_t Length2= Length - Length1; // TBD: can Length2 become negative?
/* align */ MemCpy(aDest1, aSource, Length1);
if(Length2) MemCpy(aDest2, aSource + Length1, Length2);
}
template<class Type>
void MemCpyFromRingBuffer( Type* aDest
, const Type* aSrcBuffer, size_t SrcBufferSize, size_t SrcStartIdx
, size_t Length
)
{
SrcStartIdx= SrcStartIdx % SrcBufferSize;
if( SrcStartIdx < 0) // The % operator is mathematically correct, but
// less usefull for programmers.
SrcStartIdx+= SrcBufferSize;
ptrdiff_t Length1= Length < SrcBuffer - SrcStartIdx? Length : SrcBuffer - SrcStartIdx;
ptrdiff_t Length2= Length - Length1;
/* align */ MemCpy(aDest, aSrcBuffer+ SrcStartIdx, Length1);
if(Length2) MemCpy(aDest+ Length1, aSrcBuffer, Length2);
}
template<class Type>
void MemCpyFromToRingBuffer( Type* aDestBuffer, int DestBufferSize, int DestStartIdx
, const Type* aSrcBuffer, int SrcBufferSize, int SrcStartIdx
, int Length
)
{
// TBD: Implement.
}
|