source: trunk/nv/types.hh @ 77

Last change on this file since 77 was 77, checked in by epyon, 12 years ago
  • types - typemap based on type_index, allowing type retrival by typeid
  • object - autoinitialization of uid and lua_index, based on root's capabilities
  • object - proper cleanup of uid and lua_index
  • object - root accessor
  • lua_state - implementation of register_object and unregister_object
File size: 13.9 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
19#define NV_REGISTER_NAME( s ) template <> inline const char* nv::get_type_name<s>   () { return #s; }
20
21namespace nv
22{
23
24        enum datatype
25        {
26                INT,
27                BYTE,
28                SHORT,
29                UINT,
30                UBYTE,
31                USHORT,
32                FLOAT,
33                FLOAT_VECTOR_2,
34                FLOAT_VECTOR_3,
35                FLOAT_VECTOR_4,
36                FLOAT_MATRIX_2,
37                FLOAT_MATRIX_3,
38                FLOAT_MATRIX_4,
39                INT_VECTOR_2,
40                INT_VECTOR_3,
41                INT_VECTOR_4,
42                // unsupported gl conversion, remove?
43                BYTE_VECTOR_2,
44                BYTE_VECTOR_3,
45                BYTE_VECTOR_4,
46        };
47
48        template <typename T>
49        struct datatype_traits
50        {
51                typedef T type;
52                typedef T base_type;
53                static const size_t size = 1;
54        };
55
56        template <typename T>
57        struct datatype_traits< glm::detail::tvec2<T> >
58        {
59                typedef glm::detail::tvec2<T> type;
60                typedef typename type::value_type base_type;
61                static const size_t size = 2;
62        };
63
64        template <typename T>
65        struct datatype_traits< glm::detail::tvec3<T> >
66        {
67                typedef glm::detail::tvec3<T> type;
68                typedef typename type::value_type base_type;
69                static const size_t size = 3;
70        };
71
72        template <typename T>
73        struct datatype_traits< glm::detail::tvec4<T> >
74        {
75                typedef glm::detail::tvec4<T> type;
76                typedef typename type::value_type base_type;
77                static const size_t size = 4;
78        };
79
80        typedef glm::detail::tvec2<sint8> i8vec2;
81        typedef glm::detail::tvec3<sint8> i8vec3;
82        typedef glm::detail::tvec4<sint8> i8vec4;
83
84        typedef glm::vec2 vec2;
85        typedef glm::vec3 vec3;
86        typedef glm::vec4 vec4;
87
88        typedef glm::ivec2 ivec2;
89        typedef glm::ivec3 ivec3;
90        typedef glm::ivec4 ivec4;
91
92        typedef glm::mat2 mat2;
93        typedef glm::mat3 mat3;
94        typedef glm::mat4 mat4;
95
96        template < datatype EnumType > struct enum_to_type {};
97
98        template <> struct enum_to_type< INT >   { typedef int type; };
99        template <> struct enum_to_type< UINT >  { typedef unsigned int type; };
100        template <> struct enum_to_type< SHORT > { typedef short type; };
101        template <> struct enum_to_type< USHORT >{ typedef unsigned short type; };
102        template <> struct enum_to_type< BYTE >  { typedef char type; };
103        template <> struct enum_to_type< UBYTE > { typedef unsigned char type; };
104        template <> struct enum_to_type< FLOAT > { typedef f32 type; };
105
106        template <> struct enum_to_type< FLOAT_VECTOR_2 > { typedef vec2 type; };
107        template <> struct enum_to_type< FLOAT_VECTOR_3 > { typedef vec3 type; };
108        template <> struct enum_to_type< FLOAT_VECTOR_4 > { typedef vec4 type; };
109
110        template <> struct enum_to_type< INT_VECTOR_2 > { typedef ivec2 type; };
111        template <> struct enum_to_type< INT_VECTOR_3 > { typedef ivec3 type; };
112        template <> struct enum_to_type< INT_VECTOR_4 > { typedef ivec4 type; };
113
114        template <> struct enum_to_type< BYTE_VECTOR_2 > { typedef i8vec2 type; };
115        template <> struct enum_to_type< BYTE_VECTOR_3 > { typedef i8vec3 type; };
116        template <> struct enum_to_type< BYTE_VECTOR_4 > { typedef i8vec4 type; };
117
118        template <> struct enum_to_type< FLOAT_MATRIX_2 > { typedef mat2 type; };
119        template <> struct enum_to_type< FLOAT_MATRIX_3 > { typedef mat3 type; };
120        template <> struct enum_to_type< FLOAT_MATRIX_4 > { typedef mat4 type; };
121
122        template < typename TYPE > struct type_to_enum {};
123
124        template <> struct type_to_enum< int >           { static const datatype type = INT; };
125        template <> struct type_to_enum< unsigned int >  { static const datatype type = UINT; };
126        template <> struct type_to_enum< short >         { static const datatype type = SHORT; };
127        template <> struct type_to_enum< unsigned short >{ static const datatype type = USHORT; };
128        template <> struct type_to_enum< char >          { static const datatype type = BYTE; };
129        template <> struct type_to_enum< signed char >   { static const datatype type = BYTE; };
130        template <> struct type_to_enum< unsigned char > { static const datatype type = UBYTE; };
131        template <> struct type_to_enum< f32 > { static const datatype type = FLOAT; };
132
133        template <> struct type_to_enum< vec2 > { static const datatype type = FLOAT_VECTOR_2; };
134        template <> struct type_to_enum< vec3 > { static const datatype type = FLOAT_VECTOR_3; };
135        template <> struct type_to_enum< vec4 > { static const datatype type = FLOAT_VECTOR_4; };
136
137        template <> struct type_to_enum< ivec2 > { static const datatype type = INT_VECTOR_2; };
138        template <> struct type_to_enum< ivec3 > { static const datatype type = INT_VECTOR_3; };
139        template <> struct type_to_enum< ivec4 > { static const datatype type = INT_VECTOR_4; };
140
141        template <> struct type_to_enum< i8vec2 > { static const datatype type = BYTE_VECTOR_2; };
142        template <> struct type_to_enum< i8vec3 > { static const datatype type = BYTE_VECTOR_3; };
143        template <> struct type_to_enum< i8vec4 > { static const datatype type = BYTE_VECTOR_4; };
144
145        template <> struct type_to_enum< mat2 > { static const datatype type = FLOAT_MATRIX_2; };
146        template <> struct type_to_enum< mat3 > { static const datatype type = FLOAT_MATRIX_3; };
147        template <> struct type_to_enum< mat4 > { static const datatype type = FLOAT_MATRIX_4; };
148
149        template <typename TYPE>
150    inline const char* get_type_name()
151    {
152        static_assert(sizeof(TYPE) == 0, "Type not implemented!");
153        return NULL;
154    }
155
156        template <> inline const char* get_type_name<int>   () { return "sint"; }
157    template <> inline const char* get_type_name<sint8> () { return "sint8"; }
158    template <> inline const char* get_type_name<sint16>() { return "sint16"; }
159    template <> inline const char* get_type_name<sint32>() { return "sint32"; }
160    template <> inline const char* get_type_name<sint64>() { return "sint64"; }
161
162        template <> inline const char* get_type_name<unsigned int>() { return "uint"; }
163        template <> inline const char* get_type_name<uint8> ()       { return "uint8"; }
164    template <> inline const char* get_type_name<uint16>()       { return "uint16"; }
165    template <> inline const char* get_type_name<uint32>()       { return "uint32"; }
166    template <> inline const char* get_type_name<uint64>()       { return "uint64"; }
167
168        template <> inline const char* get_type_name<f32> () { return "f32"; }
169        template <> inline const char* get_type_name<f64> () { return "f64"; }
170
171        template <> inline const char* get_type_name< vec2 > () { return "vec2"; }
172        template <> inline const char* get_type_name< vec3 > () { return "vec3"; }
173        template <> inline const char* get_type_name< vec4 > () { return "vec4"; }
174
175        template <> inline const char* get_type_name< ivec2 > () { return "ivec2"; }
176        template <> inline const char* get_type_name< ivec3 > () { return "ivec3"; }
177        template <> inline const char* get_type_name< ivec4 > () { return "ivec4"; }
178
179        template <> inline const char* get_type_name< i8vec2 > () { return "i8vec2"; }
180        template <> inline const char* get_type_name< i8vec3 > () { return "i8vec3"; }
181        template <> inline const char* get_type_name< i8vec4 > () { return "i8vec4"; }
182
183        template <> inline const char* get_type_name< mat2 > () { return "mat2"; }
184        template <> inline const char* get_type_name< mat3 > () { return "mat3"; }
185        template <> inline const char* get_type_name< mat4 > () { return "mat4"; }
186
187        template <> inline const char* get_type_name<bool> () { return "bool"; }
188
189        template <> inline const char* get_type_name<std::string> () { return "string"; }
190        template <> inline const char* get_type_name<object>      () { return "object"; }
191
192        template<typename T>
193        struct is_container
194        {
195        private:
196                typedef char                      yes;
197                typedef struct { char array[2]; } no;
198                template<typename C> static yes test(typename C::iterator*);
199                template<typename C> static no  test(...);
200        public:
201                static const bool value = sizeof(test<T>(0)) == sizeof(yes);
202        };
203
204        template<>
205        struct is_container< std::string > {
206                static const bool value = false;
207        };
208
209
210        template <typename TYPE>
211    std::size_t get_type_id()
212    {
213        static std::size_t type_id = std::hash<std::string>()(std::string(get_type_name<TYPE>()));
214        return type_id;
215    };
216
217        struct hash_string
218    {
219        std::size_t hash;
220        const char* text;
221                hash_string() {}
222                hash_string( const char* a_text ) :
223                        text( a_text )
224                {
225                        hash = std::hash<std::string>()( std::string( a_text ) );
226                }
227                inline bool operator == (const hash_string& hs ) const
228                {
229                        return hs.hash == hash;
230                }
231    };
232
233}
234
235namespace std {
236        template<>
237        struct hash<nv::hash_string> {
238                size_t operator()(const nv::hash_string &hs) const
239                {
240                        return hs.hash;
241                }
242        };
243}
244
245namespace nv
246{
247        struct type_entry;
248
249        enum type_flag
250        {
251                TF_POINTER      = 0x01, //< field is a pointer
252                TF_NOSERIALIZE  = 0x02, //< ignore during serialization
253                TF_INVISIBLE    = 0x04, //< field invisible to API
254                TF_READONLY     = 0x08, //< read only field
255                TF_SIMPLETYPE   = 0x10, //< raw binary I/O possible
256                TF_OWNED        = 0x20,
257                TF_CONTAINER    = 0x40, //< is a container
258        };
259
260        struct type_field
261        {
262                hash_string  name;      //< name of the field
263                hash_string  type_name; //< name of the type of the field
264                type_entry*  type;      //< pointer to field type
265                unsigned int flags;     //< flags
266                size_t       offset;
267
268                template< typename TOBJECT, typename TFIELD >
269                type_field( hash_string name, TFIELD TOBJECT::*field, typename std::enable_if< is_container<TFIELD>::value, void* >::type = nullptr )
270                        : name(name)
271                        , type_name( get_type_name< std::remove_pointer<typename TFIELD::value_type>::type >() )
272                        , type( nullptr )
273                        , flags( 0 )
274                        , offset( offsetof( TOBJECT, *field ) )
275                        // NOTE: if offsetof behaves badly, check offset_of in common.hh
276                {
277                        flags = TF_CONTAINER |
278                                ( std::is_pointer<TFIELD::value_type>::value ? TF_POINTER : 0 ) |
279                                ( std::is_pod<TFIELD::value_type>::value ? TF_SIMPLETYPE : 0 );
280                }
281
282                template< typename TOBJECT, typename TFIELD >
283                type_field( hash_string name, TFIELD TOBJECT::*field, typename std::enable_if< !is_container<TFIELD>::value, void* >::type = nullptr )
284                        : name(name)
285                        , type_name( get_type_name< std::remove_pointer<TFIELD>::type >() )
286                        , type( nullptr )
287                        , flags( 0 )
288                        , offset( offsetof( TOBJECT, *field ) )
289                        // NOTE: if offsetof behaves badly, check offset_of in common.hh
290                {
291                        flags =
292                                ( std::is_pointer<TFIELD>::value ? TF_POINTER : 0 ) |
293                                ( std::is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 );
294                }
295
296                type_field& flag( unsigned int f )
297                {
298                        flags |= f;
299                        return *this;
300                }
301        };
302
303        struct type_enum
304        {
305                hash_string name;
306                int         value;
307                type_enum( hash_string name, int value ) : name(name), value(value) {}
308        };
309
310    struct type_entry
311    {
312                 // Function types for the constructor and destructor of registered types
313            typedef void (*constructor_func)(void*);
314            typedef void (*destructor_func)(void*);
315
316                // Parent type database
317        class type_database* type_db;
318
319        // Scoped C++ name of the type
320        hash_string name;
321 
322        // Pointers to the constructor and destructor functions
323        constructor_func constructor;
324        destructor_func  destructor;
325 
326        // Result of sizeof(type) operation
327        size_t size;
328
329                // Base type
330                type_entry* base_type;
331
332                // Field list
333                std::vector<type_field> field_list;
334
335                // Enum list
336                std::vector<type_enum> enum_list;
337
338                template <int TYPE>
339                type_entry& base()
340                {
341                        base_type = type_db->get_type( get_type_name<TYPE>() )
342                }
343
344                template <int SIZE>
345                type_entry& fields( type_field (&init_fields)[SIZE] )
346                {
347                        for (int i = 0; i < SIZE; i++)
348                        {
349                                type_field f = init_fields[i];
350                                f.type = type_db->get_type(f.type_name);
351                                field_list.push_back(f);
352                        }
353                        return *this;
354                }
355
356                template <int SIZE>
357                type_entry& enums( type_enum (&init_enums)[SIZE] )
358                {
359                        for (int i = 0; i < SIZE; i++)
360                        {
361                                enum_list.push_back( init_enums[i] );
362                        }
363                        return *this;
364                }
365    };
366
367        // TODO: we don't need the get_type_name template? Can we just base on typeid now, and
368        //       pass type name on creation?
369    class type_database
370    {
371    public:
372                template< typename TYPE >
373        type_entry& create_type()
374                {
375                        hash_string name( get_type_name<TYPE>() );
376                        type_entry* i_type = nullptr;
377                        type_map::iterator it = m_types.find( name );
378                        if ( it != m_types.end() )
379                        {
380                                return *(it->second);
381                        }
382                        i_type          = new type_entry;
383                        i_type->type_db = this;
384                        i_type->name    = name;
385                        i_type->size    = sizeof(TYPE);
386                       
387                        i_type->constructor = ConstructObject<TYPE>;
388                        i_type->destructor  = DestructObject<TYPE>;
389
390                        m_types[name]             = i_type;
391                        m_idx_types[typeid(TYPE)] = i_type;
392                        return *i_type;
393                }
394                // TODO: delete?
395        type_entry* get_type( hash_string name )
396                {
397                        type_map::iterator it = m_types.find( name );
398                        if ( it != m_types.end() )
399                        {
400                                return it->second;
401                        }
402                        return nullptr;
403                }
404                type_entry* get_type( const type_info& t )
405                {
406                        type_info_map::iterator it = m_idx_types.find( std::type_index(t) );
407                        if ( it != m_idx_types.end() )
408                        {
409                                return it->second;
410                        }
411                        return nullptr;
412                }
413    private:
414                struct compare_type_info {
415                        bool operator ()(const type_info* a, const type_info* b) const {
416                                return a->before(*b);
417                        }
418                };
419
420        typedef std::unordered_map<hash_string, type_entry*>     type_map;
421                typedef std::unordered_map<std::type_index, type_entry*> type_info_map;
422        type_map      m_types;
423                type_info_map m_idx_types;
424        };
425
426        template <typename TYPE> void ConstructObject(void* object)
427    {
428        // Use placement new to call the constructor
429        new (object) TYPE;
430    }
431    template <typename TYPE> void DestructObject(void* object)
432    {
433        // Explicit call of the destructor
434        ((TYPE*)object)->TYPE::~TYPE();
435    }
436
437}
438
439#endif
440
Note: See TracBrowser for help on using the repository browser.