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 27 namespace android { 28 29 /* 30 * Types traits 31 */ 32 33 template <typename T> struct trait_trivial_ctor { enum { value = false }; }; 34 template <typename T> struct trait_trivial_dtor { enum { value = false }; }; 35 template <typename T> struct trait_trivial_copy { enum { value = false }; }; 36 template <typename T> struct trait_trivial_move { enum { value = false }; }; 37 template <typename T> struct trait_pointer { enum { value = false }; }; 38 template <typename T> struct trait_pointer<T*> { enum { value = true }; }; 39 40 template <typename TYPE> 41 struct 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 56 template <typename T, typename U> 57 struct 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 95 ANDROID_BASIC_TYPES_TRAITS( void ) 96 ANDROID_BASIC_TYPES_TRAITS( bool ) 97 ANDROID_BASIC_TYPES_TRAITS( char ) 98 ANDROID_BASIC_TYPES_TRAITS( unsigned char ) 99 ANDROID_BASIC_TYPES_TRAITS( short ) 100 ANDROID_BASIC_TYPES_TRAITS( unsigned short ) 101 ANDROID_BASIC_TYPES_TRAITS( int ) 102 ANDROID_BASIC_TYPES_TRAITS( unsigned int ) 103 ANDROID_BASIC_TYPES_TRAITS( long ) 104 ANDROID_BASIC_TYPES_TRAITS( unsigned long ) 105 ANDROID_BASIC_TYPES_TRAITS( long long ) 106 ANDROID_BASIC_TYPES_TRAITS( unsigned long long ) 107 ANDROID_BASIC_TYPES_TRAITS( float ) 108 ANDROID_BASIC_TYPES_TRAITS( double ) 109 110 // --------------------------------------------------------------------------- 111 112 113 /* 114 * compare and order types 115 */ 116 117 template<typename TYPE> inline 118 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { 119 return (lhs < rhs) ? 1 : 0; 120 } 121 122 template<typename TYPE> inline 123 int 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 131 template<typename TYPE> inline 132 void construct_type(TYPE* p, size_t n) { 133 if (!traits<TYPE>::has_trivial_ctor) { 134 while (n > 0) { 135 n--; 136 new(p++) TYPE; 137 } 138 } 139 } 140 141 template<typename TYPE> inline 142 void destroy_type(TYPE* p, size_t n) { 143 if (!traits<TYPE>::has_trivial_dtor) { 144 while (n > 0) { 145 n--; 146 p->~TYPE(); 147 p++; 148 } 149 } 150 } 151 152 template<typename TYPE> inline 153 void copy_type(TYPE* d, const TYPE* s, size_t n) { 154 if (!traits<TYPE>::has_trivial_copy) { 155 while (n > 0) { 156 n--; 157 new(d) TYPE(*s); 158 d++, s++; 159 } 160 } else { 161 memcpy(d,s,n*sizeof(TYPE)); 162 } 163 } 164 165 template<typename TYPE> inline 166 void splat_type(TYPE* where, const TYPE* what, size_t n) { 167 if (!traits<TYPE>::has_trivial_copy) { 168 while (n > 0) { 169 n--; 170 new(where) TYPE(*what); 171 where++; 172 } 173 } else { 174 while (n > 0) { 175 n--; 176 *where++ = *what; 177 } 178 } 179 } 180 181 template<typename TYPE> inline 182 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 183 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 184 || traits<TYPE>::has_trivial_move) 185 { 186 memmove(d,s,n*sizeof(TYPE)); 187 } else { 188 d += n; 189 s += n; 190 while (n > 0) { 191 n--; 192 --d, --s; 193 if (!traits<TYPE>::has_trivial_copy) { 194 new(d) TYPE(*s); 195 } else { 196 *d = *s; 197 } 198 if (!traits<TYPE>::has_trivial_dtor) { 199 s->~TYPE(); 200 } 201 } 202 } 203 } 204 205 template<typename TYPE> inline 206 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 207 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 208 || traits<TYPE>::has_trivial_move) 209 { 210 memmove(d,s,n*sizeof(TYPE)); 211 } else { 212 while (n > 0) { 213 n--; 214 if (!traits<TYPE>::has_trivial_copy) { 215 new(d) TYPE(*s); 216 } else { 217 *d = *s; 218 } 219 if (!traits<TYPE>::has_trivial_dtor) { 220 s->~TYPE(); 221 } 222 d++, s++; 223 } 224 } 225 } 226 227 // --------------------------------------------------------------------------- 228 229 /* 230 * a key/value pair 231 */ 232 233 template <typename KEY, typename VALUE> 234 struct key_value_pair_t { 235 typedef KEY key_t; 236 typedef VALUE value_t; 237 238 KEY key; 239 VALUE value; 240 key_value_pair_t() { } 241 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } 242 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } 243 key_value_pair_t(const KEY& k) : key(k) { } 244 inline bool operator < (const key_value_pair_t& o) const { 245 return strictly_order_type(key, o.key); 246 } 247 inline const KEY& getKey() const { 248 return key; 249 } 250 inline const VALUE& getValue() const { 251 return value; 252 } 253 }; 254 255 template <typename K, typename V> 256 struct trait_trivial_ctor< key_value_pair_t<K, V> > 257 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; 258 template <typename K, typename V> 259 struct trait_trivial_dtor< key_value_pair_t<K, V> > 260 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; 261 template <typename K, typename V> 262 struct trait_trivial_copy< key_value_pair_t<K, V> > 263 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; 264 template <typename K, typename V> 265 struct trait_trivial_move< key_value_pair_t<K, V> > 266 { enum { value = aggregate_traits<K,V>::has_trivial_move }; }; 267 268 // --------------------------------------------------------------------------- 269 270 /* 271 * Hash codes. 272 */ 273 typedef uint32_t hash_t; 274 275 template <typename TKey> 276 hash_t hash_type(const TKey& key); 277 278 /* Built-in hash code specializations. 279 * Assumes pointers are 32bit. */ 280 #define ANDROID_INT32_HASH(T) \ 281 template <> inline hash_t hash_type(const T& value) { return hash_t(value); } 282 #define ANDROID_INT64_HASH(T) \ 283 template <> inline hash_t hash_type(const T& value) { \ 284 return hash_t((value >> 32) ^ value); } 285 #define ANDROID_REINTERPRET_HASH(T, R) \ 286 template <> inline hash_t hash_type(const T& value) { \ 287 return hash_type(*reinterpret_cast<const R*>(&value)); } 288 289 ANDROID_INT32_HASH(bool) 290 ANDROID_INT32_HASH(int8_t) 291 ANDROID_INT32_HASH(uint8_t) 292 ANDROID_INT32_HASH(int16_t) 293 ANDROID_INT32_HASH(uint16_t) 294 ANDROID_INT32_HASH(int32_t) 295 ANDROID_INT32_HASH(uint32_t) 296 ANDROID_INT64_HASH(int64_t) 297 ANDROID_INT64_HASH(uint64_t) 298 ANDROID_REINTERPRET_HASH(float, uint32_t) 299 ANDROID_REINTERPRET_HASH(double, uint64_t) 300 301 template <typename T> inline hash_t hash_type(T* const & value) { 302 return hash_type(uintptr_t(value)); 303 } 304 305 }; // namespace android 306 307 // --------------------------------------------------------------------------- 308 309 #endif // ANDROID_TYPE_HELPERS_H 310