Free Electron
Castable.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __core_Castable_h__
8 #define __core_Castable_h__
9 
10 namespace fe
11 {
12 
13 #define FE_CASTABLE_DEBUG FALSE
14 #define FE_CASTABLE_MAP FALSE
15 
16 // NOTE Visual Studio doesn't appear to allow unspecialized export
17 // of template static members, so we have to compare on a string hash
18 // Unreal on Linux also seems to have problems with it.
19 #define FE_CASTABLE_STATIC FE_USE_TEMPLATE_STATIC
20 #define FE_CASTABLE_STRING_KEY FALSE //* vs hash (if not FE_CASTABLE_STATIC)
21 
22 #if !FE_RTTI_HOMEBREW
23 
24 typedef std::type_info fe_type_info;
25 
26 template<typename T>
27 inline const fe_type_info& getTypeId(void)
28 {
29  return typeid(T);
30 }
31 
32 #else
33 
34 class fe_type_info: public String
35 {
36  public:
37  const char* name(void) const { return c_str(); }
38 
39  bool before(const fe_type_info& a_rOther) const
40  { return (strcmp(name(),a_rOther.name())<0); }
41 };
42 
43 template<typename T>
44 class fe_type_info_of: public fe_type_info
45 {
46  public:
47  fe_type_info_of(void)
48  { String::operator=(FE_TYPESTRING(T)); }
49 };
50 
51 template<typename T>
52 inline const fe_type_info& getTypeId(void)
53 {
54  static fe_type_info_of<T> info;
55  return info;
56 }
57 
58 class fe_type_hash
59 {
60  public:
61  U64 value(void) const { return m_value; }
62 
63  protected:
64  U64 m_value;
65 };
66 
67 template<typename T>
68 class fe_type_hash_of: public fe_type_hash
69 {
70  public:
71  fe_type_hash_of(void)
72  {
73  const String typeString=FE_TYPESTRING(T);
74  m_value=typeString.computeFowlerNollVo1();
75 
76 // feLog("fe_type_hash_of<%s> is %p\n",
77 // typeString.c_str(),m_value);
78  }
79 };
80 
81 template<typename T>
82 inline U64 getTypeHash(void)
83 {
84  static fe_type_hash_of<T> hash;
85  return hash.value();
86 }
87 
88 #endif
89 
90 /**************************************************************************//**
91  @brief Base participation non-RTTI fallback dynamic casting mechanism
92 *//***************************************************************************/
93 class FE_DL_PUBLIC FE_CORE_PORT Castable
94 {
95  public:
96 
97 #if FE_RTTI_HOMEBREW
98 #if !FE_CASTABLE_STATIC
99 #if FE_CASTABLE_STRING_KEY
100  typedef String IdType;
101 #else
102  typedef U64 IdType;
103 #endif
104 #else
105  typedef void* IdType;
106 #endif
107 
108 #if FE_CASTABLE_MAP
109  class CastMap: public std::map<IdType,void*>
110  {
111  public:
112  void set(const IdType a_classId,void* a_pPtr)
113  { operator[](a_classId)=a_pPtr; }
114  void* lookup(const IdType a_classId) const
115  {
116  CastMap<IdType,void*>::const_iterator it=
117  find(a_classId);
118  return (it==end()? NULL: it->second);
119  }
120  };
121 #else
122  class Casting
123  {
124  public:
125  Casting(const IdType a_classId,void* a_pPtr):
126  m_classId(a_classId),
127  m_pPtr(a_pPtr) {}
128  IdType m_classId;
129  void* m_pPtr;
130  };
131  class CastMap: public std::vector<Casting>
132  {
133  public:
134  void set(const IdType a_classId,void* a_pPtr)
135  { push_back(Casting(a_classId,a_pPtr)); }
136  void* lookup(const IdType a_classId) const
137  {
138  const U32 count=size();
139  for(U32 index=0;index<count;index++)
140  {
141  const Casting& rCasting=operator[](index);
142  if(rCasting.m_classId == a_classId)
143  {
144  return rCasting.m_pPtr;
145  }
146  }
147  return NULL;
148  }
149  };
150 #endif
151 
152  Castable(void) {}
153 
154 #if FE_CPLUSPLUS >= 201103L
155  //* We have to specify these as default because deleting
156  //* the implicit copy-assignment and move-assignment
157  //* operator below also automatically deletes the implicit
158  //* copy-constructor and move-constructor.
159  Castable(Castable&&) =default;
160  Castable(const Castable&) =default;
161 
162  //* otherwise gcc warns with '-Wvirtual-move-assign'
163  Castable& operator=(Castable&&) =delete;
164  Castable& operator=(const Castable&) =delete;
165 #endif
166 
167 #if !FE_CASTABLE_STATIC
168 #if FE_CASTABLE_STRING_KEY
169  void addCast(const String& a_classId,void* a_pPtr)
170 #else
171  void addCast(const IdType a_classId,void* a_pPtr)
172 #endif
173  { m_castMap.set(a_classId,a_pPtr); }
174 #else
175  void addCast(IdType a_classId,void* a_pPtr)
176  { m_castMap.set(a_classId,a_pPtr); }
177 #endif
178 
179  template<class X>
180  X* castTo(void) const;
181 
182  private:
183 
184  CastMap m_castMap;
185 #endif
186 };
187 
188 /**************************************************************************//**
189  @brief Per-class participation non-RTTI fallback dynamic casting mechanism
190 *//***************************************************************************/
191 template<class T>
192 class FE_DL_EXPORT CastableAs: virtual public Castable
193 {
194 #if FE_RTTI_HOMEBREW
195  public:
196 #if !FE_CASTABLE_STATIC
197  CastableAs(void):
198  Castable()
199  {
200 #if FE_CASTABLE_DEBUG
201 #if FE_CASTABLE_STRING_KEY
202  feLog("CastableAs::CastableAs<%s> %p id \"%s\"\n",
203  FE_TYPESTRING(T).c_str(),
204  (T*)this,classId().c_str());
205 #else
206  feLog("CastableAs::CastableAs<%s> %p id %p\n",
207  FE_TYPESTRING(T).c_str(),(T*)this,classId());
208 #endif
209 #endif
210 
211  addCast(classId(),(T*)this);
212  }
213 
214 #if FE_CASTABLE_STRING_KEY
215 static const String& classId(void) { return getTypeId<T>(); }
216 #else
217 static IdType classId(void) { return getTypeHash<T>(); }
218 #endif
219 #else
220 
221  CastableAs(void)
222  {
223  IdType id=CastableAs<T>::classId();
224 
225 #if FE_CASTABLE_DEBUG
226  feLog("CastableAs::CastableAs<%s> %p id %p\n",
227  FE_TYPESTRING(T).c_str(),(T*)this,id);
228 #endif
229 
230  addCast(id,(T*)this);
231  }
232 
233 static IdType classId(void) { return &ms_classId; }
234 
235  private:
236 static FE_DL_PUBLIC IdType ms_classId;
237 #endif
238 
239 #endif
240 };
241 
242 #if FE_RTTI_HOMEBREW
243 
244 #if FE_CASTABLE_STATIC
245 template<class T> FE_DL_PUBLIC Castable::IdType CastableAs<T>::ms_classId=NULL;
246 #endif
247 
248 template<class X>
249 inline X* Castable::castTo(void) const
250 {
251 #if FE_CASTABLE_DEBUG
252 #if !FE_CASTABLE_STATIC
253 #if FE_CASTABLE_STRING_KEY
254  feLog("Castable::castTo<%s> id \"%s\"\n",
255  FE_TYPESTRING(X).c_str(),CastableAs<X>::classId().c_str());
256 #else
257  feLog("Castable::castTo<%s> id %p\n",
258  FE_TYPESTRING(X).c_str(),CastableAs<X>::classId());
259 #endif
260 
261  for(CastMap::const_iterator it=m_castMap.begin();
262  it!=m_castMap.end();it++)
263  {
264 #if FE_CASTABLE_MAP
265 #if FE_CASTABLE_STRING_KEY
266  feLog(" \"%s\" %p\n",it->first.c_str(),it->second);
267 #else
268  feLog(" %p %p\n",it->first,it->second);
269 #endif
270 #else
271  feLog(" %p %p\n",it->m_classId,it->m_pPtr);
272 #endif
273  }
274 #else
275  feLog("Castable::castTo<%s> id %p\n",
276  FE_TYPESTRING(X).c_str(),CastableAs<X>::classId());
277  for(CastMap::const_iterator it=m_castMap.begin();
278  it!=m_castMap.end();it++)
279  {
280 #if FE_CASTABLE_MAP
281  feLog(" %p %p\n",it->first,it->second);
282 #else
283  feLog(" %p %p\n",it->m_classId,it->m_pPtr);
284 #endif
285  }
286 #endif
287 #endif
288 
289  return (X*)(m_castMap.lookup(CastableAs<X>::classId()));
290 }
291 #endif
292 
293 } // namespace
294 
295 #if FE_RTTI_HOMEBREW
296 template<class T,class U>
297 inline T* fe_cast(U* a_pU)
298 { return a_pU? a_pU->template castTo<T>(): NULL; }
299 #else
300 template<class T,class U>
301 inline T* fe_cast(U* a_pU) { return dynamic_cast<T*>(a_pU); }
302 #endif
303 
304 #endif // __core_Castable_h__
Base participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:93
String & operator=(const String &operand)
Compare to another String.
Definition: String.h:584
kernel
Definition: namespace.dox:3
Automatically reference-counted string container.
Definition: String.h:128
Per-class participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:192