TypeHelpers.h revision 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407
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_assign{ enum { value = false }; };
37
38template <typename T> struct trait_pointer     { enum { value = false }; };
39template <typename T> struct trait_pointer<T*> { enum { value = true }; };
40
41#define ANDROID_BASIC_TYPES_TRAITS( T )                                       \
42    template<> struct trait_trivial_ctor< T >  { enum { value = true }; };    \
43    template<> struct trait_trivial_dtor< T >  { enum { value = true }; };    \
44    template<> struct trait_trivial_copy< T >  { enum { value = true }; };    \
45    template<> struct trait_trivial_assign< T >{ enum { value = true }; };
46
47#define ANDROID_TYPE_TRAITS( T, ctor, dtor, copy, assign )                    \
48    template<> struct trait_trivial_ctor< T >  { enum { value = ctor }; };    \
49    template<> struct trait_trivial_dtor< T >  { enum { value = dtor }; };    \
50    template<> struct trait_trivial_copy< T >  { enum { value = copy }; };    \
51    template<> struct trait_trivial_assign< T >{ enum { value = assign }; };
52
53template <typename TYPE>
54struct traits {
55    enum {
56        is_pointer          = trait_pointer<TYPE>::value,
57        has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
58        has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
59        has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
60        has_trivial_assign  = is_pointer || trait_trivial_assign<TYPE>::value
61    };
62};
63
64template <typename T, typename U>
65struct aggregate_traits {
66    enum {
67        is_pointer          = false,
68        has_trivial_ctor    = traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
69        has_trivial_dtor    = traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
70        has_trivial_copy    = traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
71        has_trivial_assign  = traits<T>::has_trivial_assign && traits<U>::has_trivial_assign
72    };
73};
74
75// ---------------------------------------------------------------------------
76
77/*
78 * basic types traits
79 */
80
81ANDROID_BASIC_TYPES_TRAITS( void );
82ANDROID_BASIC_TYPES_TRAITS( bool );
83ANDROID_BASIC_TYPES_TRAITS( char );
84ANDROID_BASIC_TYPES_TRAITS( unsigned char );
85ANDROID_BASIC_TYPES_TRAITS( short );
86ANDROID_BASIC_TYPES_TRAITS( unsigned short );
87ANDROID_BASIC_TYPES_TRAITS( int );
88ANDROID_BASIC_TYPES_TRAITS( unsigned int );
89ANDROID_BASIC_TYPES_TRAITS( long );
90ANDROID_BASIC_TYPES_TRAITS( unsigned long );
91ANDROID_BASIC_TYPES_TRAITS( long long );
92ANDROID_BASIC_TYPES_TRAITS( unsigned long long );
93ANDROID_BASIC_TYPES_TRAITS( float );
94ANDROID_BASIC_TYPES_TRAITS( double );
95
96// ---------------------------------------------------------------------------
97
98
99/*
100 * compare and order types
101 */
102
103template<typename TYPE> inline
104int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
105    return (lhs < rhs) ? 1 : 0;
106}
107
108template<typename TYPE> inline
109int compare_type(const TYPE& lhs, const TYPE& rhs) {
110    return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
111}
112
113/*
114 * create, destroy, copy and assign types...
115 */
116
117template<typename TYPE> inline
118void construct_type(TYPE* p, size_t n) {
119    if (!traits<TYPE>::has_trivial_ctor) {
120        while (n--) {
121            new(p++) TYPE;
122        }
123    }
124}
125
126template<typename TYPE> inline
127void destroy_type(TYPE* p, size_t n) {
128    if (!traits<TYPE>::has_trivial_dtor) {
129        while (n--) {
130            p->~TYPE();
131            p++;
132        }
133    }
134}
135
136template<typename TYPE> inline
137void copy_type(TYPE* d, const TYPE* s, size_t n) {
138    if (!traits<TYPE>::has_trivial_copy) {
139        while (n--) {
140            new(d) TYPE(*s);
141            d++, s++;
142        }
143    } else {
144        memcpy(d,s,n*sizeof(TYPE));
145    }
146}
147
148template<typename TYPE> inline
149void assign_type(TYPE* d, const TYPE* s, size_t n) {
150    if (!traits<TYPE>::has_trivial_assign) {
151        while (n--) {
152            *d++ = *s++;
153        }
154    } else {
155        memcpy(d,s,n*sizeof(TYPE));
156    }
157}
158
159template<typename TYPE> inline
160void splat_type(TYPE* where, const TYPE* what, size_t n) {
161    if (!traits<TYPE>::has_trivial_copy) {
162        while (n--) {
163            new(where) TYPE(*what);
164            where++;
165        }
166    } else {
167         while (n--) {
168             *where++ = *what;
169        }
170    }
171}
172
173template<typename TYPE> inline
174void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
175    if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
176        d += n;
177        s += n;
178        while (n--) {
179            --d, --s;
180            if (!traits<TYPE>::has_trivial_copy) {
181                new(d) TYPE(*s);
182            } else {
183                *d = *s;
184            }
185            if (!traits<TYPE>::has_trivial_dtor) {
186                s->~TYPE();
187            }
188        }
189    } else {
190        memmove(d,s,n*sizeof(TYPE));
191    }
192}
193
194template<typename TYPE> inline
195void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
196    if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
197        while (n--) {
198            if (!traits<TYPE>::has_trivial_copy) {
199                new(d) TYPE(*s);
200            } else {
201                *d = *s;
202            }
203            if (!traits<TYPE>::has_trivial_dtor) {
204                s->~TYPE();
205            }
206            d++, s++;
207        }
208    } else {
209        memmove(d,s,n*sizeof(TYPE));
210    }
211}
212// ---------------------------------------------------------------------------
213
214/*
215 * a key/value pair
216 */
217
218template <typename KEY, typename VALUE>
219struct key_value_pair_t {
220    KEY     key;
221    VALUE   value;
222    key_value_pair_t() { }
223    key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
224    key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
225    key_value_pair_t(const KEY& k) : key(k) { }
226    inline bool operator < (const key_value_pair_t& o) const {
227        return strictly_order_type(key, o.key);
228    }
229};
230
231template<>
232template <typename K, typename V>
233struct trait_trivial_ctor< key_value_pair_t<K, V> >
234{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
235template<>
236template <typename K, typename V>
237struct trait_trivial_dtor< key_value_pair_t<K, V> >
238{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
239template<>
240template <typename K, typename V>
241struct trait_trivial_copy< key_value_pair_t<K, V> >
242{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
243template<>
244template <typename K, typename V>
245struct trait_trivial_assign< key_value_pair_t<K, V> >
246{ enum { value = aggregate_traits<K,V>::has_trivial_assign};};
247
248// ---------------------------------------------------------------------------
249
250}; // namespace android
251
252// ---------------------------------------------------------------------------
253
254#endif // ANDROID_TYPE_HELPERS_H
255