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
27namespace android {
28
29/*
30 * Types traits
31 */
32
33template <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 }; };
39
40template <typename TYPE>
41struct 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
56template <typename T, typename U>
57struct 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
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 )
109
110// ---------------------------------------------------------------------------
111
112
113/*
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/*
128 * create, destroy, copy and move types...
129 */
130
131template<typename TYPE> inline
132void 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
140template<typename TYPE> inline
141void 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
150template<typename TYPE> inline
151void 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
162template<typename TYPE> inline
163void 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
176template<typename TYPE> inline
177void 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
199template<typename TYPE> inline
200void 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
226template <typename KEY, typename VALUE>
227struct 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
248template <typename K, typename V>
249struct trait_trivial_ctor< key_value_pair_t<K, V> >
250{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
251template <typename K, typename V>
252struct trait_trivial_dtor< key_value_pair_t<K, V> >
253{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
254template <typename K, typename V>
255struct trait_trivial_copy< key_value_pair_t<K, V> >
256{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
257template <typename K, typename V>
258struct 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 */
266typedef uint32_t hash_t;
267
268template <typename TKey>
269hash_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
282ANDROID_INT32_HASH(bool)
283ANDROID_INT32_HASH(int8_t)
284ANDROID_INT32_HASH(uint8_t)
285ANDROID_INT32_HASH(int16_t)
286ANDROID_INT32_HASH(uint16_t)
287ANDROID_INT32_HASH(int32_t)
288ANDROID_INT32_HASH(uint32_t)
289ANDROID_INT64_HASH(int64_t)
290ANDROID_INT64_HASH(uint64_t)
291ANDROID_REINTERPRET_HASH(float, uint32_t)
292ANDROID_REINTERPRET_HASH(double, uint64_t)
293
294template <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