source: trunk/nv/types.hh @ 121

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