• 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 <stdint.h>
22 #include <string.h>
23 #include <sys/types.h>
24 
25 // ---------------------------------------------------------------------------
26 
27 namespace android {
28 
29 /*
30  * Types traits
31  */
32 
33 template <typename T> struct trait_trivial_ctor { enum { value = false }; };
34 template <typename T> struct trait_trivial_dtor { enum { value = false }; };
35 template <typename T> struct trait_trivial_copy { enum { value = false }; };
36 template <typename T> struct trait_trivial_move { enum { value = false }; };
37 template <typename T> struct trait_pointer      { enum { value = false }; };
38 template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
39 
40 template <typename TYPE>
41 struct traits {
42     enum {
43         // whether this type is a pointer
44         is_pointer          = trait_pointer<TYPE>::value,
45         // whether this type's constructor is a no-op
46         has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
47         // whether this type's destructor is a no-op
48         has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
49         // whether this type type can be copy-constructed with memcpy
50         has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
51         // whether this type can be moved with memmove
52         has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
53     };
54 };
55 
56 template <typename T, typename U>
57 struct aggregate_traits {
58     enum {
59         is_pointer          = false,
60         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
68     };
69 };
70 
71 #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 ) \
81     template<> struct trait_trivial_move< T >   { enum { value = true }; };
82 
83 #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 
89 // ---------------------------------------------------------------------------
90 
91 /*
92  * basic types traits
93  */
94 
95 ANDROID_BASIC_TYPES_TRAITS( void )
96 ANDROID_BASIC_TYPES_TRAITS( bool )
97 ANDROID_BASIC_TYPES_TRAITS( char )
98 ANDROID_BASIC_TYPES_TRAITS( unsigned char )
99 ANDROID_BASIC_TYPES_TRAITS( short )
100 ANDROID_BASIC_TYPES_TRAITS( unsigned short )
101 ANDROID_BASIC_TYPES_TRAITS( int )
102 ANDROID_BASIC_TYPES_TRAITS( unsigned int )
103 ANDROID_BASIC_TYPES_TRAITS( long )
104 ANDROID_BASIC_TYPES_TRAITS( unsigned long )
105 ANDROID_BASIC_TYPES_TRAITS( long long )
106 ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
107 ANDROID_BASIC_TYPES_TRAITS( float )
108 ANDROID_BASIC_TYPES_TRAITS( double )
109 
110 // ---------------------------------------------------------------------------
111 
112 
113 /*
114  * compare and order types
115  */
116 
117 template<typename TYPE> inline
118 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
119     return (lhs < rhs) ? 1 : 0;
120 }
121 
122 template<typename TYPE> inline
123 int compare_type(const TYPE& lhs, const TYPE& rhs) {
124     return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
125 }
126 
127 /*
128  * create, destroy, copy and move types...
129  */
130 
131 template<typename TYPE> inline
132 void construct_type(TYPE* p, size_t n) {
133     if (!traits<TYPE>::has_trivial_ctor) {
134         while (n--) {
135             new(p++) TYPE;
136         }
137     }
138 }
139 
140 template<typename TYPE> inline
141 void destroy_type(TYPE* p, size_t n) {
142     if (!traits<TYPE>::has_trivial_dtor) {
143         while (n--) {
144             p->~TYPE();
145             p++;
146         }
147     }
148 }
149 
150 template<typename TYPE> inline
151 void copy_type(TYPE* d, const TYPE* s, size_t n) {
152     if (!traits<TYPE>::has_trivial_copy) {
153         while (n--) {
154             new(d) TYPE(*s);
155             d++, s++;
156         }
157     } else {
158         memcpy(d,s,n*sizeof(TYPE));
159     }
160 }
161 
162 template<typename TYPE> inline
163 void splat_type(TYPE* where, const TYPE* what, size_t n) {
164     if (!traits<TYPE>::has_trivial_copy) {
165         while (n--) {
166             new(where) TYPE(*what);
167             where++;
168         }
169     } else {
170         while (n--) {
171             *where++ = *what;
172         }
173     }
174 }
175 
176 template<typename TYPE> inline
177 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
178     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
179             || traits<TYPE>::has_trivial_move)
180     {
181         memmove(d,s,n*sizeof(TYPE));
182     } else {
183         d += n;
184         s += n;
185         while (n--) {
186             --d, --s;
187             if (!traits<TYPE>::has_trivial_copy) {
188                 new(d) TYPE(*s);
189             } else {
190                 *d = *s;
191             }
192             if (!traits<TYPE>::has_trivial_dtor) {
193                 s->~TYPE();
194             }
195         }
196     }
197 }
198 
199 template<typename TYPE> inline
200 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
201     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
202             || traits<TYPE>::has_trivial_move)
203     {
204         memmove(d,s,n*sizeof(TYPE));
205     } else {
206         while (n--) {
207             if (!traits<TYPE>::has_trivial_copy) {
208                 new(d) TYPE(*s);
209             } else {
210                 *d = *s;
211             }
212             if (!traits<TYPE>::has_trivial_dtor) {
213                 s->~TYPE();
214             }
215             d++, s++;
216         }
217     }
218 }
219 
220 // ---------------------------------------------------------------------------
221 
222 /*
223  * a key/value pair
224  */
225 
226 template <typename KEY, typename VALUE>
227 struct key_value_pair_t {
228     typedef KEY key_t;
229     typedef VALUE value_t;
230 
231     KEY     key;
232     VALUE   value;
233     key_value_pair_t() { }
234     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
235     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
236     key_value_pair_t(const KEY& k) : key(k) { }
237     inline bool operator < (const key_value_pair_t& o) const {
238         return strictly_order_type(key, o.key);
239     }
240     inline const KEY& getKey() const {
241         return key;
242     }
243     inline const VALUE& getValue() const {
244         return value;
245     }
246 };
247 
248 template <typename K, typename V>
249 struct trait_trivial_ctor< key_value_pair_t<K, V> >
250 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
251 template <typename K, typename V>
252 struct trait_trivial_dtor< key_value_pair_t<K, V> >
253 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
254 template <typename K, typename V>
255 struct trait_trivial_copy< key_value_pair_t<K, V> >
256 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
257 template <typename K, typename V>
258 struct trait_trivial_move< key_value_pair_t<K, V> >
259 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
260 
261 // ---------------------------------------------------------------------------
262 
263 /*
264  * Hash codes.
265  */
266 typedef uint32_t hash_t;
267 
268 template <typename TKey>
269 hash_t hash_type(const TKey& key);
270 
271 /* Built-in hash code specializations.
272  * Assumes pointers are 32bit. */
273 #define ANDROID_INT32_HASH(T) \
274         template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
275 #define ANDROID_INT64_HASH(T) \
276         template <> inline hash_t hash_type(const T& value) { \
277                 return hash_t((value >> 32) ^ value); }
278 #define ANDROID_REINTERPRET_HASH(T, R) \
279         template <> inline hash_t hash_type(const T& value) { \
280                 return hash_type(*reinterpret_cast<const R*>(&value)); }
281 
282 ANDROID_INT32_HASH(bool)
283 ANDROID_INT32_HASH(int8_t)
284 ANDROID_INT32_HASH(uint8_t)
285 ANDROID_INT32_HASH(int16_t)
286 ANDROID_INT32_HASH(uint16_t)
287 ANDROID_INT32_HASH(int32_t)
288 ANDROID_INT32_HASH(uint32_t)
289 ANDROID_INT64_HASH(int64_t)
290 ANDROID_INT64_HASH(uint64_t)
291 ANDROID_REINTERPRET_HASH(float, uint32_t)
292 ANDROID_REINTERPRET_HASH(double, uint64_t)
293 
294 template <typename T> inline hash_t hash_type(const T*& value) {
295     return hash_type(uintptr_t(value));
296 }
297 
298 }; // namespace android
299 
300 // ---------------------------------------------------------------------------
301 
302 #endif // ANDROID_TYPE_HELPERS_H
303