1 // COPY OF TypeHelpers.h from system/core/libutils/include/utils.
2 /*
3  * Copyright (C) 2013 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef RS_TYPE_HELPERS_H
19 #define RS_TYPE_HELPERS_H
20 
21 #include <new>
22 #include <stdint.h>
23 #include <string.h>
24 #include <sys/types.h>
25 
26 // ---------------------------------------------------------------------------
27 namespace android {
28 namespace RSC {
29 
30 /*
31  * Types traits
32  */
33 
34 template <typename T> struct trait_trivial_ctor { enum { value = false }; };
35 template <typename T> struct trait_trivial_dtor { enum { value = false }; };
36 template <typename T> struct trait_trivial_copy { enum { value = false }; };
37 template <typename T> struct trait_trivial_move { enum { value = false }; };
38 template <typename T> struct trait_pointer      { enum { value = false }; };
39 template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
40 
41 template <typename TYPE>
42 struct traits {
43     enum {
44         // whether this type is a pointer
45         is_pointer          = trait_pointer<TYPE>::value,
46         // whether this type's constructor is a no-op
47         has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
48         // whether this type's destructor is a no-op
49         has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
50         // whether this type type can be copy-constructed with memcpy
51         has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
52         // whether this type can be moved with memmove
53         has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
54     };
55 };
56 
57 template <typename T, typename U>
58 struct aggregate_traits {
59     enum {
60         is_pointer          = false,
61         has_trivial_ctor    =
62             traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
63         has_trivial_dtor    =
64             traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
65         has_trivial_copy    =
66             traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
67         has_trivial_move    =
68             traits<T>::has_trivial_move && traits<U>::has_trivial_move
69     };
70 };
71 
72 #define RS_TRIVIAL_CTOR_TRAIT( T ) \
73     template<> struct trait_trivial_ctor< T >   { enum { value = true }; };
74 
75 #define RS_TRIVIAL_DTOR_TRAIT( T ) \
76     template<> struct trait_trivial_dtor< T >   { enum { value = true }; };
77 
78 #define RS_TRIVIAL_COPY_TRAIT( T ) \
79     template<> struct trait_trivial_copy< T >   { enum { value = true }; };
80 
81 #define RS_TRIVIAL_MOVE_TRAIT( T ) \
82     template<> struct trait_trivial_move< T >   { enum { value = true }; };
83 
84 #define RS_BASIC_TYPES_TRAITS( T ) \
85     RS_TRIVIAL_CTOR_TRAIT( T ) \
86     RS_TRIVIAL_DTOR_TRAIT( T ) \
87     RS_TRIVIAL_COPY_TRAIT( T ) \
88     RS_TRIVIAL_MOVE_TRAIT( T )
89 
90 // ---------------------------------------------------------------------------
91 
92 /*
93  * basic types traits
94  */
95 
96 RS_BASIC_TYPES_TRAITS( void )
97 RS_BASIC_TYPES_TRAITS( bool )
98 RS_BASIC_TYPES_TRAITS( char )
99 RS_BASIC_TYPES_TRAITS( unsigned char )
100 RS_BASIC_TYPES_TRAITS( short )
101 RS_BASIC_TYPES_TRAITS( unsigned short )
102 RS_BASIC_TYPES_TRAITS( int )
103 RS_BASIC_TYPES_TRAITS( unsigned int )
104 RS_BASIC_TYPES_TRAITS( long )
105 RS_BASIC_TYPES_TRAITS( unsigned long )
106 RS_BASIC_TYPES_TRAITS( long long )
107 RS_BASIC_TYPES_TRAITS( unsigned long long )
108 RS_BASIC_TYPES_TRAITS( float )
109 RS_BASIC_TYPES_TRAITS( double )
110 
111 // ---------------------------------------------------------------------------
112 
113 
114 /*
115  * compare and order types
116  */
117 
118 template<typename TYPE> inline
119 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
120     return (lhs < rhs) ? 1 : 0;
121 }
122 
123 template<typename TYPE> inline
124 int compare_type(const TYPE& lhs, const TYPE& rhs) {
125     return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
126 }
127 
128 /*
129  * create, destroy, copy and move types...
130  */
131 
132 template<typename TYPE> inline
133 void construct_type(TYPE* p, size_t n) {
134     if (!traits<TYPE>::has_trivial_ctor) {
135         while (n--) {
136             new(p++) TYPE;
137         }
138     }
139 }
140 
141 template<typename TYPE> inline
142 void destroy_type(TYPE* p, size_t n) {
143     if (!traits<TYPE>::has_trivial_dtor) {
144         while (n--) {
145             p->~TYPE();
146             p++;
147         }
148     }
149 }
150 
151 template<typename TYPE> inline
152 void copy_type(TYPE* d, const TYPE* s, size_t n) {
153     if (!traits<TYPE>::has_trivial_copy) {
154         while (n--) {
155             new(d) TYPE(*s);
156             d++, s++;
157         }
158     } else {
159         memcpy(d,s,n*sizeof(TYPE));
160     }
161 }
162 
163 template<typename TYPE> inline
164 void splat_type(TYPE* where, const TYPE* what, size_t n) {
165     if (!traits<TYPE>::has_trivial_copy) {
166         while (n--) {
167             new(where) TYPE(*what);
168             where++;
169         }
170     } else {
171         while (n--) {
172             *where++ = *what;
173         }
174     }
175 }
176 
177 template<typename TYPE> inline
178 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
179     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
180             || traits<TYPE>::has_trivial_move)
181     {
182         memmove(d,s,n*sizeof(TYPE));
183     } else {
184         d += n;
185         s += n;
186         while (n--) {
187             --d, --s;
188             if (!traits<TYPE>::has_trivial_copy) {
189                 new(d) TYPE(*s);
190             } else {
191                 *d = *s;
192             }
193             if (!traits<TYPE>::has_trivial_dtor) {
194                 s->~TYPE();
195             }
196         }
197     }
198 }
199 
200 template<typename TYPE> inline
201 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
202     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
203             || traits<TYPE>::has_trivial_move)
204     {
205         memmove(d,s,n*sizeof(TYPE));
206     } else {
207         while (n--) {
208             if (!traits<TYPE>::has_trivial_copy) {
209                 new(d) TYPE(*s);
210             } else {
211                 *d = *s;
212             }
213             if (!traits<TYPE>::has_trivial_dtor) {
214                 s->~TYPE();
215             }
216             d++, s++;
217         }
218     }
219 }
220 
221 // ---------------------------------------------------------------------------
222 
223 /*
224  * a key/value pair
225  */
226 
227 template <typename KEY, typename VALUE>
228 struct key_value_pair_t {
229     typedef KEY key_t;
230     typedef VALUE value_t;
231 
232     KEY     key;
233     VALUE   value;
234     key_value_pair_t() { }
235     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
236     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
237     explicit key_value_pair_t(const KEY& k) : key(k) { }
238     inline bool operator < (const key_value_pair_t& o) const {
239         return strictly_order_type(key, o.key);
240     }
241     inline const KEY& getKey() const {
242         return key;
243     }
244     inline const VALUE& getValue() const {
245         return value;
246     }
247 };
248 
249 template <typename K, typename V>
250 struct trait_trivial_ctor< key_value_pair_t<K, V> >
251 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
252 template <typename K, typename V>
253 struct trait_trivial_dtor< key_value_pair_t<K, V> >
254 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
255 template <typename K, typename V>
256 struct trait_trivial_copy< key_value_pair_t<K, V> >
257 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
258 template <typename K, typename V>
259 struct trait_trivial_move< key_value_pair_t<K, V> >
260 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
261 
262 // ---------------------------------------------------------------------------
263 
264 /*
265  * Hash codes.
266  */
267 typedef uint32_t hash_t;
268 
269 template <typename TKey>
270 hash_t hash_type(const TKey& key);
271 
272 /* Built-in hash code specializations.
273  * Assumes pointers are 32bit. */
274 #define RS_INT32_HASH(T) \
275         template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
276 #define RS_INT64_HASH(T) \
277         template <> inline hash_t hash_type(const T& value) { \
278                 return hash_t((value >> 32) ^ value); }
279 #define RS_REINTERPRET_HASH(T, R) \
280         template <> inline hash_t hash_type(const T& value) { \
281                 return hash_type(*reinterpret_cast<const R*>(&value)); }
282 
283 RS_INT32_HASH(bool)
284 RS_INT32_HASH(int8_t)
285 RS_INT32_HASH(uint8_t)
286 RS_INT32_HASH(int16_t)
287 RS_INT32_HASH(uint16_t)
288 RS_INT32_HASH(int32_t)
289 RS_INT32_HASH(uint32_t)
290 RS_INT64_HASH(int64_t)
291 RS_INT64_HASH(uint64_t)
292 RS_REINTERPRET_HASH(float, uint32_t)
293 RS_REINTERPRET_HASH(double, uint64_t)
294 
295 template <typename T> inline hash_t hash_type(T* const & value) {
296     return hash_type(uintptr_t(value));
297 }
298 
299 }; // namespace RSC
300 }; // namespace android
301 // ---------------------------------------------------------------------------
302 
303 #endif // RS_TYPE_HELPERS_H
304