source: trunk/nv/types.hh @ 87

Last change on this file since 87 was 87, checked in by epyon, 12 years ago
  • compilation fix - should work now both under MSVC and GCC
File size: 10.7 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( offset_of( field ) )
194                {
195                        NV_LOG( LOG_INFO, name << "-" << offset);
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( offset_of( field ) )
209                {
210                        NV_LOG( LOG_INFO, name << "-" << offset);
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        class type_database
289        {
290        public:
291                template< typename TYPE >
292                type_entry& create_type( const char* name )
293                {
294                        type_entry* i_type = nullptr;
295                        type_name_map::iterator it = m_name_types.find( name );
296                        if ( it != m_name_types.end() )
297                        {
298                                return *(it->second);
299                        }
300                        i_type          = new type_entry;
301                        i_type->type_db = this;
302                        i_type->name    = name;
303                        i_type->size    = sizeof(TYPE);
304
305                        i_type->constructor = ConstructObject<TYPE>;
306                        i_type->destructor  = DestructObject<TYPE>;
307
308                        m_name_types[name]        = i_type;
309                        m_idx_types[typeid(TYPE)] = i_type;
310                        return *i_type;
311                }
312
313                type_entry* get_type( const std::string name )
314                {
315                        type_name_map::iterator it = m_name_types.find( name );
316                        if ( it != m_name_types.end() )
317                        {
318                                return it->second;
319                        }
320                        return nullptr;
321                }
322
323                type_entry* get_type( const std::type_info& t )
324                {
325                        type_info_map::iterator it = m_idx_types.find( std::type_index(t) );
326                        if ( it != m_idx_types.end() )
327                        {
328                                return it->second;
329                        }
330                        return nullptr;
331                }
332        private:
333                struct compare_type_info {
334                        bool operator ()(const std::type_info* a, const std::type_info* b) const {
335                                return a->before(*b);
336                        }
337                };
338
339                typedef std::unordered_map<std::string, type_entry*>     type_name_map;
340                typedef std::unordered_map<std::type_index, type_entry*> type_info_map;
341                type_name_map m_name_types;
342                type_info_map m_idx_types;
343        };
344
345        template <typename TYPE> void ConstructObject(void* object)
346        {
347                // Use placement new to call the constructor
348                new (object) TYPE;
349        }
350        template <typename TYPE> void DestructObject(void* object)
351        {
352                // Explicit call of the destructor
353                ((TYPE*)object)->TYPE::~TYPE();
354        }
355
356}
357
358#endif
359
Note: See TracBrowser for help on using the repository browser.