Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Authors: Sebastian Reiter, Andreas Vogel
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__
34 : #define __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__
35 :
36 : #include <algorithm>
37 : #include <string>
38 :
39 : #include "class_name_provider.h"
40 : #include "common/util/typename.h"
41 :
42 : namespace ug{
43 : namespace bridge{
44 :
45 : ////////////////////////////////////////////////////////////////////////////////
46 : // ClassNameProvider
47 : ////////////////////////////////////////////////////////////////////////////////
48 :
49 : template <typename TClass>
50 3731 : void ClassNameProvider<TClass>::
51 : set_name(const std::string& nameIn, const std::string& group, bool newName)
52 : {
53 : // if class already named throw error
54 3731 : if(newName == true && m_bForwardDeclared==false && !m_ClassNameNode.empty())
55 : {
56 0 : if(nameIn != name())
57 0 : UG_THROW_REGISTRY_ERROR(nameIn,
58 : "Trying to register class with name '"<<nameIn
59 : << "', that has already been named. This is not allowed.");
60 : }
61 :
62 : // check name
63 3731 : if(nameIn.empty())
64 0 : UG_THROW_REGISTRY_MSG("Registered class name has length zero");
65 :
66 3731 : if(nameIn.c_str()[0] == '[')
67 0 : UG_THROW_REGISTRY_ERROR(nameIn, "Registered class name must not begin with '['");
68 :
69 : // check for non-allowed character
70 : size_t found = nameIn.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
71 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
72 : "_"
73 : "0123456789");
74 3731 : if (found!=std::string::npos)
75 : {
76 0 : UG_ERR_LOG("Non-allowed character '"<<nameIn[found]<<"' "<<
77 : "contained at position "<<int(found)<<" in registered Class Name "
78 : "'"<<nameIn<<"'.\nClass names must match the regular expression: "
79 : "[a-zA-Z_][a-zA-Z_0-9]*, \ni.e. only alphabetic characters, numbers "
80 : " and '_' are allowed; no numbers at the beginning.\n");
81 0 : UG_THROW_REGISTRY_ERROR(nameIn, "Class Name must only contain [a-zA-Z_][a-zA-Z_0-9]*.");
82 : }
83 :
84 : // check that no number at the beginning
85 : found = nameIn.find_first_of("0123456789");
86 3731 : if (found!=std::string::npos && found == 0)
87 : {
88 0 : UG_ERR_LOG("Class Name "<<nameIn<<" starts with a number.\nThis is "
89 : " not allowed. Please change naming.\n");
90 0 : UG_THROW_REGISTRY_ERROR(nameIn,"Class Name must not start with number.");
91 : }
92 :
93 :
94 : // copy name into static string
95 3731 : m_ClassNameNode.set_name(nameIn);
96 :
97 : // set forward declared to false, since now name set
98 3731 : m_bForwardDeclared = false;
99 :
100 : // remember groups
101 3731 : m_group = std::string(group);
102 3731 : };
103 :
104 : template <typename TClass>
105 : template <typename TParent1>
106 : void ClassNameProvider<TClass>::
107 : set_name(const std::string& name, const std::string& group, bool newName)
108 : {
109 : // set own name
110 982 : set_name(name, group, newName);
111 :
112 : // add parent nodes
113 982 : m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
114 : }
115 :
116 : template <typename TClass>
117 : template <typename TParent1, typename TParent2>
118 51 : void ClassNameProvider<TClass>::
119 : set_name(const std::string& name, const std::string& group,bool newName)
120 : {
121 : // set own name
122 51 : set_name(name, group, newName);
123 :
124 : // add parent nodes
125 51 : m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
126 51 : m_ClassNameNode.add_base_class(ClassNameProvider<TParent2>::class_name_node());
127 51 : }
128 :
129 : template <typename TClass>
130 : bool ClassNameProvider<TClass>::is_a(const std::string& parent, bool strict)
131 : {
132 : // check if class is forward declared
133 : if(m_bForwardDeclared)
134 : UG_THROW_REGISTRY_ERROR(parent,
135 : "Class '"<<parent<<"' must not be foreward declared to use is_a");
136 :
137 : // strict comparison: must match this class name, parents are not allowed
138 : if(strict)
139 : {
140 : // compare strings
141 : if(parent == name()) return true;
142 :
143 : // names does not match
144 : return false;
145 : }
146 :
147 : // return if parent name is contained in tree of base classes
148 : return ClassNameTreeContains(m_ClassNameNode, parent);
149 : }
150 :
151 : template <typename TClass>
152 : const std::string& ClassNameProvider<TClass>::name()
153 : {
154 : // if name has not been set, set temporary forward declaration
155 3472359 : if(m_ClassNameNode.empty()) set_foreward_declared();
156 :
157 : // return the name of this class as stored in ClassNameNode
158 : return m_ClassNameNode.name();
159 : }
160 :
161 : template <typename TClass>
162 0 : const std::vector<const char*>& ClassNameProvider<TClass>::names()
163 : {
164 : // if name has not been set, set temporary forward declaration
165 0 : if(m_ClassNameNode.empty()) set_foreward_declared();
166 :
167 : // create names list, including this class and all base classes
168 : // \todo: remove this, avoid names-vector
169 0 : ExtractClassNameVec(m_names, m_ClassNameNode, true);
170 :
171 : // return the vector of base class names
172 0 : return m_names;
173 : }
174 :
175 : template <typename TClass>
176 0 : void ClassNameProvider<TClass>::set_foreward_declared()
177 : {
178 : // build default name using typeinfo
179 0 : std::string name("[[");
180 0 : name.append( TypeName<TClass>() );
181 0 : name.append(" (undeclared) ]]");
182 :
183 : // set this as current name, but remember pre-declaration
184 0 : m_ClassNameNode.set_name(name);
185 0 : m_bForwardDeclared = true;
186 0 : }
187 :
188 : template <typename TClass>
189 : std::vector<const char*> ClassNameProvider<TClass>::m_names = std::vector<const char*>();
190 :
191 : template <typename TClass>
192 : std::string ClassNameProvider<TClass>::m_group = std::string("");
193 :
194 : template <typename TClass>
195 : bool ClassNameProvider<TClass>::m_bForwardDeclared = false;
196 :
197 : template <typename TClass>
198 : ClassNameNode ClassNameProvider<TClass>::m_ClassNameNode = ClassNameNode();
199 :
200 : ////////////////////////////////////////////////////////////////////////////////
201 : // ClassCastProvider
202 : ////////////////////////////////////////////////////////////////////////////////
203 :
204 : template <typename TBase, typename TDerived>
205 0 : void* StaticVoidCast(void* DerivVoidPtr)
206 : {
207 : // cast to derived class; this assumes, that the void pointer points to the
208 : // beginning of the data field of the Derived object
209 : TDerived* pDeriv = reinterpret_cast<TDerived*>(DerivVoidPtr);
210 :
211 : // static case to the Derid class
212 0 : TBase* pBase = static_cast<TBase*>(pDeriv);
213 :
214 : // return cast to void
215 0 : return reinterpret_cast<void*>(pBase);
216 : }
217 :
218 : template <typename TBase, typename TDerived>
219 : void ClassCastProvider::add_cast_func()
220 : {
221 : const ClassNameNode* pBaseNode =
222 : &ClassNameProvider<TBase>::class_name_node();
223 : const ClassNameNode* pDerivNode =
224 : &ClassNameProvider<TDerived>::class_name_node();
225 :
226 : std::pair<const ClassNameNode*, const ClassNameNode*>
227 : namePair(pBaseNode, pDerivNode);
228 :
229 1033 : m_mmCast[namePair] = &StaticVoidCast<TBase, TDerived>;
230 : }
231 :
232 : template <typename T>
233 0 : T* ClassCastProvider::
234 : cast_to(void* ptr, const ClassNameNode*& node)
235 : {
236 : // get base name
237 : const std::string& baseName = ClassNameProvider<T>::name();
238 :
239 : // cast the plain pointer
240 0 : ptr = ClassCastProvider::cast_to_base_class(ptr, node, baseName);
241 :
242 : // return it
243 0 : return reinterpret_cast<T*>(ptr);
244 : }
245 :
246 : template <typename T>
247 0 : const T* ClassCastProvider::
248 : cast_to(const void* ptr, const ClassNameNode*& node)
249 : {
250 : // get base name
251 : const std::string& baseName = ClassNameProvider<T>::name();
252 :
253 : // cast the plain pointer
254 0 : ptr = ClassCastProvider::cast_to_base_class(ptr, node, baseName);
255 :
256 : // return it
257 0 : return reinterpret_cast<const T*>(ptr);
258 : }
259 :
260 : template <typename T>
261 0 : SmartPtr<T> ClassCastProvider::
262 : cast_to(SmartPtr<void> spDerivVoid, const ClassNameNode*& node)
263 : {
264 : // get base name
265 : const std::string& baseName = ClassNameProvider<T>::name();
266 :
267 : // extract plain pointer
268 : void* rawPtr = spDerivVoid.get();
269 :
270 : // cast the plain pointer
271 0 : rawPtr = ClassCastProvider::cast_to_base_class(rawPtr, node, baseName);
272 :
273 : // sets as pointer to the smart ptr
274 : spDerivVoid.set_impl<T, FreeDelete>(rawPtr);
275 :
276 : // return it
277 0 : return spDerivVoid.cast_reinterpret<T, FreeDelete>();
278 : }
279 :
280 : template <typename T>
281 0 : ConstSmartPtr<T> ClassCastProvider::
282 : cast_to(ConstSmartPtr<void> spDerivVoid, const ClassNameNode*& node)
283 : {
284 : // get base name
285 : const std::string& baseName = ClassNameProvider<T>::name();
286 :
287 : // extract plain pointer
288 : const void* rawPtr = spDerivVoid.get();
289 :
290 : // cast the plain pointer
291 0 : rawPtr = ClassCastProvider::cast_to_base_class(rawPtr, node, baseName);
292 :
293 : // sets as pointer to the smart ptr
294 : spDerivVoid.set_impl<T, FreeDelete>(rawPtr);
295 :
296 : // return it
297 0 : return spDerivVoid.cast_reinterpret<T, FreeDelete>();
298 : }
299 : } // end namespace ug
300 : } // end namespace bridge
301 :
302 : #endif /* __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__ */
|