Cafu Engine
TypeSys.hpp
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
6 
7 #ifndef CAFU_TYPESYS_TYPEINFO_HPP_INCLUDED
8 #define CAFU_TYPESYS_TYPEINFO_HPP_INCLUDED
9 
10 #include "Templates/Array.hpp"
11 
12 
13 struct luaL_Reg;
14 
15 
16 namespace cf
17 {
18  /// The TypeSys ("type system") namespace provides classes for two related, but entirely independent concepts:
19  /// - The TypeInfoT and TypeInfoManT classes provide meta-information about classes and class hierarchies.
20  /// - The Var*T classes provide meta-information about class members.
21  /// The rest of this text talks about the TypeInfo*T classes only: see the documentation of the Var*T classes
22  /// for the second point. -- TODO: update/revise this text accordingly!
23  ///
24  /// The main purpose of the Type System is to make the programmers life easier when he is working with inheritance
25  /// hierarchies of C++ classes. In many such cases, "meta" knowledge about the classes is required.
26  ///
27  /// For example, when binding a hierarchy of C++ classes to Lua it is very helpful during Lua state initialization when
28  /// we can iterate over all classes in the hierarchy (specially ordered so that bases classes always occur before their
29  /// child classes). Additionally, classes should register themselves automatically in the data-structure for the
30  /// iteration, so that adding new classes to the hierarchy is easy and doesn't require any changes elsewhere, such as
31  /// to the Lua init code (a very convenient and important feature for MOD and game developers!).
32  /// The TypeSys is employed for the game entities hierarchy (BaseEntityT), for which the TypeSys was initially invented,
33  /// as well as the windows hierarchy of the GuiSys (cf::GuiSys::WindowT), which supports scripting as well.
34  ///
35  /// Other uses directly suggest themselves from the details of the implementation, or were trivially added to the basic system:
36  /// - Auto-assign each type a unique type number, e.g. for sending over the network.
37  /// The type number is also "robust", i.e. independent of actual static initialization order.
38  /// - Be able to iterate over all types (entity classes), e.g. for early initialization of the Lua state (adding a metatable
39  /// for each entity class to the registry of the Lua state), or for listing all supported script methods (user help), etc.
40  /// - Factory: Be able to instantiate an entity class by type name (e.g. from map file) or by type number (e.g. as received over the network).
41  /// ( - Provide a faster means for dynamic_cast<>(). )
42  ///
43  /// The Type System achieves its goals by explicitly modelling an inheritance hierarchy of C++ classes as a graph,
44  /// which presents a "meta-layer" of information about the hierarchy and thus allows other C++ code to become conciously
45  /// aware of the inheritance structure.
46  namespace TypeSys
47  {
48  class TypeInfoManT;
49 
50 
51  // Unfortunately, when this is nested in TypeInfoT, it cannot be forward-declared...
53  {
54  };
55 
56 
57  class MethsDocT
58  {
59  public:
60 
61  const char* Name;
62  const char* Doc;
63  const char* ReturnType;
64  const char* Parameters;
65  };
66 
67 
68  class VarsDocT
69  {
70  public:
71 
72  const char* Name;
73  const char* Doc;
74  };
75 
76 
77  /// This class keeps type information (about an entity class that occurs in the game).
78  /// (Supports single, but not multiple inheritance.)
79  class TypeInfoT
80  {
81  public:
82 
83  // TODO: Is there a nice way to make the CreateInstance() call-back type-safe?
84  // Note that for entities (who have a virtual GetType() method), the following asserts should hold:
85  // BaseEntityT* BE=dynamic_cast<BaseEntityT*>(SomeType->CreateInstance());
86  // or BaseEntityT* BE=(BaseEntityT*)SomeType->CreateInstance();
87  // assert(BE!=NULL);
88  // assert(BE->GetType()==SomeType);
89  typedef void* (*CreateInstanceT)(const CreateParamsT& Params);
90 
91  /// The constructor.
92  /// This is supposed to be called only by the static TypeInfoT member of each entity class.
93  TypeInfoT(TypeInfoManT& TIM, const char* ClassName_, const char* BaseClassName_, CreateInstanceT CreateInstance_, const luaL_Reg MethodsList_[],
94  const char* DocClass_=NULL, const MethsDocT DocMethods_[]=NULL, const MethsDocT DocCallbacks_[]=NULL, const VarsDocT DocVars_[]=NULL);
95 
96  /// Prints the contents of this node to the console.
97  /// @param Recurse Whether the children (derived classes) of this node should be printed.
98  /// @param RecDepth The current recursion depth. This is for the methods internal use - user code should never pass it.
99  void Print(bool Recurse=true, unsigned long RecDepth=0) const;
100 
101  /// Determines whether the other given type info is in the inheritance tree of this type
102  /// (this method roughly corresponds to dynamic_cast<>() in C++).
103  bool HierarchyHas(const TypeInfoT* Other) const;
104 
105  /// Returns the next type info in the hierarchy.
106  const TypeInfoT* GetNext() const;
107 
108 
109  const char* ClassName; ///< The name of this class.
110  const char* BaseClassName; ///< The name of the base/super/parent class of this class.
111  CreateInstanceT CreateInstance; ///< The call-back function that creates an instance of this class.
112  const luaL_Reg* MethodsList; ///< The list (array) of Lua methods that this class implements.
113 
114  const TypeInfoT* Base; ///< The type info for the base class.
115  const TypeInfoT* Sibling; ///< The type info for the next sibling class (a linked list).
116  const TypeInfoT* Child; ///< The type info for the first child class.
117  unsigned long TypeNr; ///< The unique and "robust" number of this type, obtained by enumerating the hierarchy nodes in depth-first order.
118  unsigned long LastChildNr; ///< The highest TypeNr in the subhierarchy of this type. Depth-first enumeration guarantees that for all type numbers T in this subhierarchy, TypeNr<=T<=LastChildNr holds.
119 
120  // The next three members provide documentation about the class that this TypeInfoT is about.
121  // They are intended to provide the user with live help in CaWE (e.g. as tool-tips), with live
122  // help in scripts (e.g. `window:help()`), and to automatically generate "fake" header files
123  // that are processed by Doxygen in order to create online scripting reference documentation.
124  const char* DocClass; ///< Documentation for this class.
125  const MethsDocT* DocMethods; ///< Documentation for the Lua methods in MethodsList.
126  const MethsDocT* DocCallbacks; ///< Documentation for any Lua methods that we call but expect users to provide implementations for.
127  const VarsDocT* DocVars; ///< Documentation for the variables in this class. (Used in classes that have `cf::TypeSys::VarT<>` instances.)
128 
129 
130  private:
131 
132  TypeInfoT(const TypeInfoT&); ///< Use of the Copy Constructor is not allowed.
133  void operator = (const TypeInfoT&); ///< Use of the Assignment Operator is not allowed.
134  };
135 
136 
137  /// This class manages the type infos.
138  ///
139  /// Intended usage:
140  /// Each entity class that occurs in the game keeps a static TypeInfoT member
141  /// (plus a non-static, *virtual* GetTypeInfo() method that returns that member).
142  /// The constructor of each such TypeInfoT member registers its own this-pointer with an instance of this class,
143  /// so that when main() begins, the TypeInfoManT is aware of all TypeInfoTs and thus all entity classes.
144  /// Its Init() method then completes the type initialization.
146  {
147  public:
148 
149  /// The constructor.
150  TypeInfoManT();
151 
152  /// Registers the given TypeInfoT with this type info manager.
153  /// Only the TypeInfoT constructor code should call this, which in turn should only occur during global static initialization time,
154  /// never after Init() has been called.
155  void Register(TypeInfoT* TI);
156 
157  /// Completes the initialization of the TypeInfoManT and the registered type infos.
158  /// Should be called exactly once before any other TypeInfoManT method is called.
159  void Init();
160 
161 
162  /// Returns the type info matching the class name ClassName.
163  /// @returns the (pointer to the) TypeInfoT matching ClassName, or NULL if not found.
164  const TypeInfoT* FindTypeInfoByName(const char* ClassName) const;
165 
166  /// Returns the type info matching the type number TypeNr.
167  /// @returns the (pointer to the) TypeInfoT T, so that T->TypeNr==TypeNr.
168  const TypeInfoT* FindTypeInfoByNr(unsigned long TypeNr) const;
169 
170  /// Returns all type infos registered with this TypeInfoManT, ordered by name.
171  const ArrayT<const TypeInfoT*>& GetTypeInfosByName() const { assert(IsInited); return TypeInfosByName; }
172 
173  /// Returns all type infos registered with this TypeInfoManT, ordered by type number.
174  /// `GetTypeInfosByNr()[i]->TypeNr == i`
175  const ArrayT<const TypeInfoT*>& GetTypeInfosByNr() const { assert(IsInited); return TypeInfosByNr; }
176 
177  /// Returns the roots of the inheritance trees. (Normally there should only be one root.)
178  const ArrayT<const TypeInfoT*>& GetTypeInfoRoots() const { assert(IsInited); return TypeInfoRoots; }
179 
180 
181  private:
182 
183  bool IsInited; ///< Tells whether Init() has already been called.
184  ArrayT<const TypeInfoT*> TypeInfosByName; ///< The registered type infos listed in alphabetical order.
185  ArrayT<const TypeInfoT*> TypeInfosByNr; ///< The registered type infos listed in TypeNr order, TypeInfosByNr[i].TypeNr==i.
186  ArrayT<const TypeInfoT*> TypeInfoRoots; ///< The roots of the inheritance trees. Normally there should only be one root.
187  };
188  }
189 }
190 
191 
192 /* #define DECLARE_TYPE_INFO() \
193  /// Returns the proper type info for this class. This method is virtual \
194  /// so that it works even when called with a base class pointer. \
195  virtual const cf::TypeSys::TypeInfoT* GetType() const { return &TypeInfo; } \
196 \
197  /// Creates an instance of this class from the given Params object. \
198  /// This call-back function is a part (member) of the TypeInfoT of this class. \
199  static void* CreateInstance(const cf::TypeSys::CreateParamsT& Params); \
200 \
201  /// The type info object for (objects/instances of) this class. \
202  static const cf::TypeSys::TypeInfoT TypeInfo; */
203 
204 
205 /* #define IMPLEMENT_TYPE_INFO() \
206 // ... */
207 
208 #endif
void Print(bool Recurse=true, unsigned long RecDepth=0) const
Prints the contents of this node to the console.
Definition: TypeSys.cpp:46
const TypeInfoT * Sibling
The type info for the next sibling class (a linked list).
Definition: TypeSys.hpp:115
const TypeInfoT * FindTypeInfoByName(const char *ClassName) const
Returns the type info matching the class name ClassName.
Definition: TypeSys.cpp:232
TypeInfoManT()
The constructor.
Definition: TypeSys.cpp:101
const TypeInfoT * GetNext() const
Returns the next type info in the hierarchy.
Definition: TypeSys.cpp:80
const ArrayT< const TypeInfoT * > & GetTypeInfosByName() const
Returns all type infos registered with this TypeInfoManT, ordered by name.
Definition: TypeSys.hpp:171
unsigned long LastChildNr
The highest TypeNr in the subhierarchy of this type. Depth-first enumeration guarantees that for all ...
Definition: TypeSys.hpp:118
const VarsDocT * DocVars
Documentation for the variables in this class. (Used in classes that have cf::TypeSys::VarT<> instanc...
Definition: TypeSys.hpp:127
const ArrayT< const TypeInfoT * > & GetTypeInfosByNr() const
Returns all type infos registered with this TypeInfoManT, ordered by type number. ...
Definition: TypeSys.hpp:175
const TypeInfoT * FindTypeInfoByNr(unsigned long TypeNr) const
Returns the type info matching the type number TypeNr.
Definition: TypeSys.cpp:260
This class manages the type infos.
Definition: TypeSys.hpp:145
const char * DocClass
Documentation for this class.
Definition: TypeSys.hpp:124
const TypeInfoT * Child
The type info for the first child class.
Definition: TypeSys.hpp:116
bool HierarchyHas(const TypeInfoT *Other) const
Determines whether the other given type info is in the inheritance tree of this type (this method rou...
Definition: TypeSys.cpp:68
CreateInstanceT CreateInstance
The call-back function that creates an instance of this class.
Definition: TypeSys.hpp:111
void Register(TypeInfoT *TI)
Registers the given TypeInfoT with this type info manager.
Definition: TypeSys.cpp:107
const MethsDocT * DocMethods
Documentation for the Lua methods in MethodsList.
Definition: TypeSys.hpp:125
unsigned long TypeNr
The unique and "robust" number of this type, obtained by enumerating the hierarchy nodes in depth-fir...
Definition: TypeSys.hpp:117
const luaL_Reg * MethodsList
The list (array) of Lua methods that this class implements.
Definition: TypeSys.hpp:112
const char * BaseClassName
The name of the base/super/parent class of this class.
Definition: TypeSys.hpp:110
const char * ClassName
The name of this class.
Definition: TypeSys.hpp:109
Definition: Renderer.hpp:16
Definition: TypeSys.hpp:52
Definition: TypeSys.hpp:57
This class keeps type information (about an entity class that occurs in the game).
Definition: TypeSys.hpp:79
const TypeInfoT * Base
The type info for the base class.
Definition: TypeSys.hpp:114
const ArrayT< const TypeInfoT * > & GetTypeInfoRoots() const
Returns the roots of the inheritance trees. (Normally there should only be one root.)
Definition: TypeSys.hpp:178
const MethsDocT * DocCallbacks
Documentation for any Lua methods that we call but expect users to provide implementations for...
Definition: TypeSys.hpp:126
TypeInfoT(TypeInfoManT &TIM, const char *ClassName_, const char *BaseClassName_, CreateInstanceT CreateInstance_, const luaL_Reg MethodsList_[], const char *DocClass_=NULL, const MethsDocT DocMethods_[]=NULL, const MethsDocT DocCallbacks_[]=NULL, const VarsDocT DocVars_[]=NULL)
The constructor.
Definition: TypeSys.cpp:21
Definition: TypeSys.hpp:68
void Init()
Completes the initialization of the TypeInfoManT and the registered type infos.
Definition: TypeSys.cpp:125