mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
364 lines
7.7 KiB
C++
364 lines
7.7 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#ifndef GRIM_POOL_H
|
|
#define GRIM_POOL_H
|
|
|
|
#include "common/hashmap.h"
|
|
#include "common/list.h"
|
|
|
|
#include "engines/grim/savegame.h"
|
|
|
|
namespace Grim {
|
|
|
|
template<class T> class Pool;
|
|
|
|
class PoolObjectBase {
|
|
public:
|
|
virtual ~PoolObjectBase() { };
|
|
virtual int getId() const = 0;
|
|
virtual int32 getTag() const = 0;
|
|
};
|
|
|
|
template<class T>
|
|
class PoolObject : public PoolObjectBase {
|
|
public:
|
|
class Pool {
|
|
public:
|
|
template<class it, class Type>
|
|
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<typename Common::HashMap<int32, T *>::iterator, T *> iterator;
|
|
typedef Iterator<typename Common::HashMap<int32, T *>::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<int32, T*> _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();
|
|
|
|
void setId(int id);
|
|
|
|
int getId() const override;
|
|
int32 getTag() const override { return T::getStaticTag(); }
|
|
|
|
static Pool &getPool();
|
|
|
|
protected:
|
|
PoolObject();
|
|
|
|
static void saveStaticState(SaveGame *state) {}
|
|
static void restoreStaticState(SaveGame *state) {}
|
|
|
|
private:
|
|
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<Ptr *> _pointers;
|
|
|
|
friend class Pool;
|
|
friend class Ptr;
|
|
};
|
|
|
|
template <class T>
|
|
bool operator==(T *obj, const typename PoolObject<T>::Ptr &ptr) {
|
|
return obj == ptr._obj;
|
|
}
|
|
|
|
template <class T>
|
|
bool operator!=(T *obj, const typename PoolObject<T>::Ptr &ptr) {
|
|
return obj != ptr._obj;
|
|
}
|
|
|
|
template <class T>
|
|
int PoolObject<T>::s_id = 0;
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool *PoolObject<T>::s_pool = NULL;
|
|
|
|
template <class T>
|
|
PoolObject<T>::PoolObject() {
|
|
++s_id;
|
|
_id = s_id;
|
|
|
|
if (!s_pool) {
|
|
s_pool = new Pool();
|
|
}
|
|
s_pool->addObject(static_cast<T *>(this));
|
|
}
|
|
|
|
template <class T>
|
|
PoolObject<T>::~PoolObject() {
|
|
s_pool->removeObject(_id);
|
|
|
|
for (typename Common::List<Ptr *>::iterator i = _pointers.begin(); i != _pointers.end(); ++i) {
|
|
(*i)->reset();
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::setId(int id) {
|
|
_id = id;
|
|
if (id > s_id) {
|
|
s_id = id;
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
int PoolObject<T>::getId() const {
|
|
return _id;
|
|
}
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool &PoolObject<T>::getPool() {
|
|
if (!s_pool) {
|
|
s_pool = new Pool();
|
|
}
|
|
return *s_pool;
|
|
}
|
|
|
|
/**
|
|
* @class Pool
|
|
*/
|
|
|
|
template <class T>
|
|
PoolObject<T>::Pool::Pool() :
|
|
_restoring(false) {
|
|
}
|
|
|
|
template <class T>
|
|
PoolObject<T>::Pool::~Pool() {
|
|
PoolObject<T>::s_pool = NULL;
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::Pool::addObject(T *obj) {
|
|
if (!_restoring) {
|
|
_map.setVal(obj->_id, obj);
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::Pool::removeObject(int32 id) {
|
|
_map.erase(id);
|
|
}
|
|
|
|
template <class T>
|
|
T *PoolObject<T>::Pool::getObject(int32 id) {
|
|
return _map.getValOrDefault(id, NULL);
|
|
}
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool::iterator PoolObject<T>::Pool::begin() {
|
|
return iterator(_map.begin());
|
|
}
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool::const_iterator PoolObject<T>::Pool::begin() const {
|
|
return const_iterator(_map.begin());
|
|
}
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool::iterator PoolObject<T>::Pool::end() {
|
|
return iterator(_map.end());
|
|
}
|
|
|
|
template <class T>
|
|
typename PoolObject<T>::Pool::const_iterator PoolObject<T>::Pool::end() const {
|
|
return const_iterator(_map.end());
|
|
}
|
|
|
|
template <class T>
|
|
int PoolObject<T>::Pool::getSize() const {
|
|
return _map.size();
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::Pool::deleteObjects() {
|
|
while (!_map.empty()) {
|
|
delete *begin();
|
|
}
|
|
delete this;
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::Pool::saveObjects(SaveGame *state) {
|
|
state->beginSection(T::getStaticTag());
|
|
|
|
T::saveStaticState(state);
|
|
|
|
state->writeLEUint32(_map.size());
|
|
for (iterator i = begin(); i != end(); ++i) {
|
|
T *a = *i;
|
|
state->writeLESint32(i.getId());
|
|
|
|
a->saveState(state);
|
|
}
|
|
|
|
state->endSection();
|
|
}
|
|
|
|
template <class T>
|
|
void PoolObject<T>::Pool::restoreObjects(SaveGame *state) {
|
|
state->beginSection(T::getStaticTag());
|
|
|
|
T::restoreStaticState(state);
|
|
|
|
int32 size = state->readLEUint32();
|
|
_restoring = true;
|
|
Common::HashMap<int32, T *> tempMap;
|
|
for (int32 i = 0; i < size; ++i) {
|
|
int32 id = state->readLESint32();
|
|
T *t = nullptr;
|
|
if (_map.tryGetVal(id, t))
|
|
_map.erase(id);
|
|
else {
|
|
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<class T>
|
|
typename PoolObject<T>::Ptr &PoolObject<T>::Ptr::operator=(T *obj) {
|
|
if (_obj) {
|
|
_obj->removePointer(this);
|
|
}
|
|
_obj = obj;
|
|
if (obj) {
|
|
obj->addPointer(this);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<class T>
|
|
typename PoolObject<T>::Ptr &PoolObject<T>::Ptr::operator=(const Ptr &ptr) {
|
|
if (_obj) {
|
|
_obj->removePointer(this);
|
|
}
|
|
_obj = ptr._obj;
|
|
if (_obj) {
|
|
_obj->addPointer(this);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|