remove RSA's md4.c, replace by DP's
[xonotic/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 "generic/callback.h"
28 #include "generic/static.h"
29
30 class InitialiserList
31 {
32   typedef std::list<Callback> Initialisers;
33   Initialisers m_initialisers;
34   mutable bool m_initialised;
35 public:
36   InitialiserList() : m_initialised(false)
37   {
38   }
39   void addInitialiser(const Callback& callback)
40   {
41     m_initialisers.push_back(callback); 
42   }
43   void initialise() const
44   {
45     if(!m_initialised)
46     {
47       m_initialised = true;
48
49       for(Initialisers::const_iterator i = m_initialisers.begin(); i != m_initialisers.end(); ++i)
50       {
51         (*i)();
52       }
53     }
54   }
55 };
56
57 //--Type System-------------------
58
59 class TypeSystemInitialiser : public InitialiserList
60 {
61 };
62
63 typedef SmartStatic<TypeSystemInitialiser> StaticTypeSystemInitialiser;
64
65 class TypeSystemRef : public StaticTypeSystemInitialiser
66 {
67 public:
68   TypeSystemRef()
69   {
70     StaticTypeSystemInitialiser::instance().initialise();
71   }
72 };
73
74
75
76 typedef std::size_t TypeId;
77 typedef void*(*TypeCast)(void*);
78
79 template<std::size_t SIZE>
80 class TypeCastTable
81 {
82   TypeCast m_casts[SIZE];
83 public:
84   TypeCastTable()
85   {
86     std::uninitialized_fill(m_casts, m_casts + SIZE, TypeCast(0));
87   }
88   void install(TypeId typeId, TypeCast typeCast)
89   {
90     m_casts[typeId] = typeCast;
91   }
92   void* cast(TypeId typeId, void* p)
93   {
94     TypeCast typeCast = m_casts[typeId];
95     if(typeCast != 0)
96     {
97       return typeCast(p);
98     }
99     return 0;
100   }
101 };
102
103 template<typename Type, typename Cast>
104 class CastInstaller
105 {
106 public:
107   static void install(TypeCastTable<Type::SIZE>& table)
108   {
109     table.install(Type::getTypeId(), Cast::cast);
110   }
111 };
112
113 template<typename Type>
114 class IdentityCast
115 {
116 public:
117   static void* cast(void* p)
118   {
119     return p;
120   }
121 };
122
123 template<typename Type, typename Base>
124 class StaticCast
125 {
126 public:
127   static void* cast(void* p)
128   {
129     return static_cast<Base*>(reinterpret_cast<Type*>(p));
130   }
131 };
132
133 template<typename Type>
134 class NullType
135 {
136 };
137
138 template<typename Type, typename Contained>
139 class ContainedCast
140 {
141 public:
142   static void* cast(void* p)
143   {
144     return &reinterpret_cast<Type*>(p)->get(NullType<Contained>());
145   }
146 };
147
148
149 #endif