Home

hersto:  typed_mem.h

Source of typed_mem.h:

Here is a link for right-clicking and downloading the file: typed_mem.h (7.11 K Byte),

and below is its content to view online.


// 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.
}









__.-.__
end of document