source: trunk/nv/types.hh @ 55

Last change on this file since 55 was 55, checked in by epyon, 12 years ago
  • offset_of hack added if in future problems will arise
File size: 9.9 KB
Line 
1// Copyright (C) 2012 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#ifndef NV_TYPES_HH
6#define NV_TYPES_HH
7
8#include <glm/glm.hpp>
9#include <nv/common.hh>
10#include <type_traits>
11#include <utility>
12#include <unordered_map>
13#include <vector>
14#include <string>
15
16namespace nv
17{
18        enum type
19        {
20                INT,
21                BYTE,
22                SHORT,
23                UINT,
24                UBYTE,
25                USHORT,
26                FLOAT,
27                FLOAT_VECTOR_2,
28                FLOAT_VECTOR_3,
29                FLOAT_VECTOR_4,
30                FLOAT_MATRIX_2,
31                FLOAT_MATRIX_3,
32                FLOAT_MATRIX_4,
33                INT_VECTOR_2,
34                INT_VECTOR_3,
35                INT_VECTOR_4
36        };
37
38        typedef glm::vec2 vec2;
39        typedef glm::vec3 vec3;
40        typedef glm::vec4 vec4;
41
42        typedef glm::ivec2 ivec2;
43        typedef glm::ivec3 ivec3;
44        typedef glm::ivec4 ivec4;
45
46        typedef glm::mat2 mat2;
47        typedef glm::mat3 mat3;
48        typedef glm::mat4 mat4;
49
50        template < type EnumType > struct enum_to_type {};
51
52        template <> struct enum_to_type< INT >   { typedef int type; };
53        template <> struct enum_to_type< UINT >  { typedef unsigned int type; };
54        template <> struct enum_to_type< SHORT > { typedef short type; };
55        template <> struct enum_to_type< USHORT >{ typedef unsigned short type; };
56        template <> struct enum_to_type< BYTE >  { typedef char type; };
57        template <> struct enum_to_type< UBYTE > { typedef unsigned char type; };
58        template <> struct enum_to_type< FLOAT > { typedef f32 type; };
59
60        template <> struct enum_to_type< FLOAT_VECTOR_2 > { typedef vec2 type; };
61        template <> struct enum_to_type< FLOAT_VECTOR_3 > { typedef vec3 type; };
62        template <> struct enum_to_type< FLOAT_VECTOR_4 > { typedef vec4 type; };
63
64        template <> struct enum_to_type< INT_VECTOR_2 > { typedef ivec2 type; };
65        template <> struct enum_to_type< INT_VECTOR_3 > { typedef ivec3 type; };
66        template <> struct enum_to_type< INT_VECTOR_4 > { typedef ivec4 type; };
67
68        template <> struct enum_to_type< FLOAT_MATRIX_2 > { typedef mat2 type; };
69        template <> struct enum_to_type< FLOAT_MATRIX_3 > { typedef mat3 type; };
70        template <> struct enum_to_type< FLOAT_MATRIX_4 > { typedef mat4 type; };
71
72        template < typename TYPE > struct type_to_enum {};
73
74        template <> struct type_to_enum< int >           { static const type type = INT; };
75        template <> struct type_to_enum< unsigned int >  { static const type type = UINT; };
76        template <> struct type_to_enum< short >         { static const type type = SHORT; };
77        template <> struct type_to_enum< unsigned short >{ static const type type = USHORT; };
78        template <> struct type_to_enum< char >          { static const type type = BYTE; };
79        template <> struct type_to_enum< unsigned char > { static const type type = UBYTE; };
80        template <> struct type_to_enum< f32 > { static const type type = FLOAT; };
81
82        template <> struct type_to_enum< vec2 > { static const type type = FLOAT_VECTOR_2; };
83        template <> struct type_to_enum< vec3 > { static const type type = FLOAT_VECTOR_3; };
84        template <> struct type_to_enum< vec4 > { static const type type = FLOAT_VECTOR_4; };
85
86        template <> struct type_to_enum< ivec2 > { static const type type = INT_VECTOR_2; };
87        template <> struct type_to_enum< ivec3 > { static const type type = INT_VECTOR_3; };
88        template <> struct type_to_enum< ivec4 > { static const type type = INT_VECTOR_4; };
89
90        template <> struct type_to_enum< mat2 > { static const type type = FLOAT_MATRIX_2; };
91        template <> struct type_to_enum< mat3 > { static const type type = FLOAT_MATRIX_3; };
92        template <> struct type_to_enum< mat4 > { static const type type = FLOAT_MATRIX_4; };
93
94        template <typename TYPE>
95    inline const char* get_type_name()
96    {
97        static_assert< FALSE >( "Type not implemented!" );
98    }
99
100#define NV_REGISTER_NAME( s ) template <> inline const char* nv::get_type_name<s>   () { return #s; }
101
102        template <> inline const char* get_type_name<int>   () { return "sint"; }
103    template <> inline const char* get_type_name<sint8> () { return "sint8"; }
104    template <> inline const char* get_type_name<sint16>() { return "sint16"; }
105    template <> inline const char* get_type_name<sint32>() { return "sint32"; }
106    template <> inline const char* get_type_name<sint64>() { return "sint64"; }
107
108        template <> inline const char* get_type_name<unsigned int>() { return "uint"; }
109        template <> inline const char* get_type_name<uint8> ()       { return "uint8"; }
110    template <> inline const char* get_type_name<uint16>()       { return "uint16"; }
111    template <> inline const char* get_type_name<uint32>()       { return "uint32"; }
112    template <> inline const char* get_type_name<uint64>()       { return "uint64"; }
113
114        template <> inline const char* get_type_name<f32> () { return "f32"; }
115        template <> inline const char* get_type_name<f64> () { return "f64"; }
116
117        template <> inline const char* get_type_name< vec2 > () { return "vec2"; }
118        template <> inline const char* get_type_name< vec3 > () { return "vec3"; }
119        template <> inline const char* get_type_name< vec4 > () { return "vec4"; }
120
121        template <> inline const char* get_type_name< ivec2 > () { return "ivec2"; }
122        template <> inline const char* get_type_name< ivec3 > () { return "ivec3"; }
123        template <> inline const char* get_type_name< ivec4 > () { return "ivec4"; }
124
125        template <> inline const char* get_type_name< mat2 > () { return "mat2"; }
126        template <> inline const char* get_type_name< mat3 > () { return "mat3"; }
127        template <> inline const char* get_type_name< mat4 > () { return "mat4"; }
128
129        template <> inline const char* get_type_name<bool> () { return "bool"; }
130
131        template <> inline const char* get_type_name<std::string> () { return "string"; }
132
133        template <typename TYPE>
134    std::size_t get_type_id()
135    {
136        static std::size_t type_id = std::hash<std::string>()(std::string(get_type_name<TYPE>()));
137        return type_id;
138    };
139
140        struct hash_string
141    {
142        std::size_t hash;
143        const char* text;
144                hash_string() {}
145                hash_string( const char* a_text ) :
146                        text( a_text )
147                {
148                        hash = std::hash<std::string>()( std::string( a_text ) );
149                }
150                inline bool operator == (const hash_string& hs ) const
151                {
152                        return hs.hash == hash;
153                }
154    };
155
156}
157
158namespace std {
159        template<>
160        struct hash<nv::hash_string> {
161                size_t operator()(const nv::hash_string &hs) const
162                {
163                        return hs.hash;
164                }
165        };
166}
167
168namespace nv
169{
170        struct type_entry;
171
172        struct type_field
173        {
174                enum flags
175                {
176                        FPOINTER      = 0x01, //< field is a pointer
177                        FNOSERIALIZE  = 0x02, //< ignore during serialization
178                        FINVISIBLE    = 0x04, //< field invisible to API
179                        FREADONLY     = 0x08, //< read only field
180                        FSIMPLETYPE   = 0x10, //< raw binary I/O possible
181                        FOWNED        = 0x20,
182                };
183                hash_string  name;      //< name of the field
184                hash_string  type_name; //< name of the type of the field
185                type_entry*  type;      //< pointer to field type
186                unsigned int flags;     //< flags
187                size_t       offset;
188
189                template< typename TOBJECT, typename TFIELD>
190                type_field( hash_string name, TFIELD TOBJECT::*field )
191                        : name(name)
192                        , type_name( get_type_name< std::remove_pointer<TFIELD>::type >() )
193                        , type( nullptr )
194                        , flags( 0 )
195                        , offset( offsetof( TOBJECT, *field ) )
196                        // NOTE: if offsetof behaves badly, check offset_of in common.hh
197                {
198                        flags =
199                                ( std::is_pointer<TFIELD>::value ? FPOINTER : 0 ) |
200                                ( std::is_pod<TFIELD>::value ? FSIMPLETYPE : 0 );
201                }
202        };
203
204        struct type_enum
205        {
206                hash_string name;
207                int         value;
208                type_enum( hash_string name, int value ) : name(name), value(value) {}
209        };
210
211    struct type_entry
212    {
213                 // Function types for the constructor and destructor of registered types
214            typedef void (*constructor_func)(void*);
215            typedef void (*destructor_func)(void*);
216
217                // Parent type database
218        class type_database* type_db;
219
220        // Scoped C++ name of the type
221        hash_string name;
222 
223        // Pointers to the constructor and destructor functions
224        constructor_func constructor;
225        destructor_func  destructor;
226 
227        // Result of sizeof(type) operation
228        size_t size;
229
230                // Base type
231                type_entry* base_type;
232
233                // Field list
234                std::vector<type_field> field_list;
235
236                // Enum list
237                std::vector<type_enum> enum_list;
238
239                template <int TYPE>
240                type_entry& base()
241                {
242                        base_type = type_db->get_type( get_type_name<TYPE>() )
243                }
244
245                template <int SIZE>
246                type_entry& fields( type_field (&init_fields)[SIZE] )
247                {
248                        for (int i = 0; i < SIZE; i++)
249                        {
250                                type_field f = init_fields[i];
251                                f.type = type_db->get_type(f.type_name);
252                                field_list.push_back(f);
253                        }
254                        return *this;
255                }
256
257                template <int SIZE>
258                type_entry& enums( type_enum (&init_enums)[SIZE] )
259                {
260                        for (int i = 0; i < SIZE; i++)
261                        {
262                                enum_list.push_back( init_enums[i] )
263                        }
264                        return *this;
265                }
266    };
267
268    class type_database
269    {
270    public:
271                template< typename TYPE >
272        type_entry& create_type()
273                {
274                        hash_string name( get_type_name<TYPE>() );
275                        type_entry* i_type = nullptr;
276                        type_map::iterator it = m_types.find( name );
277                        if ( it != m_types.end() )
278                        {
279                                return *(it->second);
280                        }
281                        i_type          = new type_entry;
282                        i_type->type_db = this;
283                        i_type->name    = name;
284                        i_type->size    = sizeof(TYPE);
285                       
286                        i_type->constructor = ConstructObject<TYPE>;
287                        i_type->destructor  = DestructObject<TYPE>;
288
289                        m_types[name] = i_type;
290                        return *i_type;
291                }
292
293        type_entry* get_type( hash_string name )
294                {
295                        type_map::iterator it = m_types.find( name );
296                        if ( it != m_types.end() )
297                        {
298                                return it->second;
299                        }
300                        return nullptr;
301                }
302    private:
303        typedef std::unordered_map<hash_string, type_entry*> type_map;
304        type_map m_types;
305        };
306
307        template <typename TYPE> void ConstructObject(void* object)
308    {
309        // Use placement new to call the constructor
310        new (object) TYPE;
311    }
312    template <typename TYPE> void DestructObject(void* object)
313    {
314        // Explicit call of the destructor
315        ((TYPE*)object)->TYPE::~TYPE();
316    }
317
318}
319
320#endif NV_TYPES_HH
Note: See TracBrowser for help on using the repository browser.