source: trunk/nv/types.hh @ 83

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

Just removed all tabs with spaces, indentation is set to four. Nothing interesting here.

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<TFIELD::value_type>::value ? TF_POINTER : 0 ) |
198                ( std::is_pod<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.