1/*
2 *  TypeHelpers.h
3 *
4 *  Copyright 2005 The Android Open Source Project
5 *
6 */
7
8#ifndef ANDROID_TYPE_HELPERS_H
9#define ANDROID_TYPE_HELPERS_H
10
11#include <new>
12#include <stdint.h>
13#include <string.h>
14#include <sys/types.h>
15
16// ---------------------------------------------------------------------------
17
18namespace android {
19
20/*
21 * Types traits
22 */
23
24template <typename T> struct trait_trivial_ctor  { enum { value = false }; };
25template <typename T> struct trait_trivial_dtor  { enum { value = false }; };
26template <typename T> struct trait_trivial_copy  { enum { value = false }; };
27template <typename T> struct trait_trivial_assign{ enum { value = false }; };
28
29template <typename T> struct trait_pointer     { enum { value = false }; };
30template <typename T> struct trait_pointer<T*> { enum { value = true }; };
31
32#define ANDROID_BASIC_TYPES_TRAITS( T )                                       \
33    template<> struct trait_trivial_ctor< T >  { enum { value = true }; };    \
34    template<> struct trait_trivial_dtor< T >  { enum { value = true }; };    \
35    template<> struct trait_trivial_copy< T >  { enum { value = true }; };    \
36    template<> struct trait_trivial_assign< T >{ enum { value = true }; };
37
38#define ANDROID_TYPE_TRAITS( T, ctor, dtor, copy, assign )                    \
39    template<> struct trait_trivial_ctor< T >  { enum { value = ctor }; };    \
40    template<> struct trait_trivial_dtor< T >  { enum { value = dtor }; };    \
41    template<> struct trait_trivial_copy< T >  { enum { value = copy }; };    \
42    template<> struct trait_trivial_assign< T >{ enum { value = assign }; };
43
44template <typename TYPE>
45struct traits {
46    enum {
47        is_pointer          = trait_pointer<TYPE>::value,
48        has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
49        has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
50        has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
51        has_trivial_assign  = is_pointer || trait_trivial_assign<TYPE>::value
52    };
53};
54
55template <typename T, typename U>
56struct aggregate_traits {
57    enum {
58        is_pointer          = false,
59        has_trivial_ctor    = traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
60        has_trivial_dtor    = traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
61        has_trivial_copy    = traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
62        has_trivial_assign  = traits<T>::has_trivial_assign && traits<U>::has_trivial_assign
63    };
64};
65
66// ---------------------------------------------------------------------------
67
68/*
69 * basic types traits
70 */
71
72ANDROID_BASIC_TYPES_TRAITS( void );
73ANDROID_BASIC_TYPES_TRAITS( bool );
74ANDROID_BASIC_TYPES_TRAITS( char );
75ANDROID_BASIC_TYPES_TRAITS( unsigned char );
76ANDROID_BASIC_TYPES_TRAITS( short );
77ANDROID_BASIC_TYPES_TRAITS( unsigned short );
78ANDROID_BASIC_TYPES_TRAITS( int );
79ANDROID_BASIC_TYPES_TRAITS( unsigned int );
80ANDROID_BASIC_TYPES_TRAITS( long );
81ANDROID_BASIC_TYPES_TRAITS( unsigned long );
82ANDROID_BASIC_TYPES_TRAITS( long long );
83ANDROID_BASIC_TYPES_TRAITS( unsigned long long );
84ANDROID_BASIC_TYPES_TRAITS( float );
85ANDROID_BASIC_TYPES_TRAITS( double );
86
87// ---------------------------------------------------------------------------
88
89
90/*
91 * compare and order types
92 */
93
94template<typename TYPE> inline
95int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
96    return (lhs < rhs) ? 1 : 0;
97}
98
99template<typename TYPE> inline
100int compare_type(const TYPE& lhs, const TYPE& rhs) {
101    return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
102}
103
104/*
105 * create, destroy, copy and assign types...
106 */
107
108template<typename TYPE> inline
109void construct_type(TYPE* p, size_t n) {
110    if (!traits<TYPE>::has_trivial_ctor) {
111        while (n--) {
112            new(p++) TYPE;
113        }
114    }
115}
116
117template<typename TYPE> inline
118void destroy_type(TYPE* p, size_t n) {
119    if (!traits<TYPE>::has_trivial_dtor) {
120        while (n--) {
121            p->~TYPE();
122            p++;
123        }
124    }
125}
126
127template<typename TYPE> inline
128void copy_type(TYPE* d, const TYPE* s, size_t n) {
129    if (!traits<TYPE>::has_trivial_copy) {
130        while (n--) {
131            new(d) TYPE(*s);
132            d++, s++;
133        }
134    } else {
135        memcpy(d,s,n*sizeof(TYPE));
136    }
137}
138
139template<typename TYPE> inline
140void assign_type(TYPE* d, const TYPE* s, size_t n) {
141    if (!traits<TYPE>::has_trivial_assign) {
142        while (n--) {
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_copy || !traits<TYPE>::has_trivial_dtor) {
167        d += n;
168        s += n;
169        while (n--) {
170            --d, --s;
171            if (!traits<TYPE>::has_trivial_copy) {
172                new(d) TYPE(*s);
173            } else {
174                *d = *s;
175            }
176            if (!traits<TYPE>::has_trivial_dtor) {
177                s->~TYPE();
178            }
179        }
180    } else {
181        memmove(d,s,n*sizeof(TYPE));
182    }
183}
184
185template<typename TYPE> inline
186void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
187    if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
188        while (n--) {
189            if (!traits<TYPE>::has_trivial_copy) {
190                new(d) TYPE(*s);
191            } else {
192                *d = *s;
193            }
194            if (!traits<TYPE>::has_trivial_dtor) {
195                s->~TYPE();
196            }
197            d++, s++;
198        }
199    } else {
200        memmove(d,s,n*sizeof(TYPE));
201    }
202}
203// ---------------------------------------------------------------------------
204
205/*
206 * a key/value pair
207 */
208
209template <typename KEY, typename VALUE>
210struct key_value_pair_t {
211    KEY     key;
212    VALUE   value;
213    key_value_pair_t() { }
214    key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
215    key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
216    key_value_pair_t(const KEY& k) : key(k) { }
217    inline bool operator < (const key_value_pair_t& o) const {
218        return strictly_order_type(key, o.key);
219    }
220};
221
222template<>
223template <typename K, typename V>
224struct trait_trivial_ctor< key_value_pair_t<K, V> >
225{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
226template<>
227template <typename K, typename V>
228struct trait_trivial_dtor< key_value_pair_t<K, V> >
229{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
230template<>
231template <typename K, typename V>
232struct trait_trivial_copy< key_value_pair_t<K, V> >
233{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
234template<>
235template <typename K, typename V>
236struct trait_trivial_assign< key_value_pair_t<K, V> >
237{ enum { value = aggregate_traits<K,V>::has_trivial_assign};};
238
239// ---------------------------------------------------------------------------
240
241}; // namespace android
242
243// ---------------------------------------------------------------------------
244
245#endif // ANDROID_TYPE_HELPERS_H
246