1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 /*
24  * This code is based on Broken Sword 2.5 engine
25  *
26  * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
27  *
28  * Licensed under GNU GPL v2
29  *
30  */
31 
32 #ifndef SWORD25_OBJECTREGISTRY_H
33 #define SWORD25_OBJECTREGISTRY_H
34 
35 #include "common/func.h"
36 #include "common/hashmap.h"
37 #include "common/textconsole.h"
38 #include "sword25/kernel/common.h"
39 
40 namespace Sword25 {
41 
42 template<typename T>
43 class ObjectRegistry {
44 public:
ObjectRegistry()45 	ObjectRegistry() : _nextHandle(1) {}
~ObjectRegistry()46 	virtual ~ObjectRegistry() {}
47 
registerObject(T * objectPtr)48 	uint registerObject(T *objectPtr) {
49 		// Null-Pointer k�nnen nicht registriert werden.
50 		if (objectPtr == 0) {
51 			error("Cannot register a null pointer.");
52 			return 0;
53 		}
54 
55 		// Falls das Objekt bereits registriert wurde, wird eine Warnung ausgeben und das Handle zur�ckgeben.
56 		uint handle = findHandleByPtr(objectPtr);
57 		if (handle != 0) {
58 			warning("Tried to register a object that was already registered.");
59 			return handle;
60 		}
61 		// Ansonsten wird das Objekt in beide Maps eingetragen und das neue Handle zur�ckgeben.
62 		else {
63 			_handle2PtrMap[_nextHandle] = objectPtr;
64 			_ptr2HandleMap[objectPtr] = _nextHandle;
65 
66 			return _nextHandle++;
67 		}
68 	}
69 
registerObject(T * objectPtr,uint handle)70 	uint registerObject(T *objectPtr, uint handle) {
71 		// Null-Pointer und Null-Handle k�nnen nicht registriert werden.
72 		if (objectPtr == 0 || handle == 0) {
73 			error("Cannot register a null pointer or a null handle.");
74 			return 0;
75 		}
76 
77 		// Falls das Objekt bereits registriert wurde, wird ein Fehler ausgegeben und 0 zur�ckgeben.
78 		uint handleTest = findHandleByPtr(objectPtr);
79 		if (handleTest != 0) {
80 			error("Tried to register a object that was already registered.");
81 			return 0;
82 		}
83 		// Falls das Handle bereits vergeben ist, wird ein Fehler ausgegeben und 0 zur�ckgegeben.
84 		else if (findPtrByHandle(handle) != 0) {
85 			error("Tried to register a handle that is already taken.");
86 			return 0;
87 		}
88 		// Ansonsten wird das Objekt in beide Maps eingetragen und das gew�nschte Handle zur�ckgeben.
89 		else {
90 			_handle2PtrMap[handle] = objectPtr;
91 			_ptr2HandleMap[objectPtr] = handle;
92 
93 			// Falls das vergebene Handle gr��er oder gleich dem n�chsten automatische vergebenen Handle ist, wird das n�chste automatisch
94 			// vergebene Handle erh�ht.
95 			if (handle >= _nextHandle)
96 				_nextHandle = handle + 1;
97 
98 			return handle;
99 		}
100 	}
101 
deregisterObject(T * objectPtr)102 	void deregisterObject(T *objectPtr) {
103 		uint handle = findHandleByPtr(objectPtr);
104 
105 		if (handle != 0) {
106 			// Registriertes Objekt aus beiden Maps entfernen.
107 			_handle2PtrMap.erase(findHandleByPtr(objectPtr));
108 			_ptr2HandleMap.erase(objectPtr);
109 		} else {
110 			warning("Tried to remove a object that was not registered.");
111 		}
112 	}
113 
resolveHandle(uint handle)114 	T *resolveHandle(uint handle) {
115 		// Zum Handle geh�riges Objekt in der Hash-Map finden.
116 		T *objectPtr = findPtrByHandle(handle);
117 
118 		// Pointer zur�ckgeben. Im Fehlerfall ist dieser 0.
119 		return objectPtr;
120 	}
121 
resolvePtr(T * objectPtr)122 	uint resolvePtr(T *objectPtr) {
123 		// Zum Pointer geh�riges Handle in der Hash-Map finden.
124 		uint handle = findHandleByPtr(objectPtr);
125 
126 		// Handle zur�ckgeben. Im Fehlerfall ist dieses 0.
127 		return handle;
128 	}
129 
130 protected:
131 	struct ClassPointer_EqualTo {
operatorClassPointer_EqualTo132 		bool operator()(const T *x, const T *y) const {
133 			return x == y;
134 		}
135 	};
136 	struct ClassPointer_Hash {
operatorClassPointer_Hash137 		uint operator()(const T *x) const {
138 			return (uint)(x - (const T *)0);
139 		}
140 	};
141 
142 	typedef Common::HashMap<uint32, T *>  HANDLE2PTR_MAP;
143 	typedef Common::HashMap<T *, uint32, ClassPointer_Hash, ClassPointer_EqualTo> PTR2HANDLE_MAP;
144 
145 	HANDLE2PTR_MAP  _handle2PtrMap;
146 	PTR2HANDLE_MAP  _ptr2HandleMap;
147 	uint32    _nextHandle;
148 
findPtrByHandle(uint handle)149 	T *findPtrByHandle(uint handle) {
150 		// Zum Handle geh�rigen Pointer finden.
151 		typename HANDLE2PTR_MAP::const_iterator it = _handle2PtrMap.find(handle);
152 
153 		// Pointer zur�ckgeben, oder, falls keiner gefunden wurde, 0 zur�ckgeben.
154 		return (it != _handle2PtrMap.end()) ? it->_value : 0;
155 	}
156 
findHandleByPtr(T * objectPtr)157 	uint findHandleByPtr(T *objectPtr) {
158 		// Zum Pointer geh�riges Handle finden.
159 		typename PTR2HANDLE_MAP::const_iterator it = _ptr2HandleMap.find(objectPtr);
160 
161 		// Handle zur�ckgeben, oder, falls keines gefunden wurde, 0 zur�ckgeben.
162 		return (it != _ptr2HandleMap.end()) ? it->_value : 0;
163 	}
164 };
165 
166 } // End of namespace Sword25
167 
168 #endif
169