// BRVMHeap.h 
// Copyright © 1985-1992 by Apple Computer, Inc.  All rights fReserved.

#ifndef BRVMHEAP_H
#define BRVMHEAP_H

#ifdef BR_BUILD_MAC
#ifndef __STDDEF__
#include <StdDef.h>
#endif

#ifndef __TYPES__
#include <Types.h>
#endif
#endif //BR_BUILD_MAC

#ifdef BR_BUILD_WIN
#ifndef __STDDEF_H
#include <StdDef.h>
#endif

#ifndef __TYPES_H
//#include <Types.h>
#endif
#endif //BR_BUILD_WIN

#ifndef BRSUPDEF_H
#include "BRSupDef.h"
#endif

// ToDo's
// 1) Add method IsValid.

//----------------------------------------------------------------------------------------
// Forward class declarations
//----------------------------------------------------------------------------------------

class BR_CMemoryHookList;

#ifdef BR_BUILD_MAC
typedef size_t BR_MemoryBlockSize;		//???RSS
#endif
#ifdef BR_BUILD_WIN
typedef long int BR_MemoryBlockSize;	//???RSS
#endif
typedef long BR_PointerDifference;		//???RSS

//========================================================================================
// BR_CMemoryHook
//
//		A fMemory hook that can be used to track heap operations by subclassing BR_CMemoryHook
//		and overriding the methods of interest. Your subclass is then registered with a
//		MemoryHeap.
//
//========================================================================================

class BR_CMemoryHook
{
public:
	// These methods should all be abstract, but BR_CMemoryHookList instantiates a
	// BR_CMemoryHook to use as the head of its linked list, so here we just use empty
	// inlines. A BR_CMemoryHook still cannot be instantiated because the constructor
	// is protected.

	virtual BR_MemoryBlockSize AboutToAllocate(BR_MemoryBlockSize size);
	virtual void* DidAllocate(void* blk,
							  BR_MemoryBlockSize);
	virtual void* AboutToBlockSize(void* blk);
	virtual void* AboutToFree(void* blk);
	virtual void AboutToRealloc(void*& ,
								BR_MemoryBlockSize&);
	virtual void* DidRealloc(void* blk,
							 BR_MemoryBlockSize);
	virtual void AboutToReset();
	virtual void Comment(const char*);

	virtual~ BR_CMemoryHook();

protected:
	BR_CMemoryHook();

private:
	BR_CMemoryHook* fNextHook, * fPreviousHook;

	friend BR_CMemoryHookList;
};




//========================================================================================
// BR_CMemoryHookList
//
//		A list of fMemory hooks. This is a special linked list that assumes the links for
//		the list are fields of BR_CMemoryHook. This avoids endless recursion were we to
//		allocate nodes for the BR_CMemoryHooks here.
//
//========================================================================================

class BR_CMemoryHookList
{
public:
	BR_CMemoryHookList();

	void Add(BR_CMemoryHook* aMemoryHook);
	void Remove(BR_CMemoryHook* aMemoryHook);
	BR_CMemoryHook* First();
	BR_CMemoryHook* Next();
	BR_CMemoryHook* Previous();
	BR_CMemoryHook* Last();

	~BR_CMemoryHookList();

private:
	BR_CMemoryHook fHead;
	BR_CMemoryHook* fCurrentHook;
};


//========================================================================================
// BR_CMemoryHeap
//
//		Abstract base class for fMemory heaps.
//
//========================================================================================

class BR_CMemoryHeap
{
public:
	static const char* kDefaultDescription;

	static BR_CMemoryHeap* fHeapList;
	static BR_CMemoryHeap* GetFirstHeap();

	void* Allocate(BR_MemoryBlockSize size);
	BR_MemoryBlockSize BlockSize(const void* block) const;
	virtual BR_MemoryBlockSize BytesAllocated() const;
	virtual BR_MemoryBlockSize BytesFree() const = 0;
	virtual void Check() const = 0;
	void Free(void*);
	virtual BR_Boolean GetAutoValidation() const;
	virtual char* GetDescription() const;
	virtual BR_CMemoryHeap* GetNextHeap() const;
	virtual BR_Boolean GetZapOnAllocate() const;
	virtual BR_Boolean GetZapOnFree() const;
	virtual BR_MemoryBlockSize HeapSize() const = 0;
	virtual void InstallHook(BR_CMemoryHook* BR_CMemoryHook);
	BR_Boolean IsValidBlock(void* blk) const;
	virtual BR_Boolean IsMyBlock(void* blk) const = 0;
	virtual BR_MemoryBlockSize NumberAllocatedBlocks() const;
	virtual void Print(char* msg = "") const = 0;
	void Reset();
	void* Reallocate(void* block,
					 BR_MemoryBlockSize newSize);
	virtual void RemoveHook(BR_CMemoryHook* BR_CMemoryHook);
	virtual void SetAutoValidation(BR_Boolean = FALSE);
	virtual void SetDescription(const char* description = kDefaultDescription);
	virtual void SetZapOnAllocate(BR_Boolean = FALSE);
	virtual void SetZapOnFree(BR_Boolean = FALSE);

	void* operator new(size_t size);
	void operator delete(void* ptr);

	virtual~ BR_CMemoryHeap();

protected:
	BR_CMemoryHeap(BR_Boolean autoValidation = FALSE,
				   BR_Boolean zapOnAllocate = TRUE,
				   BR_Boolean zapOnFree = FALSE);

	virtual void* AllocateRawMemory(BR_MemoryBlockSize size);
	virtual void* DoAllocate(BR_MemoryBlockSize size,
							 BR_MemoryBlockSize& allocatedSize) = 0;
	virtual BR_MemoryBlockSize DoBlockSize(const void* block) const = 0;
	virtual void DoFree(void*) = 0;
	virtual BR_Boolean DoIsValidBlock(void* blk) const = 0;
	virtual void DoReset() = 0;
	virtual void* DoReallocate(void* block,
							   BR_MemoryBlockSize newSize,
							   BR_MemoryBlockSize& allocatedSize);
	virtual void FreeRawMemory(void* ptr);

private:
	enum
	{
		kDescriptionLength = 32
	};


	char fDescription[kDescriptionLength];
	BR_CMemoryHeap* fNextHeap;
	BR_Boolean fZapOnAllocate;
	BR_Boolean fZapOnFree;
	BR_Boolean fAutoValidation;
	BR_MemoryBlockSize fBytesAllocated;
	BR_MemoryBlockSize fNumberAllocatedBlocks;
	BR_CMemoryHookList fMemoryHookList;

	BR_MemoryBlockSize CallAboutToAllocateHooks(BR_MemoryBlockSize size);
	void* CallDidAllocateHooks(void* blk,
							   BR_MemoryBlockSize size);
	void* CallAboutToBlockSizeHooks(void* blk);
	void* CallAboutToFreeHooks(void* blk);
	void CallAboutToReallocHooks(void*& blk,
								 BR_MemoryBlockSize& size);
	void* CallDidReallocHooks(void* blk,
							  BR_MemoryBlockSize size);
	void CallAboutToResetHooks();
	void CallCommentHooks(const char* comment);
	void ValidateAndReport(void* blk) const;
};


#endif
