blob: 7b4fb70ba6410024106581646a03cf7a05697a8c [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
Mathias Agopiana33bd162009-06-22 01:17:46 -070071#define ANDROID_BASIC_TYPES_TRAITS( T ) \
72 template<> struct trait_trivial_ctor< T > { enum { value = true }; }; \
73 template<> struct trait_trivial_dtor< T > { enum { value = true }; }; \
74 template<> struct trait_trivial_copy< T > { enum { value = true }; }; \
75 template<> struct trait_trivial_move< T > { enum { value = true }; };
76
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080077// ---------------------------------------------------------------------------
78
79/*
80 * basic types traits
81 */
Mathias Agopiana33bd162009-06-22 01:17:46 -070082
83ANDROID_BASIC_TYPES_TRAITS( void )
84ANDROID_BASIC_TYPES_TRAITS( bool )
85ANDROID_BASIC_TYPES_TRAITS( char )
86ANDROID_BASIC_TYPES_TRAITS( unsigned char )
87ANDROID_BASIC_TYPES_TRAITS( short )
88ANDROID_BASIC_TYPES_TRAITS( unsigned short )
89ANDROID_BASIC_TYPES_TRAITS( int )
90ANDROID_BASIC_TYPES_TRAITS( unsigned int )
91ANDROID_BASIC_TYPES_TRAITS( long )
92ANDROID_BASIC_TYPES_TRAITS( unsigned long )
93ANDROID_BASIC_TYPES_TRAITS( long long )
94ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
95ANDROID_BASIC_TYPES_TRAITS( float )
96ANDROID_BASIC_TYPES_TRAITS( double )
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080097
98// ---------------------------------------------------------------------------
99
Mathias Agopiana33bd162009-06-22 01:17:46 -0700100
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800101/*
102 * compare and order types
103 */
104
105template<typename TYPE> inline
106int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
107 return (lhs < rhs) ? 1 : 0;
108}
109
110template<typename TYPE> inline
111int compare_type(const TYPE& lhs, const TYPE& rhs) {
112 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
113}
114
115/*
Mathias Agopiana33bd162009-06-22 01:17:46 -0700116 * create, destroy, copy and move types...
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800117 */
Mathias Agopiana33bd162009-06-22 01:17:46 -0700118
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800119template<typename TYPE> inline
120void construct_type(TYPE* p, size_t n) {
121 if (!traits<TYPE>::has_trivial_ctor) {
122 while (n--) {
123 new(p++) TYPE;
124 }
125 }
126}
127
128template<typename TYPE> inline
129void destroy_type(TYPE* p, size_t n) {
130 if (!traits<TYPE>::has_trivial_dtor) {
131 while (n--) {
132 p->~TYPE();
133 p++;
134 }
135 }
136}
137
138template<typename TYPE> inline
139void copy_type(TYPE* d, const TYPE* s, size_t n) {
140 if (!traits<TYPE>::has_trivial_copy) {
141 while (n--) {
142 new(d) TYPE(*s);
143 d++, s++;
144 }
145 } else {
146 memcpy(d,s,n*sizeof(TYPE));
147 }
148}
149
150template<typename TYPE> inline
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800151void splat_type(TYPE* where, const TYPE* what, size_t n) {
152 if (!traits<TYPE>::has_trivial_copy) {
153 while (n--) {
154 new(where) TYPE(*what);
155 where++;
156 }
157 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700158 while (n--) {
159 *where++ = *what;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800160 }
161 }
162}
163
164template<typename TYPE> inline
165void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700166 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
167 || traits<TYPE>::has_trivial_move)
168 {
169 memmove(d,s,n*sizeof(TYPE));
170 } else {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800171 d += n;
172 s += n;
173 while (n--) {
174 --d, --s;
175 if (!traits<TYPE>::has_trivial_copy) {
176 new(d) TYPE(*s);
177 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700178 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800179 }
180 if (!traits<TYPE>::has_trivial_dtor) {
181 s->~TYPE();
182 }
183 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800184 }
185}
186
187template<typename TYPE> inline
188void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700189 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
190 || traits<TYPE>::has_trivial_move)
191 {
192 memmove(d,s,n*sizeof(TYPE));
193 } else {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800194 while (n--) {
195 if (!traits<TYPE>::has_trivial_copy) {
196 new(d) TYPE(*s);
197 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700198 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800199 }
200 if (!traits<TYPE>::has_trivial_dtor) {
201 s->~TYPE();
202 }
203 d++, s++;
204 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800205 }
206}
Mathias Agopiana33bd162009-06-22 01:17:46 -0700207
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800208// ---------------------------------------------------------------------------
209
210/*
211 * a key/value pair
212 */
213
214template <typename KEY, typename VALUE>
215struct key_value_pair_t {
Jeff Browne735f232011-11-14 18:29:15 -0800216 typedef KEY key_t;
217 typedef VALUE value_t;
218
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800219 KEY key;
220 VALUE value;
221 key_value_pair_t() { }
222 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
223 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
224 key_value_pair_t(const KEY& k) : key(k) { }
225 inline bool operator < (const key_value_pair_t& o) const {
226 return strictly_order_type(key, o.key);
227 }
Jeff Browne735f232011-11-14 18:29:15 -0800228 inline const KEY& getKey() const {
229 return key;
230 }
231 inline const VALUE& getValue() const {
232 return value;
233 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800234};
235
236template<>
237template <typename K, typename V>
238struct trait_trivial_ctor< key_value_pair_t<K, V> >
239{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
240template<>
241template <typename K, typename V>
242struct trait_trivial_dtor< key_value_pair_t<K, V> >
243{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
244template<>
245template <typename K, typename V>
246struct trait_trivial_copy< key_value_pair_t<K, V> >
247{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
248template<>
249template <typename K, typename V>
Mathias Agopiana33bd162009-06-22 01:17:46 -0700250struct trait_trivial_move< key_value_pair_t<K, V> >
251{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800252
253// ---------------------------------------------------------------------------
254
Jeff Browne735f232011-11-14 18:29:15 -0800255/*
256 * Hash codes.
257 */
258typedef uint32_t hash_t;
259
260template <typename TKey>
261hash_t hash_type(const TKey& key);
262
263/* Built-in hash code specializations.
264 * Assumes pointers are 32bit. */
265#define ANDROID_INT32_HASH(T) \
266 template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
267#define ANDROID_INT64_HASH(T) \
268 template <> inline hash_t hash_type(const T& value) { \
269 return hash_t((value >> 32) ^ value); }
270#define ANDROID_REINTERPRET_HASH(T, R) \
271 template <> inline hash_t hash_type(const T& value) { \
272 return hash_type(*reinterpret_cast<const R*>(&value)); }
273
274ANDROID_INT32_HASH(bool)
Jeff Brown142dbcd2011-11-24 11:54:21 -0800275ANDROID_INT32_HASH(int8_t)
276ANDROID_INT32_HASH(uint8_t)
277ANDROID_INT32_HASH(int16_t)
278ANDROID_INT32_HASH(uint16_t)
279ANDROID_INT32_HASH(int32_t)
280ANDROID_INT32_HASH(uint32_t)
281ANDROID_INT64_HASH(int64_t)
282ANDROID_INT64_HASH(uint64_t)
Jeff Browne735f232011-11-14 18:29:15 -0800283ANDROID_REINTERPRET_HASH(float, uint32_t)
284ANDROID_REINTERPRET_HASH(double, uint64_t)
285
286template <typename T> inline hash_t hash_type(const T*& value) {
287 return hash_type(uintptr_t(value));
288}
289
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800290}; // namespace android
291
292// ---------------------------------------------------------------------------
293
294#endif // ANDROID_TYPE_HELPERS_H