//************************************************************************************** // Filename: AStdMalloc.h // Part of Contextual Menu Workshop by Abracode Inc. // http://free.abracode.com/cmworkshop/ // Copyright © 2003 Abracode, Inc. All rights reserved. // // Description: Extension to David Catmull's ACCELA Mac toolbox C++ wrapper library //************************************************************************************** #pragma once #include "AMemoryCommon.h" #include "CThrownResult.h" #include #include template class AStdMalloc { public: AStdMalloc() : mObject(NULL), mIsOwner( kMemObj_NotOwned) {} //memory allocation constructor //CAUTION: the size is interpreted as a count of T objects AStdMalloc(SInt32 inSize, EMemObjClearOption inClearOption = kMemObj_DontClearMemory) : mObject(NULL), mIsOwner(kMemObj_NotOwned) { AllocateAndCopy(NULL, inSize, inClearOption); } //plain assignment with optional ownership taking, no copy. //inMallocPtr must be allocated with malloc or calloc AStdMalloc( void * inMallocPtr, EMemObjOwnershipType inIsOwner = kMemObj_Owned) : mObject(static_cast(inMallocPtr)), mIsOwner(inIsOwner) {} //pointer and size constructor //the input pointer may not be allocated by malloc, so we allocate private copy //CAUTION: the size is interpreted as a count of T objects AStdMalloc( const T *inPtr, SInt32 inSize) : mObject(NULL), mIsOwner(kMemObj_NotOwned) { AllocateAndCopy(inPtr,inSize); } //copy constructor - only shallow is allowed here //becaue we do not keep the size of the block so we cannot copy it //the object is detached from the original AStdMalloc(const AStdMalloc& inOrig) : mObject(NULL), mIsOwner(kMemObj_NotOwned) { EMemObjOwnershipType isOwner = inOrig.mIsOwner; Reset(inOrig.Detach(), isOwner ); } virtual ~AStdMalloc() { Dispose(); } //object assignment as a shallow copy with ownership change AStdMalloc& operator=( const AStdMalloc& inMallocPtr) { EMemObjOwnershipType isOwner = inMallocPtr.mIsOwner; Reset(inMallocPtr.Detach(), isOwner ); return *this; } //plain pointer assignment with ownership taking, no copy //inMallocPtr must be allocated with malloc or calloc AStdMalloc& operator=( const void * inMallocPtr) { Reset(static_cast(const_cast(inMallocPtr)), kMemObj_Owned); return *this; } operator T*() const { return mObject; } T& operator * () const { return *mObject; } T* operator -> () const { return mObject; } T& operator [] (UInt32 index) const { return mObject[index]; } //CAUTION: potentially costly //CAUTION: you cannot reallocate not owned pointer so resize will fail //CAUTION: the size is interpreted as a count of T objects void Resize(SInt32 inNewSize) { if(mObject != NULL) { if(mIsOwner == kMemObj_Owned) {//reallocate ONLY if we own the pointer T *newPtr = static_cast(std::realloc(mObject, inNewSize*sizeof(T))); if(newPtr == NULL) CThrownOSErr throwErr = memFullErr; mObject = newPtr; } else CThrownOSErr throwErr = -1; } else AllocateAndCopy(NULL, inNewSize); } static void CopyData(const T *inSource, T *inDest, SInt32 inSize) { std::memmove(inDest, inSource, inSize *sizeof(T)); } static void ClearData(void *inPtr, SInt32 inSize) { std::memset(inPtr, 0, inSize*sizeof(T) ); } T * Get() const { return mObject; } T * Detach() const { mIsOwner = kMemObj_NotOwned; return mObject; } void Reset( T *inObject, EMemObjOwnershipType inIsOwner = kMemObj_Owned) { if ((mIsOwner == kMemObj_Owned) && (mObject != NULL) && (inObject != mObject)) DisposeSelf(); mObject = inObject; mIsOwner = inIsOwner; } void Dispose() { if (mObject != NULL) { if(mIsOwner == kMemObj_Owned) DisposeSelf(); mObject = NULL; } mIsOwner = kMemObj_NotOwned; } static void DisposeProc(void *inObj) { if(inObj != NULL) { void **objPtr = reinterpret_cast(inObj); if(*objPtr != NULL) std::free(*objPtr); *objPtr = NULL; } } protected: void AllocateAndCopy( const T *inSrcPtr, SInt32 inSize, EMemObjClearOption inClearOption = kMemObj_DontClearMemory) { if(inSize != 0) { if( (inClearOption == kMemObj_ClearMemory) && (inSrcPtr == NULL) ) mObject = static_cast(std::calloc(inSize, sizeof(T))); else mObject = static_cast(std::malloc(inSize*sizeof(T))); if(mObject == NULL) CThrownOSErr throwErr = memFullErr; mIsOwner = kMemObj_Owned; if( (inSrcPtr != NULL) && (mObject != NULL) ) CopyData(inSrcPtr, mObject, inSize); } } void DisposeSelf() { std::free(mObject); } protected: T *mObject; mutable EMemObjOwnershipType mIsOwner; }; typedef AStdMalloc AMalloc;