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 > 0) {
135             n--;
136             new(p++) TYPE;
137         }
138     }
139 }
140 
141 template<typename TYPE> inline
142 void destroy_type(TYPE* p, size_t n) {
143     if (!traits<TYPE>::has_trivial_dtor) {
144         while (n > 0) {
145             n--;
146             p->~TYPE();
147             p++;
148         }
149     }
150 }
151 
152 template<typename TYPE> inline
153 void copy_type(TYPE* d, const TYPE* s, size_t n) {
154     if (!traits<TYPE>::has_trivial_copy) {
155         while (n > 0) {
156             n--;
157             new(d) TYPE(*s);
158             d++, s++;
159         }
160     } else {
161         memcpy(d,s,n*sizeof(TYPE));
162     }
163 }
164 
165 template<typename TYPE> inline
166 void splat_type(TYPE* where, const TYPE* what, size_t n) {
167     if (!traits<TYPE>::has_trivial_copy) {
168         while (n > 0) {
169             n--;
170             new(where) TYPE(*what);
171             where++;
172         }
173     } else {
174         while (n > 0) {
175             n--;
176             *where++ = *what;
177         }
178     }
179 }
180 
181 template<typename TYPE> inline
182 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
183     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 {
188         d += n;
189         s += n;
190         while (n > 0) {
191             n--;
192             --d, --s;
193             if (!traits<TYPE>::has_trivial_copy) {
194                 new(d) TYPE(*s);
195             } else {
196                 *d = *s;
197             }
198             if (!traits<TYPE>::has_trivial_dtor) {
199                 s->~TYPE();
200             }
201         }
202     }
203 }
204 
205 template<typename TYPE> inline
206 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
207     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 {
212         while (n > 0) {
213             n--;
214             if (!traits<TYPE>::has_trivial_copy) {
215                 new(d) TYPE(*s);
216             } else {
217                 *d = *s;
218             }
219             if (!traits<TYPE>::has_trivial_dtor) {
220                 s->~TYPE();
221             }
222             d++, s++;
223         }
224     }
225 }
226 
227 // ---------------------------------------------------------------------------
228 
229 /*
230  * a key/value pair
231  */
232 
233 template <typename KEY, typename VALUE>
234 struct key_value_pair_t {
235     typedef KEY key_t;
236     typedef VALUE value_t;
237 
238     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)  { }
243     key_value_pair_t(const KEY& k) : key(k) { }
244     inline bool operator < (const key_value_pair_t& o) const {
245         return strictly_order_type(key, o.key);
246     }
247     inline const KEY& getKey() const {
248         return key;
249     }
250     inline const VALUE& getValue() const {
251         return value;
252     }
253 };
254 
255 template <typename K, typename V>
256 struct trait_trivial_ctor< key_value_pair_t<K, V> >
257 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
258 template <typename K, typename V>
259 struct trait_trivial_dtor< key_value_pair_t<K, V> >
260 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
261 template <typename K, typename V>
262 struct trait_trivial_copy< key_value_pair_t<K, V> >
263 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
264 template <typename K, typename V>
265 struct trait_trivial_move< key_value_pair_t<K, V> >
266 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
267 
268 // ---------------------------------------------------------------------------
269 
270 /*
271  * Hash codes.
272  */
273 typedef uint32_t hash_t;
274 
275 template <typename TKey>
276 hash_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 
289 ANDROID_INT32_HASH(bool)
290 ANDROID_INT32_HASH(int8_t)
291 ANDROID_INT32_HASH(uint8_t)
292 ANDROID_INT32_HASH(int16_t)
293 ANDROID_INT32_HASH(uint16_t)
294 ANDROID_INT32_HASH(int32_t)
295 ANDROID_INT32_HASH(uint32_t)
296 ANDROID_INT64_HASH(int64_t)
297 ANDROID_INT64_HASH(uint64_t)
298 ANDROID_REINTERPRET_HASH(float, uint32_t)
299 ANDROID_REINTERPRET_HASH(double, uint64_t)
300 
301 template <typename T> inline hash_t hash_type(T* const & value) {
302     return hash_type(uintptr_t(value));
303 }
304 
305 }; // namespace android
306 
307 // ---------------------------------------------------------------------------
308 
309 #endif // ANDROID_TYPE_HELPERS_H
310