source: trunk/nv/types.hh @ 63

Last change on this file since 63 was 63, checked in by melon, 12 years ago

Fixes some, but not all errors in types.hh

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