////////////////////////////////////////////////////////////////////////////////
// Object.h -- this file is part of the Emulator Developers Kit
// available at http://ourworld.compuserve.com/homepages/pc64/develop.htm

class Object {

  flag fAutoDelete;
  const char* pcName;
  Object* pParent;
  Object* pFirstChild;
  Object* pSibling;

  void ForAllChildrenCall(void (*pFunction)(Object*));
  friend global void ForAllObjectsCall(void (*pFunction)(Object*));
  void DeleteAllChildrenOfType(const type_info& Class);
  friend global void DeleteAllObjectsOfType(const type_info& Class);

protected:

  // initialisation
  global virtual void DoInit() {}

  // persistence
  global virtual void Read(File& In);
  global virtual void Write(File& Out);

  // forward declaration for SetClock()
  typedef class Clock Clock;

public:

  // constructor
  global Object() {
    fAutoDelete = false;
    pcName = NULL;
    pParent = NULL;
    pFirstChild = NULL;
    pSibling = NULL;
  }

  // destructor
  global virtual ~Object();

  // allocate object on a 32 byte boundary for cache optimization
  inline void* Object::operator new(size_t Size) { return MemAlloc(Size); }
  inline void Object::operator delete(void* pMem) { MemFree(pMem); }

  // initialisation
  global void Init(const char* pcNewName, Object* pNewParent);
  global virtual void SetClock(Clock& NewClock);
  inline void SetAutoDelete()                                                                       { fAutoDelete = true; }

  // object properties
  inline const char* GetName()                                                                      { return pcName; }
  global char* GetFullName(char* pcBuffer, const char* pcEnd);
  inline const Object* GetParent()                                                                  { return pParent; }

  // find a child, return NULL or throw exception
  global const Object* FindChild(const char* pcName);
  global const Object* GetChild(const char* pcName);
};


////////////////////////////////////////////////////////////////////////////////
// function pointers with different arguments

typedef void (Object::*pfn)();
typedef byte (Object::*bpfn)();
typedef void (Object::*pfnb)(byte);
typedef void (Object::*pfnbb)(byte, byte);
typedef void (Object::*pfni)(int);


////////////////////////////////////////////////////////////////////////////////
// a simple cast would not compile with MSVC42

inline pfn make_pfn(void* p) {
  union u {
    void* p;
    pfn pfn;
  } u;
  u.p = p;
  return u.pfn;
}


////////////////////////////////////////////////////////////////////////////////
// old style function pointers
// TODO: delete

typedef void (*pfnv)();

inline bpfn make_bpfn(pfnv pfnOnRead) {
  union u {
    pfnv pfnOnRead;
    bpfn bpfnOnRead;
  } u;
  u.pfnOnRead = pfnOnRead;
  return u.bpfnOnRead;
}

inline pfnb make_pfnb(pfnv pfnOnWrite) {
  union u {
    pfnv pfnOnWrite;
    pfnb pfnbOnWrite;
  } u;
  u.pfnOnWrite = pfnOnWrite;
  return u.pfnbOnWrite;
}


////////////////////////////////////////////////////////////////////////////////
// find an object, return NULL or throw exception

global const Object* FindObject(const char* pcName);
global const Object* GetObject(const char* pcName);


////////////////////////////////////////////////////////////////////////////////
// connect extension classes to existing objects

global void ForAllObjectsCall(void (*pFunction)(Object*));
global void DeleteAllObjectsOfType(const type_info& Class);
global void AddAfterInitHook(void (*pFunction)(Object*));
global void RemoveAfterInitHook(void (*pFunction)(Object*));


////////////////////////////////////////////////////////////////////////////////
// persistence
                                                                                                    global void _RegisterPersistentClass(const type_info& Class, Object* (*pfnCreate)()); global void _UnregisterPersistentClass(const type_info& Class);
#define RegisterPersistentClass(ClassName)                                                          static Object* new_##ClassName() { return (Object*)new ClassName; } static struct RegisterPersistentClass##ClassName { RegisterPersistentClass##ClassName() { _RegisterPersistentClass(typeid(ClassName), new_##ClassName); } ~RegisterPersistentClass##ClassName() { _UnregisterPersistentClass(typeid(ClassName)); } } RegisterPersistentClass##ClassName;
global void SaveObjects(File& Out);
global void LoadObjects(File& In);
