]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_traits.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_traits.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_traits.h
28 #pragma once
29
30 #include "vogl_core.h"
31
32 namespace vogl
33 {
34     template <typename T>
35     struct int_traits
36     {
37         enum
38         {
39             cMin = vogl::cINT32_MIN,
40             cMax = vogl::cINT32_MAX,
41             cSigned = true
42         };
43     };
44
45     template <>
46     struct int_traits<int8>
47     {
48         enum
49         {
50             cMin = vogl::cINT8_MIN,
51             cMax = vogl::cINT8_MAX,
52             cSigned = true
53         };
54     };
55     template <>
56     struct int_traits<int16>
57     {
58         enum
59         {
60             cMin = vogl::cINT16_MIN,
61             cMax = vogl::cINT16_MAX,
62             cSigned = true
63         };
64     };
65     template <>
66     struct int_traits<int32>
67     {
68         enum
69         {
70             cMin = vogl::cINT32_MIN,
71             cMax = vogl::cINT32_MAX,
72             cSigned = true
73         };
74     };
75
76     template <>
77     struct int_traits<uint8>
78     {
79         enum
80         {
81             cMin = 0,
82             cMax = vogl::cUINT8_MAX,
83             cSigned = false
84         };
85     };
86     template <>
87     struct int_traits<uint16>
88     {
89         enum
90         {
91             cMin = 0,
92             cMax = vogl::cUINT16_MAX,
93             cSigned = false
94         };
95     };
96     template <>
97     struct int_traits<uint32>
98     {
99         enum
100         {
101             cMin = 0,
102             cMax = vogl::cUINT32_MAX,
103             cSigned = false
104         };
105     };
106
107     // scalar_type<T>::construct, construct_array, etc. ensures integral types are initialized to 0 when constructed
108     template <typename T>
109     struct scalar_type
110     {
111         enum
112         {
113             cFlag = false
114         };
115         static inline void construct(T *p)
116         {
117             helpers::construct(p);
118         }
119         static inline void construct(T *p, const T &init)
120         {
121             helpers::construct(p, init);
122         }
123         static inline void construct_array(T *p, uint n)
124         {
125             helpers::construct_array(p, n);
126         }
127         static inline void destruct(T *p)
128         {
129             helpers::destruct(p);
130         }
131         static inline void destruct_array(T *p, uint n)
132         {
133             helpers::destruct_array(p, n);
134         }
135     };
136
137     template <typename T>
138     struct scalar_type<T *>
139     {
140         enum
141         {
142             cFlag = true
143         };
144         static inline void construct(T **p)
145         {
146             memset(p, 0, sizeof(T *));
147         }
148         static inline void construct(T **p, T *init)
149         {
150             *p = init;
151         }
152         static inline void construct_array(T **p, uint n)
153         {
154             memset(p, 0, sizeof(T *) * n);
155         }
156         static inline void destruct(T **p)
157         {
158             VOGL_NOTE_UNUSED(p);
159         }
160         static inline void destruct_array(T **p, uint n)
161         {
162             VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n);
163         }
164     };
165
166 #define VOGL_DEFINE_BUILT_IN_TYPE(X)                    \
167     template <> struct scalar_type<X>                     \
168     {                                                     \
169         enum { cFlag = true };                            \
170         static inline void construct(X *p)                \
171         {                                                 \
172             memset(p, 0, sizeof(X));                      \
173         }                                                 \
174         static inline void construct(X *p, const X &init) \
175         {                                                 \
176             memcpy(p, &init, sizeof(X));                  \
177         }                                                 \
178         static inline void construct_array(X *p, uint n)  \
179         {                                                 \
180             memset(p, 0, sizeof(X) * n);                  \
181         }                                                 \
182         static inline void destruct(X *p)                 \
183         {                                                 \
184             VOGL_NOTE_UNUSED(p);                        \
185         }                                                 \
186         static inline void destruct_array(X *p, uint n)   \
187         {                                                 \
188             VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n); \
189         }                                                 \
190     };
191
192     VOGL_DEFINE_BUILT_IN_TYPE(bool)
193     VOGL_DEFINE_BUILT_IN_TYPE(char)
194     VOGL_DEFINE_BUILT_IN_TYPE(unsigned char)
195     VOGL_DEFINE_BUILT_IN_TYPE(short)
196     VOGL_DEFINE_BUILT_IN_TYPE(unsigned short)
197     VOGL_DEFINE_BUILT_IN_TYPE(int)
198     VOGL_DEFINE_BUILT_IN_TYPE(unsigned int)
199     VOGL_DEFINE_BUILT_IN_TYPE(long)
200     VOGL_DEFINE_BUILT_IN_TYPE(unsigned long)
201 #ifdef __GNUC__
202     VOGL_DEFINE_BUILT_IN_TYPE(long long)
203     VOGL_DEFINE_BUILT_IN_TYPE(unsigned long long)
204 #else
205     VOGL_DEFINE_BUILT_IN_TYPE(__int64)
206     VOGL_DEFINE_BUILT_IN_TYPE(unsigned __int64)
207 #endif
208     VOGL_DEFINE_BUILT_IN_TYPE(float)
209     VOGL_DEFINE_BUILT_IN_TYPE(double)
210     VOGL_DEFINE_BUILT_IN_TYPE(long double)
211
212 #undef VOGL_DEFINE_BUILT_IN_TYPE
213
214     // See: http://erdani.org/publications/cuj-2004-06.pdf
215
216     template <typename T>
217     struct bitwise_movable
218     {
219         enum
220         {
221             cFlag = false
222         };
223     };
224
225 // Defines type Q as bitwise movable. Use with types requiring destruction. DO NOT use with types that contain pointers into themselves.
226 // Bitwise movable: type T may be safely moved to a new location via memcpy, without requiring the old copy to be destructed.
227 // However, the final version of the object (wherever it winds up in memory) must be eventually destructed (a single time, of course).
228 // Bitwise movable is a superset of bitwise copyable (all bitwise copyable types are also bitwise movable).
229 #define VOGL_DEFINE_BITWISE_MOVABLE(Q)  \
230     template <> struct bitwise_movable<Q> \
231     {                                     \
232         enum { cFlag = true };            \
233     };
234
235     template <typename T>
236     struct bitwise_copyable
237     {
238         enum
239         {
240             cFlag = false
241         };
242     };
243
244 // Defines type Q as bitwise copyable. This is NOT SAFE for use with types that require destruction. DO NOT use with types that contain pointers into themselves.
245 // Bitwise copyable: type T may be safely and freely copied (duplicated) via memcpy, and *does not* require destruction.
246 #define VOGL_DEFINE_BITWISE_COPYABLE(Q)  \
247     template <> struct bitwise_copyable<Q> \
248     {                                      \
249         enum { cFlag = true };             \
250     };
251
252 #define VOGL_IS_POD(T) __is_pod(T)
253
254 #define VOGL_IS_SCALAR_TYPE(T) (scalar_type<T>::cFlag)
255
256 #define VOGL_IS_BITWISE_COPYABLE(T) (VOGL_IS_SCALAR_TYPE(T) || VOGL_IS_POD(T) || (bitwise_copyable<T>::cFlag))
257
258 #define VOGL_IS_BITWISE_COPYABLE_OR_MOVABLE(T) (VOGL_IS_BITWISE_COPYABLE(T) || (bitwise_movable<T>::cFlag))
259
260 #define VOGL_HAS_DESTRUCTOR(T) ((!scalar_type<T>::cFlag) && (!__is_pod(T)))
261
262     // From yasli_traits.h:
263     // Credit goes to Boost;
264     // also found in the C++ Templates book by Vandevoorde and Josuttis
265
266     typedef char (&yes_t)[1];
267     typedef char (&no_t)[2];
268
269     template <class U>
270     yes_t class_test(int U::*);
271     template <class U>
272     no_t class_test(...);
273
274     template <class T>
275     struct is_class
276     {
277         enum
278         {
279             value = (sizeof(class_test<T>(0)) == sizeof(yes_t))
280         };
281     };
282
283     template <typename T>
284     struct is_pointer
285     {
286         enum
287         {
288             value = false
289         };
290     };
291
292     template <typename T>
293     struct is_pointer<T *>
294     {
295         enum
296         {
297             value = true
298         };
299     };
300
301     VOGL_DEFINE_BITWISE_COPYABLE(empty_type);
302     VOGL_DEFINE_BITWISE_MOVABLE(empty_type);
303
304     namespace helpers
305     {
306         // dst must be uninitialized memory, src will be destructed
307         template <typename T>
308         inline void move(T &dst, T &src)
309         {
310             if (VOGL_IS_BITWISE_COPYABLE_OR_MOVABLE(T))
311                 memcpy(&dst, &src, sizeof(T));
312             else
313             {
314                 construct(&dst, src);
315                 destruct(&src);
316             }
317         }
318
319         // pDst must be uninitialized memory, pSrc will be destructed
320         template <typename T>
321         inline void move_array(T *pDst, T *pSrc, uint n)
322         {
323             if (VOGL_IS_BITWISE_COPYABLE_OR_MOVABLE(T))
324                 memcpy(pDst, pSrc, sizeof(T) * n);
325             else
326             {
327                 for (uint i = 0; i < n; i++)
328                 {
329                     construct(pDst + i, pSrc[i]);
330                     destruct(pSrc + i);
331                 }
332             }
333         }
334
335         // pDst must be uninitialized memory
336         template <typename T>
337         inline void copy_array(T *pDst, const T *pSrc, uint n)
338         {
339             if (VOGL_IS_BITWISE_COPYABLE(T))
340                 memcpy(pDst, pSrc, sizeof(T) * n);
341             else
342             {
343                 for (uint i = 0; i < n; i++)
344                     construct(pDst + i, pSrc[i]);
345             }
346         }
347     }
348
349     // This doesn't invoke RTTI - but the return name is not portable so only use it for debugging purposes.
350     // You can use vogl::demangle() to demangle the returned string.
351     template <typename T>
352     inline const char *type_name()
353     {
354         return typeid(T).name();
355     }
356
357     template <typename T>
358     inline const char *type_name(const T &obj)
359     {
360         VOGL_NOTE_UNUSED(obj);
361         return typeid(T).name();
362     }
363
364 } // namespace vogl