]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - include/modulesystem.h
CMake: switch minizip casing
[xonotic/netradiant.git] / include / modulesystem.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant 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 GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_MODULESYSTEM_H )
23 #define INCLUDED_MODULESYSTEM_H
24
25 #include "generic/static.h"
26 #include "debugging/debugging.h"
27
28 #if defined( WIN32 )
29 #define RADIANT_DLLEXPORT __declspec(dllexport)
30 #define RADIANT_DLLIMPORT __declspec(dllimport)
31 #else
32 #define RADIANT_DLLEXPORT __attribute__((visibility("default")))
33 #define RADIANT_DLLIMPORT
34 #endif
35
36
37 class Module
38 {
39 public:
40 virtual void capture() = 0;
41 virtual void release() = 0;
42 virtual void* getTable() = 0;
43 };
44
45 inline void* Module_getTable( Module& module ){
46         return module.getTable();
47 }
48
49 class TextOutputStream;
50 class DebugMessageHandler;
51
52 class ModuleServer
53 {
54 public:
55 class Visitor
56 {
57 public:
58 virtual void visit( const char* name, Module& module ) const = 0;
59 };
60
61 virtual void setError( bool error ) = 0;
62 virtual bool getError() const = 0;
63
64 virtual TextOutputStream& getOutputStream() = 0;
65 virtual TextOutputStream& getErrorStream() = 0;
66 virtual DebugMessageHandler& getDebugMessageHandler() = 0;
67
68 virtual void registerModule( const char* type, int version, const char* name, Module& module ) = 0;
69 virtual Module* findModule( const char* type, int version, const char* name ) const = 0;
70 virtual void foreachModule( const char* type, int version, const Visitor& visitor ) = 0;
71 };
72
73 class ModuleServerHolder
74 {
75 ModuleServer* m_server;
76 public:
77 ModuleServerHolder()
78         : m_server( 0 ){
79 }
80 void set( ModuleServer& server ){
81         m_server = &server;
82 }
83 ModuleServer& get(){
84         return *m_server;
85 }
86 };
87
88 typedef Static<ModuleServerHolder> GlobalModuleServer;
89
90 inline ModuleServer& globalModuleServer(){
91         return GlobalModuleServer::instance().get();
92 }
93
94
95 inline void initialiseModule( ModuleServer& server ){
96         GlobalErrorStream::instance().setOutputStream( server.getErrorStream() );
97         GlobalOutputStream::instance().setOutputStream( server.getOutputStream() );
98         GlobalDebugMessageHandler::instance().setHandler( server.getDebugMessageHandler() );
99         GlobalModuleServer::instance().set( server );
100 }
101
102
103
104 template<typename Type>
105 class Modules
106 {
107 public:
108 class Visitor
109 {
110 public:
111 virtual void visit( const char* name, const Type& table ) const = 0;
112 };
113
114 virtual Type* findModule( const char* name ) = 0;
115 virtual void foreachModule( const Visitor& visitor ) = 0;
116 };
117
118 #include "debugging/debugging.h"
119
120 template<typename Type>
121 class ModuleRef
122 {
123 Module* m_module;
124 Type* m_table;
125 public:
126 ModuleRef( const char* name ) : m_table( 0 ){
127         if ( !globalModuleServer().getError() ) {
128                 m_module = globalModuleServer().findModule( typename Type::Name(), typename Type::Version(), name );
129                 if ( m_module == 0 ) {
130                         globalModuleServer().setError( true );
131                         globalErrorStream() << "ModuleRef::initialise: type=" << makeQuoted( typename Type::Name() ) << " version=" << makeQuoted( typename Type::Version() ) << " name=" << makeQuoted( name ) << " - not found\n";
132                 }
133                 else
134                 {
135                         m_module->capture();
136                         if ( !globalModuleServer().getError() ) {
137                                 m_table = static_cast<Type*>( m_module->getTable() );
138                         }
139                 }
140         }
141 }
142 ~ModuleRef(){
143         if ( m_module != 0 ) {
144                 m_module->release();
145         }
146 }
147 Type* getTable(){
148 #if defined( _DEBUG )
149         ASSERT_MESSAGE( m_table != 0, "ModuleRef::getTable: type=" << makeQuoted( typename Type::Name() ) << " version=" << makeQuoted( typename Type::Version() ) << " - module-reference used without being initialised" );
150 #endif
151         return m_table;
152 }
153 };
154
155 template<typename Type>
156 class SingletonModuleRef
157 {
158 Module* m_module;
159 Type* m_table;
160 public:
161
162 SingletonModuleRef()
163         : m_module( 0 ), m_table( 0 ){
164 }
165
166 bool initialised() const {
167         return m_module != 0;
168 }
169
170 void initialise( const char* name ){
171         m_module = globalModuleServer().findModule( typename Type::Name(), typename Type::Version(), name );
172         if ( m_module == 0 ) {
173                 globalModuleServer().setError( true );
174                 globalErrorStream() << "SingletonModuleRef::initialise: type=" << makeQuoted( typename Type::Name() ) << " version=" << makeQuoted( typename Type::Version() ) << " name=" << makeQuoted( name ) << " - not found\n";
175         }
176 }
177
178 Type* getTable(){
179 #if defined( _DEBUG )
180         ASSERT_MESSAGE( m_table != 0, "SingletonModuleRef::getTable: type=" << makeQuoted( typename Type::Name() ) << " version=" << makeQuoted( typename Type::Version() ) << " - module-reference used without being initialised" );
181 #endif
182         return m_table;
183 }
184 void capture(){
185         if ( initialised() ) {
186                 m_module->capture();
187                 m_table = static_cast<Type*>( m_module->getTable() );
188         }
189 }
190 void release(){
191         if ( initialised() ) {
192                 m_module->release();
193         }
194 }
195 };
196
197 template<typename Type>
198 class GlobalModule
199 {
200 static SingletonModuleRef<Type> m_instance;
201 public:
202 static SingletonModuleRef<Type>& instance(){
203         return m_instance;
204 }
205 static Type& getTable(){
206         return *m_instance.getTable();
207 }
208 };
209
210 template<class Type>
211 SingletonModuleRef<Type> GlobalModule<Type>::m_instance;
212
213
214 template<typename Type>
215 class GlobalModuleRef
216 {
217 public:
218 GlobalModuleRef( const char* name = "*" ){
219         if ( !globalModuleServer().getError() ) {
220                 GlobalModule<Type>::instance().initialise( name );
221         }
222         GlobalModule<Type>::instance().capture();
223 }
224 ~GlobalModuleRef(){
225         GlobalModule<Type>::instance().release();
226 }
227 Type& getTable(){
228         return GlobalModule<Type>::getTable();
229 }
230 };
231
232 #endif