blob: 62757935078841fab2dfb507240995ba29371dd4 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
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>
Colin Cross17b5b822016-09-15 18:15:37 -070021#include <type_traits>
22
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080023#include <stdint.h>
24#include <string.h>
25#include <sys/types.h>
26
27// ---------------------------------------------------------------------------
28
29namespace android {
30
31/*
32 * Types traits
33 */
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080034
Mathias Agopiana33bd162009-06-22 01:17:46 -070035template <typename T> struct trait_trivial_ctor { enum { value = false }; };
36template <typename T> struct trait_trivial_dtor { enum { value = false }; };
37template <typename T> struct trait_trivial_copy { enum { value = false }; };
38template <typename T> struct trait_trivial_move { enum { value = false }; };
39template <typename T> struct trait_pointer { enum { value = false }; };
40template <typename T> struct trait_pointer<T*> { enum { value = true }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080041
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080042template <typename TYPE>
43struct traits {
44 enum {
Mathias Agopiana33bd162009-06-22 01:17:46 -070045 // whether this type is a pointer
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080046 is_pointer = trait_pointer<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070047 // whether this type's constructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080048 has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070049 // whether this type's destructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080050 has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070051 // whether this type type can be copy-constructed with memcpy
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080052 has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070053 // whether this type can be moved with memmove
54 has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080055 };
56};
57
58template <typename T, typename U>
59struct aggregate_traits {
60 enum {
61 is_pointer = false,
Mathias Agopiana33bd162009-06-22 01:17:46 -070062 has_trivial_ctor =
63 traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
64 has_trivial_dtor =
65 traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
66 has_trivial_copy =
67 traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
68 has_trivial_move =
69 traits<T>::has_trivial_move && traits<U>::has_trivial_move
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080070 };
71};
72
Jeff Brown9a0a76d2012-03-16 14:45:49 -070073#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
74 template<> struct trait_trivial_ctor< T > { enum { value = true }; };
75
76#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
77 template<> struct trait_trivial_dtor< T > { enum { value = true }; };
78
79#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
80 template<> struct trait_trivial_copy< T > { enum { value = true }; };
81
82#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
Mathias Agopiana33bd162009-06-22 01:17:46 -070083 template<> struct trait_trivial_move< T > { enum { value = true }; };
84
Jeff Brown9a0a76d2012-03-16 14:45:49 -070085#define ANDROID_BASIC_TYPES_TRAITS( T ) \
86 ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
87 ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
88 ANDROID_TRIVIAL_COPY_TRAIT( T ) \
89 ANDROID_TRIVIAL_MOVE_TRAIT( T )
90
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080091// ---------------------------------------------------------------------------
92
93/*
94 * basic types traits
95 */
Mathias Agopiana33bd162009-06-22 01:17:46 -070096
97ANDROID_BASIC_TYPES_TRAITS( void )
98ANDROID_BASIC_TYPES_TRAITS( bool )
99ANDROID_BASIC_TYPES_TRAITS( char )
100ANDROID_BASIC_TYPES_TRAITS( unsigned char )
101ANDROID_BASIC_TYPES_TRAITS( short )
102ANDROID_BASIC_TYPES_TRAITS( unsigned short )
103ANDROID_BASIC_TYPES_TRAITS( int )
104ANDROID_BASIC_TYPES_TRAITS( unsigned int )
105ANDROID_BASIC_TYPES_TRAITS( long )
106ANDROID_BASIC_TYPES_TRAITS( unsigned long )
107ANDROID_BASIC_TYPES_TRAITS( long long )
108ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
109ANDROID_BASIC_TYPES_TRAITS( float )
110ANDROID_BASIC_TYPES_TRAITS( double )
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800111
112// ---------------------------------------------------------------------------
113
Mathias Agopiana33bd162009-06-22 01:17:46 -0700114
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800115/*
116 * compare and order types
117 */
118
119template<typename TYPE> inline
120int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
121 return (lhs < rhs) ? 1 : 0;
122}
123
124template<typename TYPE> inline
125int compare_type(const TYPE& lhs, const TYPE& rhs) {
126 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
127}
128
129/*
Mathias Agopiana33bd162009-06-22 01:17:46 -0700130 * create, destroy, copy and move types...
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800131 */
Mathias Agopiana33bd162009-06-22 01:17:46 -0700132
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800133template<typename TYPE> inline
134void construct_type(TYPE* p, size_t n) {
135 if (!traits<TYPE>::has_trivial_ctor) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700136 while (n > 0) {
137 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800138 new(p++) TYPE;
139 }
140 }
141}
142
143template<typename TYPE> inline
144void destroy_type(TYPE* p, size_t n) {
145 if (!traits<TYPE>::has_trivial_dtor) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700146 while (n > 0) {
147 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800148 p->~TYPE();
149 p++;
150 }
151 }
152}
153
154template<typename TYPE> inline
155void copy_type(TYPE* d, const TYPE* s, size_t n) {
156 if (!traits<TYPE>::has_trivial_copy) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700157 while (n > 0) {
158 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800159 new(d) TYPE(*s);
160 d++, s++;
161 }
162 } else {
163 memcpy(d,s,n*sizeof(TYPE));
164 }
165}
166
167template<typename TYPE> inline
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800168void splat_type(TYPE* where, const TYPE* what, size_t n) {
169 if (!traits<TYPE>::has_trivial_copy) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700170 while (n > 0) {
171 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800172 new(where) TYPE(*what);
173 where++;
174 }
175 } else {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700176 while (n > 0) {
177 n--;
Mathias Agopiana33bd162009-06-22 01:17:46 -0700178 *where++ = *what;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800179 }
180 }
181}
182
Colin Cross17b5b822016-09-15 18:15:37 -0700183template<typename TYPE>
184struct use_trivial_move : public std::integral_constant<bool,
185 (traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
186 || traits<TYPE>::has_trivial_move
187> {};
188
189template<typename TYPE>
190typename std::enable_if<use_trivial_move<TYPE>::value>::type
191inline
192move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
193 memmove(d, s, n*sizeof(TYPE));
194}
195
196template<typename TYPE>
197typename std::enable_if<!use_trivial_move<TYPE>::value>::type
198inline
199move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
200 d += n;
201 s += n;
202 while (n > 0) {
203 n--;
204 --d, --s;
205 if (!traits<TYPE>::has_trivial_copy) {
206 new(d) TYPE(*s);
207 } else {
208 *d = *s;
209 }
210 if (!traits<TYPE>::has_trivial_dtor) {
211 s->~TYPE();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800212 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800213 }
214}
215
Colin Cross17b5b822016-09-15 18:15:37 -0700216template<typename TYPE>
217typename std::enable_if<use_trivial_move<TYPE>::value>::type
218inline
219move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
220 memmove(d, s, n*sizeof(TYPE));
221}
222
223template<typename TYPE>
224typename std::enable_if<!use_trivial_move<TYPE>::value>::type
225inline
226move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
227 while (n > 0) {
228 n--;
229 if (!traits<TYPE>::has_trivial_copy) {
230 new(d) TYPE(*s);
231 } else {
232 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800233 }
Colin Cross17b5b822016-09-15 18:15:37 -0700234 if (!traits<TYPE>::has_trivial_dtor) {
235 s->~TYPE();
236 }
237 d++, s++;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800238 }
239}
Mathias Agopiana33bd162009-06-22 01:17:46 -0700240
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800241// ---------------------------------------------------------------------------
242
243/*
244 * a key/value pair
245 */
246
247template <typename KEY, typename VALUE>
248struct key_value_pair_t {
Jeff Browne735f232011-11-14 18:29:15 -0800249 typedef KEY key_t;
250 typedef VALUE value_t;
251
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800252 KEY key;
253 VALUE value;
254 key_value_pair_t() { }
255 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
Colin Cross17b5b822016-09-15 18:15:37 -0700256 key_value_pair_t& operator=(const key_value_pair_t& o) {
257 key = o.key;
258 value = o.value;
259 return *this;
260 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800261 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -0700262 explicit key_value_pair_t(const KEY& k) : key(k) { }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800263 inline bool operator < (const key_value_pair_t& o) const {
264 return strictly_order_type(key, o.key);
265 }
Jeff Browne735f232011-11-14 18:29:15 -0800266 inline const KEY& getKey() const {
267 return key;
268 }
269 inline const VALUE& getValue() const {
270 return value;
271 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800272};
273
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800274template <typename K, typename V>
275struct trait_trivial_ctor< key_value_pair_t<K, V> >
276{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800277template <typename K, typename V>
278struct trait_trivial_dtor< key_value_pair_t<K, V> >
279{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800280template <typename K, typename V>
281struct trait_trivial_copy< key_value_pair_t<K, V> >
282{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800283template <typename K, typename V>
Mathias Agopiana33bd162009-06-22 01:17:46 -0700284struct trait_trivial_move< key_value_pair_t<K, V> >
285{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800286
287// ---------------------------------------------------------------------------
288
Jeff Browne735f232011-11-14 18:29:15 -0800289/*
290 * Hash codes.
291 */
292typedef uint32_t hash_t;
293
294template <typename TKey>
295hash_t hash_type(const TKey& key);
296
Colin Cross17b5b822016-09-15 18:15:37 -0700297/* Built-in hash code specializations */
Jeff Browne735f232011-11-14 18:29:15 -0800298#define ANDROID_INT32_HASH(T) \
299 template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
300#define ANDROID_INT64_HASH(T) \
301 template <> inline hash_t hash_type(const T& value) { \
302 return hash_t((value >> 32) ^ value); }
303#define ANDROID_REINTERPRET_HASH(T, R) \
304 template <> inline hash_t hash_type(const T& value) { \
Colin Cross17b5b822016-09-15 18:15:37 -0700305 R newValue; \
306 static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \
307 memcpy(&newValue, &value, sizeof(newValue)); \
308 return hash_type(newValue); \
309 }
Jeff Browne735f232011-11-14 18:29:15 -0800310
311ANDROID_INT32_HASH(bool)
Jeff Brown142dbcd2011-11-24 11:54:21 -0800312ANDROID_INT32_HASH(int8_t)
313ANDROID_INT32_HASH(uint8_t)
314ANDROID_INT32_HASH(int16_t)
315ANDROID_INT32_HASH(uint16_t)
316ANDROID_INT32_HASH(int32_t)
317ANDROID_INT32_HASH(uint32_t)
318ANDROID_INT64_HASH(int64_t)
319ANDROID_INT64_HASH(uint64_t)
Jeff Browne735f232011-11-14 18:29:15 -0800320ANDROID_REINTERPRET_HASH(float, uint32_t)
321ANDROID_REINTERPRET_HASH(double, uint64_t)
322
Raph Levienb6ea1752012-10-25 23:11:13 -0700323template <typename T> inline hash_t hash_type(T* const & value) {
Jeff Browne735f232011-11-14 18:29:15 -0800324 return hash_type(uintptr_t(value));
325}
326
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800327}; // namespace android
328
329// ---------------------------------------------------------------------------
330
331#endif // ANDROID_TYPE_HELPERS_H