source: trunk/nv/types.hh @ 84

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

Another portion of bugfixes. Missing typename...

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