]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/server.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / radiant / server.cpp
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 #include "server.h"
23 #include "globaldefs.h"
24
25 #include "debugging/debugging.h"
26 #include "warnings.h"
27
28 #include <vector>
29 #include <map>
30 #include "os/path.h"
31
32 #include "modulesystem.h"
33
34 class RadiantModuleServer : public ModuleServer {
35     typedef std::pair<CopiedString, int> ModuleType;
36     typedef std::pair<ModuleType, CopiedString> ModuleKey;
37     typedef std::map<ModuleKey, Module *> Modules_;
38     Modules_ m_modules;
39     bool m_error;
40
41 public:
42     RadiantModuleServer() : m_error(false)
43     {
44     }
45
46     void setError(bool error)
47     {
48         m_error = error;
49     }
50
51     bool getError() const
52     {
53         return m_error;
54     }
55
56     TextOutputStream &getOutputStream()
57     {
58         return globalOutputStream();
59     }
60
61     TextOutputStream &getErrorStream()
62     {
63         return globalErrorStream();
64     }
65
66     DebugMessageHandler &getDebugMessageHandler()
67     {
68         return globalDebugMessageHandler();
69     }
70
71     void registerModule(const char *type, int version, const char *name, Module &module)
72     {
73         if (!m_modules.insert(Modules_::value_type(ModuleKey(ModuleType(type, version), name), &module)).second) {
74             globalErrorStream() << "module already registered: type=" << makeQuoted(type) << " name="
75                                 << makeQuoted(name) << "\n";
76         } else {
77             globalOutputStream() << "Module Registered: type=" << makeQuoted(type) << " version=" << makeQuoted(version)
78                                  << " name=" << makeQuoted(name) << "\n";
79         }
80     }
81
82     Module *findModule(const char *type, int version, const char *name) const
83     {
84         Modules_::const_iterator i = m_modules.find(ModuleKey(ModuleType(type, version), name));
85         if (i != m_modules.end()) {
86             return (*i).second;
87         }
88         return 0;
89     }
90
91     void foreachModule(const char *type, int version, const Visitor &visitor)
92     {
93         for (Modules_::const_iterator i = m_modules.begin(); i != m_modules.end(); ++i) {
94             if (string_equal((*i).first.first.first.c_str(), type)) {
95                 visitor.visit((*i).first.second.c_str(), *(*i).second);
96             }
97         }
98     }
99 };
100
101
102 #if GDEF_OS_WINDOWS
103
104 #include <windows.h>
105
106 const int FORMAT_BUFSIZE = 2048;
107 const char* FormatGetLastError(){
108     static char buf[FORMAT_BUFSIZE];
109     FormatMessage(
110         FORMAT_MESSAGE_FROM_SYSTEM |
111         FORMAT_MESSAGE_IGNORE_INSERTS,
112         NULL,
113         GetLastError(),
114         MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
115         buf,
116         FORMAT_BUFSIZE,
117         NULL
118         );
119     return buf;
120 }
121
122 class DynamicLibrary
123 {
124 HMODULE m_library;
125 public:
126 typedef int ( __stdcall * FunctionPointer )();
127
128 DynamicLibrary( const char* filename ){
129     m_library = LoadLibrary( filename );
130     if ( m_library == 0 ) {
131         globalErrorStream() << "LoadLibrary failed: '" << filename << "'\n";
132         globalErrorStream() << "GetLastError: " << FormatGetLastError();
133     }
134 }
135 ~DynamicLibrary(){
136     if ( !failed() ) {
137         FreeLibrary( m_library );
138     }
139 }
140 bool failed(){
141     return m_library == 0;
142 }
143 FunctionPointer findSymbol( const char* symbol ){
144     FunctionPointer address = (FunctionPointer) GetProcAddress( m_library, symbol );
145     if ( address == 0 ) {
146         globalErrorStream() << "GetProcAddress failed: '" << symbol << "'\n";
147         globalErrorStream() << "GetLastError: " << FormatGetLastError();
148     }
149     return address;
150 }
151 };
152
153 #elif GDEF_OS_POSIX
154
155 #include <dlfcn.h>
156
157 class DynamicLibrary {
158     void *m_library;
159 public:
160     typedef int ( *FunctionPointer )();
161
162     DynamicLibrary(const char *filename)
163     {
164         m_library = dlopen(filename, RTLD_NOW);
165     }
166
167     ~DynamicLibrary()
168     {
169         if (!failed()) {
170             dlclose(m_library);
171         }
172     }
173
174     bool failed()
175     {
176         return m_library == 0;
177     }
178
179     FunctionPointer findSymbol(const char *symbol)
180     {
181         FunctionPointer p = (FunctionPointer) dlsym(m_library, symbol);
182         if (p == 0) {
183             const char *error = reinterpret_cast<const char *>( dlerror());
184             if (error != 0) {
185                 globalErrorStream() << error;
186             }
187         }
188         return p;
189     }
190 };
191
192 #else
193 #error "unsupported platform"
194 #endif
195
196 class DynamicLibraryModule {
197     typedef void ( RADIANT_DLLIMPORT *RegisterModulesFunc )(ModuleServer &server);
198
199     DynamicLibrary m_library;
200     RegisterModulesFunc m_registerModule;
201 public:
202     DynamicLibraryModule(const char *filename)
203             : m_library(filename), m_registerModule(0)
204     {
205         if (!m_library.failed()) {
206             m_registerModule = reinterpret_cast<RegisterModulesFunc>( m_library.findSymbol("Radiant_RegisterModules"));
207 #if 0
208             if ( !m_registerModule ) {
209                 m_registerModule = reinterpret_cast<RegisterModulesFunc>( m_library.findSymbol( "Radiant_RegisterModules@4" ) );
210             }
211 #endif
212         }
213     }
214
215     bool failed()
216     {
217         return m_registerModule == 0;
218     }
219
220     void registerModules(ModuleServer &server)
221     {
222         m_registerModule(server);
223     }
224 };
225
226
227 class Libraries {
228     typedef std::vector<DynamicLibraryModule *> libraries_t;
229     libraries_t m_libraries;
230
231 public:
232     ~Libraries()
233     {
234         release();
235     }
236
237     void registerLibrary(const char *filename, ModuleServer &server)
238     {
239         DynamicLibraryModule *library = new DynamicLibraryModule(filename);
240
241         if (library->failed()) {
242             delete library;
243         } else {
244             m_libraries.push_back(library);
245             library->registerModules(server);
246         }
247     }
248
249     void release()
250     {
251         for (libraries_t::iterator i = m_libraries.begin(); i != m_libraries.end(); ++i) {
252             delete *i;
253         }
254     }
255
256     void clear()
257     {
258         m_libraries.clear();
259     }
260 };
261
262
263 Libraries g_libraries;
264 RadiantModuleServer g_server;
265
266 ModuleServer &GlobalModuleServer_get()
267 {
268     return g_server;
269 }
270
271 void GlobalModuleServer_loadModule(const char *filename)
272 {
273     g_libraries.registerLibrary(filename, g_server);
274 }
275
276 void GlobalModuleServer_Initialise()
277 {
278 }
279
280 void GlobalModuleServer_Shutdown()
281 {
282 }