NOW I do it right: #woxblox#
[divverent/netradiant.git] / libs / typesystem.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #if !defined(INCLUDED_TYPESYSTEM_H)
23 #define INCLUDED_TYPESYSTEM_H
24
25
26 #include <list>
27 #include <vector>
28 #include "generic/callback.h"
29 #include "generic/static.h"
30
31 class InitialiserList
32 {
33   typedef std::list<Callback> Initialisers;
34   Initialisers m_initialisers;
35   mutable bool m_initialised;
36 public:
37   InitialiserList() : m_initialised(false)
38   {
39   }
40   void addInitialiser(const Callback& callback)
41   {
42     m_initialisers.push_back(callback); 
43   }
44   void initialise() const
45   {
46     if(!m_initialised)
47     {
48       m_initialised = true;
49
50       for(Initialisers::const_iterator i = m_initialisers.begin(); i != m_initialisers.end(); ++i)
51       {
52         (*i)();
53       }
54     }
55   }
56 };
57
58 //--Type System-------------------
59
60 class TypeSystemInitialiser : public InitialiserList
61 {
62 };
63
64 typedef SmartStatic<TypeSystemInitialiser> StaticTypeSystemInitialiser;
65
66 class TypeSystemRef : public StaticTypeSystemInitialiser
67 {
68 public:
69   TypeSystemRef()
70   {
71     StaticTypeSystemInitialiser::instance().initialise();
72   }
73 };
74
75
76
77 typedef std::size_t TypeId;
78 typedef void*(*TypeCast)(void*);
79
80 template<std::size_t SIZE>
81 class TypeCastTable
82 {
83   TypeCast m_casts[SIZE];
84 public:
85   TypeCastTable()
86   {
87     std::uninitialized_fill(m_casts, m_casts + SIZE, TypeCast(0));
88   }
89   void install(TypeId typeId, TypeCast typeCast)
90   {
91     m_casts[typeId] = typeCast;
92   }
93   void* cast(TypeId typeId, void* p)
94   {
95     TypeCast typeCast = m_casts[typeId];
96     if(typeCast != 0)
97     {
98       return typeCast(p);
99     }
100     return 0;
101   }
102 };
103
104 template<typename Type, typename Cast>
105 class CastInstaller
106 {
107 public:
108   static void install(TypeCastTable<Type::SIZE>& table)
109   {
110     table.install(Type::getTypeId(), Cast::cast);
111   }
112 };
113
114 template<typename Type>
115 class IdentityCast
116 {
117 public:
118   static void* cast(void* p)
119   {
120     return p;
121   }
122 };
123
124 template<typename Type, typename Base>
125 class StaticCast
126 {
127 public:
128   static void* cast(void* p)
129   {
130     return static_cast<Base*>(reinterpret_cast<Type*>(p));
131   }
132 };
133
134 template<typename Type>
135 class NullType
136 {
137 };
138
139 template<typename Type, typename Contained>
140 class ContainedCast
141 {
142 public:
143   static void* cast(void* p)
144   {
145     return &reinterpret_cast<Type*>(p)->get(NullType<Contained>());
146   }
147 };
148
149
150 #endif