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