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_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
77// ---------------------------------------------------------------------------
78
79/*
80 * basic types traits
81 */
82
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 )
97
98// ---------------------------------------------------------------------------
99
100
101/*
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/*
116 * create, destroy, copy and move types...
117 */
118
119template<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
151void 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 {
158        while (n--) {
159            *where++ = *what;
160        }
161    }
162}
163
164template<typename TYPE> inline
165void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
166    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 {
171        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 {
178                *d = *s;
179            }
180            if (!traits<TYPE>::has_trivial_dtor) {
181                s->~TYPE();
182            }
183        }
184    }
185}
186
187template<typename TYPE> inline
188void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
189    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 {
194        while (n--) {
195            if (!traits<TYPE>::has_trivial_copy) {
196                new(d) TYPE(*s);
197            } else {
198                *d = *s;
199            }
200            if (!traits<TYPE>::has_trivial_dtor) {
201                s->~TYPE();
202            }
203            d++, s++;
204        }
205    }
206}
207
208// ---------------------------------------------------------------------------
209
210/*
211 * a key/value pair
212 */
213
214template <typename KEY, typename VALUE>
215struct key_value_pair_t {
216    KEY     key;
217    VALUE   value;
218    key_value_pair_t() { }
219    key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
220    key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
221    key_value_pair_t(const KEY& k) : key(k) { }
222    inline bool operator < (const key_value_pair_t& o) const {
223        return strictly_order_type(key, o.key);
224    }
225};
226
227template<>
228template <typename K, typename V>
229struct trait_trivial_ctor< key_value_pair_t<K, V> >
230{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
231template<>
232template <typename K, typename V>
233struct trait_trivial_dtor< key_value_pair_t<K, V> >
234{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
235template<>
236template <typename K, typename V>
237struct trait_trivial_copy< key_value_pair_t<K, V> >
238{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
239template<>
240template <typename K, typename V>
241struct trait_trivial_move< key_value_pair_t<K, V> >
242{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
243
244// ---------------------------------------------------------------------------
245
246}; // namespace android
247
248// ---------------------------------------------------------------------------
249
250#endif // ANDROID_TYPE_HELPERS_H
251