ug4
class_name_provider_impl.h
Go to the documentation of this file.
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 
46 // ClassNameProvider
48 
49 template <typename TClass>
51 set_name(const std::string& nameIn, const std::string& group, bool newName)
52 {
53 // if class already named throw error
54  if(newName == true && m_bForwardDeclared==false && !m_ClassNameNode.empty())
55  {
56  if(nameIn != name())
58  "Trying to register class with name '"<<nameIn
59  << "', that has already been named. This is not allowed.");
60  }
61 
62 // check name
63  if(nameIn.empty())
64  UG_THROW_REGISTRY_MSG("Registered class name has length zero");
65 
66  if(nameIn.c_str()[0] == '[')
67  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  if (found!=std::string::npos)
75  {
76  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  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  if (found!=std::string::npos && found == 0)
87  {
88  UG_ERR_LOG("Class Name "<<nameIn<<" starts with a number.\nThis is "
89  " not allowed. Please change naming.\n");
90  UG_THROW_REGISTRY_ERROR(nameIn,"Class Name must not start with number.");
91  }
92 
93 
94 // copy name into static string
95  m_ClassNameNode.set_name(nameIn);
96 
97 // set forward declared to false, since now name set
98  m_bForwardDeclared = false;
99 
100 // remember groups
101  m_group = std::string(group);
102 };
103 
104 template <typename TClass>
105 template <typename TParent1>
107 set_name(const std::string& name, const std::string& group, bool newName)
108 {
109 // set own name
110  set_name(name, group, newName);
111 
112 // add parent nodes
113  m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
114 }
115 
116 template <typename TClass>
117 template <typename TParent1, typename TParent2>
119 set_name(const std::string& name, const std::string& group,bool newName)
120 {
121 // set own name
122  set_name(name, group, newName);
123 
124 // add parent nodes
125  m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
126  m_ClassNameNode.add_base_class(ClassNameProvider<TParent2>::class_name_node());
127 }
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)
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>
153 {
154 // if name has not been set, set temporary forward declaration
155  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 const std::vector<const char*>& ClassNameProvider<TClass>::names()
163 {
164 // if name has not been set, set temporary forward declaration
165  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  ExtractClassNameVec(m_names, m_ClassNameNode, true);
170 
171 // return the vector of base class names
172  return m_names;
173 }
174 
175 template <typename TClass>
177 {
178 // build default name using typeinfo
179  std::string name("[[");
180  name.append( TypeName<TClass>() );
181  name.append(" (undeclared) ]]");
182 
183 // set this as current name, but remember pre-declaration
184  m_ClassNameNode.set_name(name);
185  m_bForwardDeclared = true;
186 }
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>
196 
197 template <typename TClass>
199 
201 // ClassCastProvider
203 
204 template <typename TBase, typename TDerived>
205 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  TBase* pBase = static_cast<TBase*>(pDeriv);
213 
214 // return cast to void
215  return reinterpret_cast<void*>(pBase);
216 }
217 
218 template <typename TBase, typename TDerived>
220 {
221  const ClassNameNode* pBaseNode =
223  const ClassNameNode* pDerivNode =
225 
226  std::pair<const ClassNameNode*, const ClassNameNode*>
227  namePair(pBaseNode, pDerivNode);
228 
229  m_mmCast[namePair] = &StaticVoidCast<TBase, TDerived>;
230 }
231 
232 template <typename T>
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
241 
242 // return it
243  return reinterpret_cast<T*>(ptr);
244 }
245 
246 template <typename T>
247 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
255 
256 // return it
257  return reinterpret_cast<const T*>(ptr);
258 }
259 
260 template <typename T>
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  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  return spDerivVoid.cast_reinterpret<T, FreeDelete>();
278 }
279 
280 template <typename T>
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  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  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__ */
location name
Definition: checkpoint_util.lua:128
Definition: smart_pointer.h:650
ConstSmartPtr< T, TFreePolicy > cast_reinterpret() const
Returns a SmartPtr with the specified type and shared reference counting.
Definition: smart_pointer.h:763
const void * get() const
Definition: smart_pointer.h:789
void set_impl(const void *ptr)
sets the void* to a different location correspoding to a cast to a new type T
Definition: smart_pointer.h:772
Definition: smart_pointer.h:296
Definition: smart_pointer.h:51
Definition: smart_pointer.h:525
void set_impl(void *ptr)
sets the void* to a different location correspoding to a cast to a new type T
Definition: smart_pointer.h:608
void * get()
Definition: smart_pointer.h:625
SmartPtr< T, TFreePolicy > cast_reinterpret() const
Returns a SmartPtr with the specified type and shared reference counting.
Definition: smart_pointer.h:599
Definition: smart_pointer.h:108
static void * cast_to_base_class(void *pDerivVoid, const ClassNameNode *&node, const std::string &baseName)
cast a pointer to the desired base class
Definition: class_name_provider.cpp:139
static T * cast_to(void *pDerivVoid, const ClassNameNode *&node)
casts a void pointer to a concrete class
static void add_cast_func()
add a cast function to the registry: Casts: Derived -> Base
static std::map< std::pair< const ClassNameNode *, const ClassNameNode * >, CastFunc > m_mmCast
Definition: class_name_provider.h:236
node for class names
Definition: class_name_provider.h:65
provides the name for a class
Definition: class_name_provider.h:102
static void set_foreward_declared()
sets a temporary name to the class
Definition: class_name_provider_impl.h:176
static const std::string & name()
name of this class
Definition: class_name_provider_impl.h:152
static const ClassNameNode & class_name_node()
return the class name node in the class hierarchy
Definition: class_name_provider.h:136
static bool is_a(const std::string &parent, bool strict=false)
Definition: class_name_provider_impl.h:130
static void set_name(const std::string &nameIn, const std::string &group, bool newName=false)
set name of class and copy parent names
Definition: class_name_provider_impl.h:51
static const std::vector< const char * > & names()
returns vector of all names including parent class names
Definition: class_name_provider_impl.h:162
bool ClassNameTreeContains(const ClassNameNode &node, const std::string &name)
returns if a name is contained in the name tree at node or in base classes
Definition: class_name_provider.cpp:104
void * StaticVoidCast(void *DerivVoidPtr)
static cast function for two classes
void ExtractClassNameVec(std::vector< const char * > &names, const ClassNameNode &node, bool clearVec)
returns the vector containing all names in the name tree for node and its base classes
Definition: class_name_provider.cpp:90
#define UG_ERR_LOG(msg)
Definition: log.h:383
the ug namespace
void baseName(std::string &nameOut, const std::string &nameIn)
Definition: vtkoutput.cpp:209
#define UG_THROW_REGISTRY_MSG(msg)
Definition: error.h:81
#define UG_THROW_REGISTRY_ERROR(cls, msg)
Definition: error.h:76