source: trunk/nv/types.hh @ 68

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