Line data Source code
1 : /*
2 : * Copyright (c) 2010-2012: G-CSC, Goethe University Frankfurt
3 : * Author: 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 : #include "class_name_provider.h"
34 :
35 : namespace ug
36 : {
37 : namespace bridge
38 : {
39 :
40 2734 : ClassNameNode::ClassNameNode()
41 : {
42 : m_name.clear();
43 2734 : }
44 :
45 3731 : void ClassNameNode::set_name(const std::string& name)
46 : {
47 : // set name
48 7462 : m_name = std::string(name);
49 :
50 : // check size
51 3731 : if(m_name.empty())
52 0 : UG_THROW_REGISTRY_MSG("Name must be longer than 0 characters.");
53 3731 : }
54 :
55 1084 : void ClassNameNode::add_base_class(const ClassNameNode& node)
56 : {
57 : std::vector<const ClassNameNode*>::iterator it
58 1084 : = std::find(m_vBaseClass.begin(), m_vBaseClass.end(), &node);
59 1084 : if(it == m_vBaseClass.end())
60 1084 : m_vBaseClass.push_back(&node);
61 1084 : }
62 :
63 0 : bool ClassNameNode::named() const
64 : {
65 : // if string is empty, then has not been named
66 0 : if(empty()) return false;
67 :
68 : // if string starts with '[' then has only been predeclared
69 0 : if(m_name.c_str()[0] == '[') return false;
70 :
71 : // has been named
72 : return true;
73 : }
74 :
75 :
76 0 : bool ClassNameVecContains(const std::vector<const char*>& names, const std::string& name)
77 : {
78 : // return true if pointers are equal
79 0 : for(size_t i = 0; i < names.size(); ++i)
80 0 : if(name.c_str() == names[i]) return true;
81 :
82 : // security fallback: if pointers not equal, compare also strings
83 0 : for(size_t i = 0; i < names.size(); ++i)
84 0 : if(name == names[i]) return true;
85 :
86 : // both comparisons fail. Name is not this class, nor on of its parents
87 : return false;
88 : }
89 :
90 0 : void ExtractClassNameVec(std::vector<const char*>& names, const ClassNameNode& node, bool clearVec)
91 : {
92 : // clear vector
93 0 : if(clearVec)
94 : names.clear();
95 :
96 : // add node name
97 0 : names.push_back(node.name().c_str());
98 :
99 : // add all base classes
100 0 : for(size_t i = 0; i < node.num_base_classes(); ++i)
101 0 : ExtractClassNameVec(names, node.base_class(i), false);
102 0 : }
103 :
104 0 : bool ClassNameTreeContains(const ClassNameNode& node, const std::string& name)
105 : {
106 : // if the node is the name, return true
107 0 : if(node.name() == name) return true;
108 :
109 : // else search in parents
110 : bool bContains = false;
111 :
112 0 : for(size_t i = 0; i < node.num_base_classes(); ++i)
113 0 : bContains |= ClassNameTreeContains(node.base_class(i), name);
114 :
115 : // return if found in parents
116 : return bContains;
117 : }
118 :
119 0 : bool ClassNameTreeWay(std::vector<size_t>& vWay, const ClassNameNode& node,
120 : const std::string& name)
121 : {
122 : // if the node is the name, return true
123 0 : if(node.name() == name) return true;
124 :
125 : // look in parents
126 0 : for(size_t i = 0; i < node.num_base_classes(); ++i)
127 : {
128 0 : if(ClassNameTreeWay(vWay, node.base_class(i), name))
129 : {
130 0 : vWay.push_back(i);
131 0 : return true;
132 : }
133 : }
134 : // return if found in parents
135 0 : return false;
136 : }
137 :
138 0 : void* ClassCastProvider::
139 : cast_to_base_class(void* pDerivVoid, const ClassNameNode*& node, const std::string& baseName)
140 : {
141 : // find way to base class
142 : std::vector<size_t> vWay;
143 0 : if(!ClassNameTreeWay(vWay, *node, baseName))
144 : {
145 0 : UG_ERR_LOG("ERROR in ClassCastProvider::cast_to_base_class: Request"
146 : " to cast from derived class '"<< node->name()<<"' to "
147 : " base class '"<<baseName<<"', but no such base class in"
148 : " registered class hierarchy.");
149 0 : throw new UGError_ClassCastFailed(node->name(), baseName);
150 : }
151 :
152 : void* currPtr = pDerivVoid;
153 0 : const ClassNameNode* pCurrNode = node;
154 :
155 : // cast all the way down
156 0 : while(!vWay.empty())
157 : {
158 : // get base class to cast to
159 0 : const ClassNameNode* pBaseClassNode = &pCurrNode->base_class(vWay.back());
160 :
161 : // get name pair
162 : std::pair<const ClassNameNode*, const ClassNameNode*> namePair(pBaseClassNode, pCurrNode);
163 :
164 : // find in map
165 : std::map<std::pair<const ClassNameNode*, const ClassNameNode*>, CastFunc>::iterator it;
166 : it = m_mmCast.find(namePair);
167 :
168 0 : if(it == m_mmCast.end())
169 : {
170 0 : UG_ERR_LOG("ERROR in ClassCastProvider::cast_to_base_class:"
171 : " Request intermediate cast from derived class '" <<
172 : pCurrNode->name() <<"' to direct base class '"
173 : <<pBaseClassNode->name()<<"', but no such cast "
174 : " function registered.");
175 0 : throw new UGError_ClassCastFailed(node->name(), baseName);
176 : }
177 :
178 : // get cast function
179 0 : CastFunc pCastFunc = it->second;
180 :
181 : // cast
182 0 : currPtr = (*pCastFunc)(currPtr);
183 :
184 : // set node to base class
185 : pCurrNode = pBaseClassNode;
186 :
187 : // pop way
188 : vWay.pop_back();
189 : }
190 :
191 : // write current node on exit
192 0 : node = pCurrNode;
193 :
194 : // return current pointer
195 0 : return currPtr;
196 0 : }
197 :
198 :
199 0 : const void* ClassCastProvider::
200 : cast_to_base_class(const void* pDerivVoid, const ClassNameNode*& node, const std::string& baseName)
201 : {
202 0 : return const_cast<const void*>(cast_to_base_class(const_cast<void*>(pDerivVoid), node, baseName));
203 : }
204 :
205 :
206 :
207 :
208 : std::map<std::pair<const ClassNameNode*, const ClassNameNode*>, void* (*)(void*)>
209 : ClassCastProvider::m_mmCast = std::map<std::pair<const ClassNameNode*, const ClassNameNode*>, void* (*)(void*)> ();
210 :
211 : }// end of namespace
212 : }// end of namespace
|