source: trunk/nv/types.hh @ 82

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

Another portion of bug-fixes (no namespaces)

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