source: trunk/nv/types.hh @ 190

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