blob: 2ff2749ba385e32cf7d0338469eef629863cf0a2 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
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 */
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080032
Mathias Agopiana33bd162009-06-22 01:17:46 -070033template <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 }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080039
Mathias Agopiana33bd162009-06-22 01:17:46 -070040// sp<> can be trivially moved
41template <typename T> class sp;
42template <typename T> struct trait_trivial_move< sp<T> >{
43 enum { value = true };
44};
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080045
Mathias Agopiana33bd162009-06-22 01:17:46 -070046// wp<> can be trivially moved
47template <typename T> class wp;
48template <typename T> struct trait_trivial_move< wp<T> >{
49 enum { value = true };
50};
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080051
52template <typename TYPE>
53struct traits {
54 enum {
Mathias Agopiana33bd162009-06-22 01:17:46 -070055 // whether this type is a pointer
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080056 is_pointer = trait_pointer<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070057 // whether this type's constructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080058 has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070059 // whether this type's destructor is a no-op
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080060 has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070061 // whether this type type can be copy-constructed with memcpy
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080062 has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
Mathias Agopiana33bd162009-06-22 01:17:46 -070063 // whether this type can be moved with memmove
64 has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080065 };
66};
67
68template <typename T, typename U>
69struct aggregate_traits {
70 enum {
71 is_pointer = false,
Mathias Agopiana33bd162009-06-22 01:17:46 -070072 has_trivial_ctor =
73 traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
74 has_trivial_dtor =
75 traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
76 has_trivial_copy =
77 traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
78 has_trivial_move =
79 traits<T>::has_trivial_move && traits<U>::has_trivial_move
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080080 };
81};
82
Mathias Agopiana33bd162009-06-22 01:17:46 -070083#define ANDROID_BASIC_TYPES_TRAITS( T ) \
84 template<> struct trait_trivial_ctor< T > { enum { value = true }; }; \
85 template<> struct trait_trivial_dtor< T > { enum { value = true }; }; \
86 template<> struct trait_trivial_copy< T > { enum { value = true }; }; \
87 template<> struct trait_trivial_move< T > { enum { value = true }; };
88
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080089// ---------------------------------------------------------------------------
90
91/*
92 * basic types traits
93 */
Mathias Agopiana33bd162009-06-22 01:17:46 -070094
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 )
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800109
110// ---------------------------------------------------------------------------
111
Mathias Agopiana33bd162009-06-22 01:17:46 -0700112
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800113/*
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/*
Mathias Agopiana33bd162009-06-22 01:17:46 -0700128 * create, destroy, copy and move types...
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800129 */
Mathias Agopiana33bd162009-06-22 01:17:46 -0700130
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800131template<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
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800163void 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 {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700170 while (n--) {
171 *where++ = *what;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800172 }
173 }
174}
175
176template<typename TYPE> inline
177void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700178 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 {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800183 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 {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700190 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800191 }
192 if (!traits<TYPE>::has_trivial_dtor) {
193 s->~TYPE();
194 }
195 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800196 }
197}
198
199template<typename TYPE> inline
200void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700201 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 {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800206 while (n--) {
207 if (!traits<TYPE>::has_trivial_copy) {
208 new(d) TYPE(*s);
209 } else {
Mathias Agopiana33bd162009-06-22 01:17:46 -0700210 *d = *s;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800211 }
212 if (!traits<TYPE>::has_trivial_dtor) {
213 s->~TYPE();
214 }
215 d++, s++;
216 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800217 }
218}
Mathias Agopiana33bd162009-06-22 01:17:46 -0700219
220
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800221// ---------------------------------------------------------------------------
222
223/*
224 * a key/value pair
225 */
226
227template <typename KEY, typename VALUE>
228struct key_value_pair_t {
229 KEY key;
230 VALUE value;
231 key_value_pair_t() { }
232 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
233 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { }
234 key_value_pair_t(const KEY& k) : key(k) { }
235 inline bool operator < (const key_value_pair_t& o) const {
236 return strictly_order_type(key, o.key);
237 }
238};
239
240template<>
241template <typename K, typename V>
242struct trait_trivial_ctor< key_value_pair_t<K, V> >
243{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
244template<>
245template <typename K, typename V>
246struct trait_trivial_dtor< key_value_pair_t<K, V> >
247{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
248template<>
249template <typename K, typename V>
250struct trait_trivial_copy< key_value_pair_t<K, V> >
251{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
252template<>
253template <typename K, typename V>
Mathias Agopiana33bd162009-06-22 01:17:46 -0700254struct trait_trivial_move< key_value_pair_t<K, V> >
255{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800256
257// ---------------------------------------------------------------------------
258
259}; // namespace android
260
261// ---------------------------------------------------------------------------
262
263#endif // ANDROID_TYPE_HELPERS_H