blob: 64d25c5db1c3965aaa9e8efcde3558a0640ad9f7 [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>
21#include <stdint.h>
22#include <string.h>
23#include <sys/types.h>
24
25// ---------------------------------------------------------------------------
26
27namespace android {
28
29/*
30 * Types traits
31 */
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080032
Mathias Agopiana33bd162009-06-22 01:17:46 -070033template <typename T> struct trait_trivial_ctor { enum { value = false }; };
34template <typename T> struct trait_trivial_dtor { enum { value = false }; };
35template <typename T> struct trait_trivial_copy { enum { value = false }; };
36template <typename T> struct trait_trivial_move { enum { value = false }; };
37template <typename T> struct trait_pointer { enum { value = false }; };
38template <typename T> struct trait_pointer<T*> { enum { value = true }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080039
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080040template <typename TYPE>
41struct traits {
42 enum {
Mathias Agopiana33bd162009-06-22 01:17:46 -070043 // whether this type is a pointer
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080044 is_pointer = trait_pointer<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070045 // whether this type's constructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080046 has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070047 // whether this type's destructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080048 has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070049 // whether this type type can be copy-constructed with memcpy
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080050 has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070051 // whether this type can be moved with memmove
52 has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080053 };
54};
55
56template <typename T, typename U>
57struct aggregate_traits {
58 enum {
59 is_pointer = false,
Mathias Agopiana33bd162009-06-22 01:17:46 -070060 has_trivial_ctor =
61 traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
62 has_trivial_dtor =
63 traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
64 has_trivial_copy =
65 traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
66 has_trivial_move =
67 traits<T>::has_trivial_move && traits<U>::has_trivial_move
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080068 };
69};
70
Jeff Brown9a0a76d2012-03-16 14:45:49 -070071#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
72 template<> struct trait_trivial_ctor< T > { enum { value = true }; };
73
74#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
75 template<> struct trait_trivial_dtor< T > { enum { value = true }; };
76
77#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
78 template<> struct trait_trivial_copy< T > { enum { value = true }; };
79
80#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
Mathias Agopiana33bd162009-06-22 01:17:46 -070081 template<> struct trait_trivial_move< T > { enum { value = true }; };
82
Jeff Brown9a0a76d2012-03-16 14:45:49 -070083#define ANDROID_BASIC_TYPES_TRAITS( T ) \
84 ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
85 ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
86 ANDROID_TRIVIAL_COPY_TRAIT( T ) \
87 ANDROID_TRIVIAL_MOVE_TRAIT( T )
88
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080089// ---------------------------------------------------------------------------
90
91/*
92 * basic types traits
93 */
Mathias Agopiana33bd162009-06-22 01:17:46 -070094
95ANDROID_BASIC_TYPES_TRAITS( void )
96ANDROID_BASIC_TYPES_TRAITS( bool )
97ANDROID_BASIC_TYPES_TRAITS( char )
98ANDROID_BASIC_TYPES_TRAITS( unsigned char )
99ANDROID_BASIC_TYPES_TRAITS( short )
100ANDROID_BASIC_TYPES_TRAITS( unsigned short )
101ANDROID_BASIC_TYPES_TRAITS( int )
102ANDROID_BASIC_TYPES_TRAITS( unsigned int )
103ANDROID_BASIC_TYPES_TRAITS( long )
104ANDROID_BASIC_TYPES_TRAITS( unsigned long )
105ANDROID_BASIC_TYPES_TRAITS( long long )
106ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
107ANDROID_BASIC_TYPES_TRAITS( float )
108ANDROID_BASIC_TYPES_TRAITS( double )
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800109
110// ---------------------------------------------------------------------------
111
Mathias Agopiana33bd162009-06-22 01:17:46 -0700112
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800113/*
114 * compare and order types
115 */
116
117template<typename TYPE> inline
118int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
119 return (lhs < rhs) ? 1 : 0;
120}
121
122template<typename TYPE> inline
123int compare_type(const TYPE& lhs, const TYPE& rhs) {
124 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
125}
126
127/*
Mathias Agopiana33bd162009-06-22 01:17:46 -0700128 * create, destroy, copy and move types...
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800129 */
Mathias Agopiana33bd162009-06-22 01:17:46 -0700130
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800131template<typename TYPE> inline
132void construct_type(TYPE* p, size_t n) {
133 if (!traits<TYPE>::has_trivial_ctor) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700134 while (n > 0) {
135 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800136 new(p++) TYPE;
137 }
138 }
139}
140
141template<typename TYPE> inline
142void destroy_type(TYPE* p, size_t n) {
143 if (!traits<TYPE>::has_trivial_dtor) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700144 while (n > 0) {
145 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800146 p->~TYPE();
147 p++;
148 }
149 }
150}
151
152template<typename TYPE> inline
153void copy_type(TYPE* d, const TYPE* s, size_t n) {
154 if (!traits<TYPE>::has_trivial_copy) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700155 while (n > 0) {
156 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800157 new(d) TYPE(*s);
158 d++, s++;
159 }
160 } else {
161 memcpy(d,s,n*sizeof(TYPE));
162 }
163}
164
165template<typename TYPE> inline
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800166void splat_type(TYPE* where, const TYPE* what, size_t n) {
167 if (!traits<TYPE>::has_trivial_copy) {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700168 while (n > 0) {
169 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800170 new(where) TYPE(*what);
171 where++;
172 }
173 } else {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700174 while (n > 0) {
175 n--;
Mathias Agopiana33bd162009-06-22 01:17:46 -0700176 *where++ = *what;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800177 }
178 }
179}
180
181template<typename TYPE> inline
182void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700183 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
184 || traits<TYPE>::has_trivial_move)
185 {
186 memmove(d,s,n*sizeof(TYPE));
187 } else {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800188 d += n;
189 s += n;
Nick Kralevich58bf5722015-06-13 15:28:53 -0700190 while (n > 0) {
191 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800192 --d, --s;
193 if (!traits<TYPE>::has_trivial_copy) {
194 new(d) TYPE(*s);
195 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700196 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800197 }
198 if (!traits<TYPE>::has_trivial_dtor) {
199 s->~TYPE();
200 }
201 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800202 }
203}
204
205template<typename TYPE> inline
206void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700207 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
208 || traits<TYPE>::has_trivial_move)
209 {
210 memmove(d,s,n*sizeof(TYPE));
211 } else {
Nick Kralevich58bf5722015-06-13 15:28:53 -0700212 while (n > 0) {
213 n--;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800214 if (!traits<TYPE>::has_trivial_copy) {
215 new(d) TYPE(*s);
216 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700217 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800218 }
219 if (!traits<TYPE>::has_trivial_dtor) {
220 s->~TYPE();
221 }
222 d++, s++;
223 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800224 }
225}
Mathias Agopiana33bd162009-06-22 01:17:46 -0700226
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800227// ---------------------------------------------------------------------------
228
229/*
230 * a key/value pair
231 */
232
233template <typename KEY, typename VALUE>
234struct key_value_pair_t {
Jeff Browne735f232011-11-14 18:29:15 -0800235 typedef KEY key_t;
236 typedef VALUE value_t;
237
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800238 KEY key;
239 VALUE value;
240 key_value_pair_t() { }
241 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
242 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
Chih-Hung Hsieh2a929962016-08-02 12:14:47 -0700243 explicit key_value_pair_t(const KEY& k) : key(k) { }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800244 inline bool operator < (const key_value_pair_t& o) const {
245 return strictly_order_type(key, o.key);
246 }
Jeff Browne735f232011-11-14 18:29:15 -0800247 inline const KEY& getKey() const {
248 return key;
249 }
250 inline const VALUE& getValue() const {
251 return value;
252 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800253};
254
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800255template <typename K, typename V>
256struct trait_trivial_ctor< key_value_pair_t<K, V> >
257{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800258template <typename K, typename V>
259struct trait_trivial_dtor< key_value_pair_t<K, V> >
260{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800261template <typename K, typename V>
262struct trait_trivial_copy< key_value_pair_t<K, V> >
263{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800264template <typename K, typename V>
Mathias Agopiana33bd162009-06-22 01:17:46 -0700265struct trait_trivial_move< key_value_pair_t<K, V> >
266{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800267
268// ---------------------------------------------------------------------------
269
Jeff Browne735f232011-11-14 18:29:15 -0800270/*
271 * Hash codes.
272 */
273typedef uint32_t hash_t;
274
275template <typename TKey>
276hash_t hash_type(const TKey& key);
277
278/* Built-in hash code specializations.
279 * Assumes pointers are 32bit. */
280#define ANDROID_INT32_HASH(T) \
281 template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
282#define ANDROID_INT64_HASH(T) \
283 template <> inline hash_t hash_type(const T& value) { \
284 return hash_t((value >> 32) ^ value); }
285#define ANDROID_REINTERPRET_HASH(T, R) \
286 template <> inline hash_t hash_type(const T& value) { \
287 return hash_type(*reinterpret_cast<const R*>(&value)); }
288
289ANDROID_INT32_HASH(bool)
Jeff Brown142dbcd2011-11-24 11:54:21 -0800290ANDROID_INT32_HASH(int8_t)
291ANDROID_INT32_HASH(uint8_t)
292ANDROID_INT32_HASH(int16_t)
293ANDROID_INT32_HASH(uint16_t)
294ANDROID_INT32_HASH(int32_t)
295ANDROID_INT32_HASH(uint32_t)
296ANDROID_INT64_HASH(int64_t)
297ANDROID_INT64_HASH(uint64_t)
Jeff Browne735f232011-11-14 18:29:15 -0800298ANDROID_REINTERPRET_HASH(float, uint32_t)
299ANDROID_REINTERPRET_HASH(double, uint64_t)
300
Raph Levienb6ea1752012-10-25 23:11:13 -0700301template <typename T> inline hash_t hash_type(T* const & value) {
Jeff Browne735f232011-11-14 18:29:15 -0800302 return hash_type(uintptr_t(value));
303}
304
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800305}; // namespace android
306
307// ---------------------------------------------------------------------------
308
309#endif // ANDROID_TYPE_HELPERS_H