source: trunk/nv/types.hh @ 72

Last change on this file since 72 was 72, checked in by epyon, 12 years ago
  • etype_traits -> datatype_traits
File size: 13.2 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 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 TYPE>
148    inline const char* get_type_name()
149    {
150        static_assert(sizeof(TYPE) == 0, "Type not implemented!");
151        return NULL;
152    }
153
154        template <> inline const char* get_type_name<int>   () { return "sint"; }
155    template <> inline const char* get_type_name<sint8> () { return "sint8"; }
156    template <> inline const char* get_type_name<sint16>() { return "sint16"; }
157    template <> inline const char* get_type_name<sint32>() { return "sint32"; }
158    template <> inline const char* get_type_name<sint64>() { return "sint64"; }
159
160        template <> inline const char* get_type_name<unsigned int>() { return "uint"; }
161        template <> inline const char* get_type_name<uint8> ()       { return "uint8"; }
162    template <> inline const char* get_type_name<uint16>()       { return "uint16"; }
163    template <> inline const char* get_type_name<uint32>()       { return "uint32"; }
164    template <> inline const char* get_type_name<uint64>()       { return "uint64"; }
165
166        template <> inline const char* get_type_name<f32> () { return "f32"; }
167        template <> inline const char* get_type_name<f64> () { return "f64"; }
168
169        template <> inline const char* get_type_name< vec2 > () { return "vec2"; }
170        template <> inline const char* get_type_name< vec3 > () { return "vec3"; }
171        template <> inline const char* get_type_name< vec4 > () { return "vec4"; }
172
173        template <> inline const char* get_type_name< ivec2 > () { return "ivec2"; }
174        template <> inline const char* get_type_name< ivec3 > () { return "ivec3"; }
175        template <> inline const char* get_type_name< ivec4 > () { return "ivec4"; }
176
177        template <> inline const char* get_type_name< i8vec2 > () { return "i8vec2"; }
178        template <> inline const char* get_type_name< i8vec3 > () { return "i8vec3"; }
179        template <> inline const char* get_type_name< i8vec4 > () { return "i8vec4"; }
180
181        template <> inline const char* get_type_name< mat2 > () { return "mat2"; }
182        template <> inline const char* get_type_name< mat3 > () { return "mat3"; }
183        template <> inline const char* get_type_name< mat4 > () { return "mat4"; }
184
185        template <> inline const char* get_type_name<bool> () { return "bool"; }
186
187        template <> inline const char* get_type_name<std::string> () { return "string"; }
188        template <> inline const char* get_type_name<object>      () { return "object"; }
189
190        template<typename T>
191        struct is_container
192        {
193        private:
194                typedef char                      yes;
195                typedef struct { char array[2]; } no;
196                template<typename C> static yes test(typename C::iterator*);
197                template<typename C> static no  test(...);
198        public:
199                static const bool value = sizeof(test<T>(0)) == sizeof(yes);
200        };
201
202        template<>
203        struct is_container< std::string > {
204                static const bool value = false;
205        };
206
207
208        template <typename TYPE>
209    std::size_t get_type_id()
210    {
211        static std::size_t type_id = std::hash<std::string>()(std::string(get_type_name<TYPE>()));
212        return type_id;
213    };
214
215        struct hash_string
216    {
217        std::size_t hash;
218        const char* text;
219                hash_string() {}
220                hash_string( const char* a_text ) :
221                        text( a_text )
222                {
223                        hash = std::hash<std::string>()( std::string( a_text ) );
224                }
225                inline bool operator == (const hash_string& hs ) const
226                {
227                        return hs.hash == hash;
228                }
229    };
230
231}
232
233namespace std {
234        template<>
235        struct hash<nv::hash_string> {
236                size_t operator()(const nv::hash_string &hs) const
237                {
238                        return hs.hash;
239                }
240        };
241}
242
243namespace nv
244{
245        struct type_entry;
246
247        enum type_flag
248        {
249                TF_POINTER      = 0x01, //< field is a pointer
250                TF_NOSERIALIZE  = 0x02, //< ignore during serialization
251                TF_INVISIBLE    = 0x04, //< field invisible to API
252                TF_READONLY     = 0x08, //< read only field
253                TF_SIMPLETYPE   = 0x10, //< raw binary I/O possible
254                TF_OWNED        = 0x20,
255                TF_CONTAINER    = 0x40, //< is a container
256        };
257
258        struct type_field
259        {
260                hash_string  name;      //< name of the field
261                hash_string  type_name; //< name of the type of the field
262                type_entry*  type;      //< pointer to field type
263                unsigned int flags;     //< flags
264                size_t       offset;
265
266                template< typename TOBJECT, typename TFIELD >
267                type_field( hash_string name, TFIELD TOBJECT::*field, typename std::enable_if< is_container<TFIELD>::value, void* >::type = nullptr )
268                        : name(name)
269                        , type_name( get_type_name< std::remove_pointer<typename TFIELD::value_type>::type >() )
270                        , type( nullptr )
271                        , flags( 0 )
272                        , offset( offsetof( TOBJECT, *field ) )
273                        // NOTE: if offsetof behaves badly, check offset_of in common.hh
274                {
275                        flags = TF_CONTAINER |
276                                ( std::is_pointer<TFIELD::value_type>::value ? TF_POINTER : 0 ) |
277                                ( std::is_pod<TFIELD::value_type>::value ? TF_SIMPLETYPE : 0 );
278                }
279
280                template< typename TOBJECT, typename TFIELD >
281                type_field( hash_string name, TFIELD TOBJECT::*field, typename std::enable_if< !is_container<TFIELD>::value, void* >::type = nullptr )
282                        : name(name)
283                        , type_name( get_type_name< std::remove_pointer<TFIELD>::type >() )
284                        , type( nullptr )
285                        , flags( 0 )
286                        , offset( offsetof( TOBJECT, *field ) )
287                        // NOTE: if offsetof behaves badly, check offset_of in common.hh
288                {
289                        flags =
290                                ( std::is_pointer<TFIELD>::value ? TF_POINTER : 0 ) |
291                                ( std::is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 );
292                }
293
294                type_field& flag( unsigned int f )
295                {
296                        flags |= f;
297                        return *this;
298                }
299        };
300
301        struct type_enum
302        {
303                hash_string name;
304                int         value;
305                type_enum( hash_string name, int value ) : name(name), value(value) {}
306        };
307
308    struct type_entry
309    {
310                 // Function types for the constructor and destructor of registered types
311            typedef void (*constructor_func)(void*);
312            typedef void (*destructor_func)(void*);
313
314                // Parent type database
315        class type_database* type_db;
316
317        // Scoped C++ name of the type
318        hash_string name;
319 
320        // Pointers to the constructor and destructor functions
321        constructor_func constructor;
322        destructor_func  destructor;
323 
324        // Result of sizeof(type) operation
325        size_t size;
326
327                // Base type
328                type_entry* base_type;
329
330                // Field list
331                std::vector<type_field> field_list;
332
333                // Enum list
334                std::vector<type_enum> enum_list;
335
336                template <int TYPE>
337                type_entry& base()
338                {
339                        base_type = type_db->get_type( get_type_name<TYPE>() )
340                }
341
342                template <int SIZE>
343                type_entry& fields( type_field (&init_fields)[SIZE] )
344                {
345                        for (int i = 0; i < SIZE; i++)
346                        {
347                                type_field f = init_fields[i];
348                                f.type = type_db->get_type(f.type_name);
349                                field_list.push_back(f);
350                        }
351                        return *this;
352                }
353
354                template <int SIZE>
355                type_entry& enums( type_enum (&init_enums)[SIZE] )
356                {
357                        for (int i = 0; i < SIZE; i++)
358                        {
359                                enum_list.push_back( init_enums[i] );
360                        }
361                        return *this;
362                }
363    };
364
365    class type_database
366    {
367    public:
368                template< typename TYPE >
369        type_entry& create_type()
370                {
371                        hash_string name( get_type_name<TYPE>() );
372                        type_entry* i_type = nullptr;
373                        type_map::iterator it = m_types.find( name );
374                        if ( it != m_types.end() )
375                        {
376                                return *(it->second);
377                        }
378                        i_type          = new type_entry;
379                        i_type->type_db = this;
380                        i_type->name    = name;
381                        i_type->size    = sizeof(TYPE);
382                       
383                        i_type->constructor = ConstructObject<TYPE>;
384                        i_type->destructor  = DestructObject<TYPE>;
385
386                        m_types[name] = i_type;
387                        return *i_type;
388                }
389
390        type_entry* get_type( hash_string name )
391                {
392                        type_map::iterator it = m_types.find( name );
393                        if ( it != m_types.end() )
394                        {
395                                return it->second;
396                        }
397                        return nullptr;
398                }
399    private:
400        typedef std::unordered_map<hash_string, type_entry*> type_map;
401        type_map m_types;
402        };
403
404        template <typename TYPE> void ConstructObject(void* object)
405    {
406        // Use placement new to call the constructor
407        new (object) TYPE;
408    }
409    template <typename TYPE> void DestructObject(void* object)
410    {
411        // Explicit call of the destructor
412        ((TYPE*)object)->TYPE::~TYPE();
413    }
414
415}
416
417#endif
418
Note: See TracBrowser for help on using the repository browser.