#ifndef GRIM_POOL_H #define GRIM_POOL_H #include "common/hashmap.h" #include "common/list.h" #include "common/foreach.h" #include "engines/grim/savegame.h" namespace Grim { template class Pool; class PoolObjectBase { public: virtual ~PoolObjectBase() { }; virtual int getId() const = 0; virtual int32 getTag() const = 0; }; template class PoolObject : public PoolObjectBase { public: class Pool { public: template class Iterator { public: Iterator(const Iterator &i) : _i(i._i) { } Iterator(const it &i) : _i(i) { } int32 getId() const { return _i->_key; } Type &getValue() const { return _i->_value; } Type &operator*() const { return _i->_value; } Iterator &operator=(const Iterator &i) { _i = i._i; return *this; } bool operator==(const Iterator i) const { return _i == i._i; } bool operator!=(const Iterator i) const { return _i != i._i; } Iterator &operator++() { ++_i; return *this; } Iterator operator++(int) { Iterator iter = *this; ++_i; return iter; } Iterator &operator--() { --_i; return *this; } Iterator operator--(int) { Iterator iter = *this; --_i; return iter; } private: it _i; }; typedef Iterator::iterator, T *> iterator; typedef Iterator::const_iterator, T *const> const_iterator; Pool(); ~Pool(); void addObject(T *obj); void removeObject(int32 id); T *getObject(int32 id); iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; int getSize() const; void deleteObjects(); void saveObjects(SaveGame *save); void restoreObjects(SaveGame *save); private: bool _restoring; Common::HashMap _map; }; /** * @short Smart pointer class * This class wraps a C pointer to T, subclass of PoolObject, which gets reset to NULL as soon as * the object is deleted, e.g by Pool::restoreObjects(). * Its operator overloads allows the Ptr class to be used as if it was a raw C pointer. */ class Ptr { public: Ptr() : _obj(NULL) { } Ptr(T *obj) : _obj(obj) { if (_obj) _obj->addPointer(this); } Ptr(const Ptr &ptr) : _obj(ptr._obj) { if (_obj) _obj->addPointer(this); } ~Ptr() { if (_obj) _obj->removePointer(this); } Ptr &operator=(T *obj); Ptr &operator=(const Ptr &ptr); inline operator bool() const { return _obj; } inline bool operator!() const { return !_obj; } inline bool operator==(T *obj) const { return _obj == obj; } inline bool operator!=(T *obj) const { return _obj != obj; } inline T *operator->() const { return _obj; } inline T &operator*() const { return *_obj; } inline operator T*() const { return _obj; } private: inline void reset() { _obj = NULL; } T *_obj; friend class PoolObject; }; virtual ~PoolObject(); int getId() const; int32 getTag() const; static int32 getTagStatic(); static Pool &getPool(); protected: PoolObject(); private: void setId(int id); void addPointer(Ptr *pointer) { _pointers.push_back(pointer); } void removePointer(Ptr *pointer) { _pointers.remove(pointer); } int _id; static int s_id; static Pool *s_pool; Common::List _pointers; friend class Pool; friend class Ptr; }; template bool operator==(T *obj, const typename PoolObject::Ptr &ptr) { return obj == ptr._obj; } template bool operator!=(T *obj, const typename PoolObject::Ptr &ptr) { return obj != ptr._obj; } template int PoolObject::s_id = 0; template typename PoolObject::Pool *PoolObject::s_pool = NULL; template PoolObject::PoolObject() { ++s_id; _id = s_id; if (!s_pool) { s_pool = new Pool(); } s_pool->addObject(static_cast(this)); } template PoolObject::~PoolObject() { s_pool->removeObject(_id); for (typename Common::List::iterator i = _pointers.begin(); i != _pointers.end(); ++i) { (*i)->reset(); } } template void PoolObject::setId(int id) { _id = id; if (id > s_id) { s_id = id; } } template int PoolObject::getId() const { return _id; } template typename PoolObject::Pool &PoolObject::getPool() { if (!s_pool) { s_pool = new Pool(); } return *s_pool; } template int32 PoolObject::getTag() const { return tag; } template int32 PoolObject::getTagStatic() { return tag; } /** * @class Pool */ template PoolObject::Pool::Pool() : _restoring(false) { } template PoolObject::Pool::~Pool() { PoolObject::s_pool = NULL; } template void PoolObject::Pool::addObject(T *obj) { if (!_restoring) { _map.setVal(obj->_id, obj); } } template void PoolObject::Pool::removeObject(int32 id) { _map.erase(id); } template T *PoolObject::Pool::getObject(int32 id) { return _map.getVal(id, NULL); } template typename PoolObject::Pool::iterator PoolObject::Pool::begin() { return iterator(_map.begin()); } template typename PoolObject::Pool::const_iterator PoolObject::Pool::begin() const { return const_iterator(_map.begin()); } template typename PoolObject::Pool::iterator PoolObject::Pool::end() { return iterator(_map.end()); } template typename PoolObject::Pool::const_iterator PoolObject::Pool::end() const { return const_iterator(_map.end()); } template int PoolObject::Pool::getSize() const { return _map.size(); } template void PoolObject::Pool::deleteObjects() { while (!_map.empty()) { delete *begin(); } delete this; } template void PoolObject::Pool::saveObjects(SaveGame *state) { state->beginSection(tag); state->writeLEUint32(_map.size()); for (iterator i = begin(); i != end(); ++i) { T *a = *i; state->writeLESint32(i.getId()); a->saveState(state); } state->endSection(); } template void PoolObject::Pool::restoreObjects(SaveGame *state) { state->beginSection(tag); int32 size = state->readLEUint32(); _restoring = true; Common::HashMap tempMap; for (int32 i = 0; i < size; ++i) { int32 id = state->readLESint32(); T *t = _map.getVal(id); _map.erase(id); if (!t) { t = new T(); t->setId(id); } tempMap[id] = t; t->restoreState(state); } for (iterator i = begin(); i != end(); i++) { delete *i; } _map = tempMap; _restoring = false; state->endSection(); } template typename PoolObject::Ptr &PoolObject::Ptr::operator=(T *obj) { if (_obj) { _obj->removePointer(this); } _obj = obj; if (obj) { obj->addPointer(this); } return *this; } template typename PoolObject::Ptr &PoolObject::Ptr::operator=(const Ptr &ptr) { if (_obj) { _obj->removePointer(this); } _obj = ptr._obj; if (_obj) { _obj->addPointer(this); } return *this; } } #endif