ok
[xonotic/netradiant.git] / libs / modulesystem / modulesmap.h
1 /*\r
2 Copyright (C) 2001-2006, William Joseph.\r
3 All Rights Reserved.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #if !defined(INCLUDED_MODULESYSTEM_MODULESMAP_H)\r
23 #define INCLUDED_MODULESYSTEM_MODULESMAP_H\r
24 \r
25 #include "modulesystem.h"\r
26 #include "string/string.h"\r
27 #include <map>\r
28 #include <set>\r
29 \r
30 template<typename Type>\r
31 class ModulesMap : public Modules<Type>\r
32 {\r
33   typedef std::map<CopiedString, Module*> modules_t;\r
34   modules_t m_modules;\r
35 public:\r
36   ~ModulesMap()\r
37   {\r
38     for(modules_t::iterator i = m_modules.begin(); i != m_modules.end(); ++i) \r
39     {\r
40       (*i).second->release();\r
41     }\r
42   }\r
43 \r
44   typedef modules_t::const_iterator iterator;\r
45 \r
46   iterator begin() const\r
47   {\r
48     return m_modules.begin();\r
49   }\r
50   iterator end() const\r
51   {\r
52     return m_modules.end();\r
53   }\r
54 \r
55   void insert(const char* name, Module& module)\r
56   {\r
57     module.capture();\r
58     if(globalModuleServer().getError())\r
59     {\r
60       module.release();\r
61       globalModuleServer().setError(false);\r
62     }\r
63     else\r
64     {\r
65       m_modules.insert(modules_t::value_type(name, &module));\r
66     }\r
67   }\r
68 \r
69   Type* find(const char* name)\r
70   {\r
71     modules_t::iterator i = m_modules.find(name);\r
72     if(i != m_modules.end())\r
73     {\r
74       return static_cast<Type*>(Module_getTable(*(*i).second));\r
75     }\r
76     return 0;\r
77   }\r
78 \r
79   Type* findModule(const char* name)\r
80   {\r
81     return find(name);\r
82   }\r
83   void foreachModule(typename Modules<Type>::Visitor& visitor)\r
84   {\r
85     for(modules_t::iterator i = m_modules.begin(); i != m_modules.end(); ++i)\r
86     {\r
87       visitor.visit((*i).first.c_str(), *static_cast<const Type*>(Module_getTable(*(*i).second)));\r
88     }\r
89   }\r
90 };\r
91 \r
92 template<typename Type>\r
93 class InsertModules : public ModuleServer::Visitor\r
94 {\r
95   ModulesMap<Type>& m_modules;\r
96 public:\r
97   InsertModules(ModulesMap<Type>& modules)\r
98     : m_modules(modules)\r
99   {\r
100   }\r
101   void visit(const char* name, Module& module)\r
102   {\r
103     m_modules.insert(name, module);\r
104   }\r
105 };\r
106 \r
107 template<typename Type>\r
108 class ModulesRef\r
109 {\r
110   ModulesMap<Type> m_modules;\r
111 public:\r
112   ModulesRef(const char* names)\r
113   {\r
114     if(!globalModuleServer().getError())\r
115     {\r
116       if(string_equal(names, "*"))\r
117       {\r
118         InsertModules<Type> visitor(m_modules);\r
119         globalModuleServer().foreachModule(typename Type::Name(), typename Type::Version(), visitor);\r
120       }\r
121       else\r
122       {\r
123         StringTokeniser tokeniser(names);\r
124         for(;;)\r
125         {\r
126           const char* name = tokeniser.getToken();\r
127           if(string_empty(name))\r
128           {\r
129             break;\r
130           }\r
131           Module* module = globalModuleServer().findModule(typename Type::Name(), typename Type::Version(), name);\r
132           if(module == 0)\r
133           {\r
134             globalModuleServer().setError(true);\r
135             globalErrorStream() << "ModulesRef::initialise: type=" << makeQuoted(typename Type::Name()) << " version=" << makeQuoted(typename Type::Version()) << " name=" << makeQuoted(name) << " - not found\n";\r
136             break;\r
137           }\r
138           else\r
139           {\r
140             m_modules.insert(name, *module);\r
141           }\r
142         }\r
143       }\r
144     }\r
145   }\r
146   ModulesMap<Type>& get()\r
147   {\r
148     return m_modules;\r
149   }\r
150 };\r
151 \r
152 #endif\r