1/* 2 * Copyright (C) 2013 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_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 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 ) 109 110// --------------------------------------------------------------------------- 111 112 113/* 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/* 128 * create, destroy, copy and move types... 129 */ 130 131template<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 163void 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 { 170 while (n--) { 171 *where++ = *what; 172 } 173 } 174} 175 176template<typename TYPE> inline 177void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 178 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 { 183 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 { 190 *d = *s; 191 } 192 if (!traits<TYPE>::has_trivial_dtor) { 193 s->~TYPE(); 194 } 195 } 196 } 197} 198 199template<typename TYPE> inline 200void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 201 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 { 206 while (n--) { 207 if (!traits<TYPE>::has_trivial_copy) { 208 new(d) TYPE(*s); 209 } else { 210 *d = *s; 211 } 212 if (!traits<TYPE>::has_trivial_dtor) { 213 s->~TYPE(); 214 } 215 d++, s++; 216 } 217 } 218} 219 220// --------------------------------------------------------------------------- 221 222/* 223 * a key/value pair 224 */ 225 226template <typename KEY, typename VALUE> 227struct key_value_pair_t { 228 typedef KEY key_t; 229 typedef VALUE value_t; 230 231 KEY key; 232 VALUE value; 233 key_value_pair_t() { } 234 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } 235 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } 236 key_value_pair_t(const KEY& k) : key(k) { } 237 inline bool operator < (const key_value_pair_t& o) const { 238 return strictly_order_type(key, o.key); 239 } 240 inline const KEY& getKey() const { 241 return key; 242 } 243 inline const VALUE& getValue() const { 244 return value; 245 } 246}; 247 248template <typename K, typename V> 249struct trait_trivial_ctor< key_value_pair_t<K, V> > 250{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; 251template <typename K, typename V> 252struct trait_trivial_dtor< key_value_pair_t<K, V> > 253{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; 254template <typename K, typename V> 255struct trait_trivial_copy< key_value_pair_t<K, V> > 256{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; 257template <typename K, typename V> 258struct trait_trivial_move< key_value_pair_t<K, V> > 259{ enum { value = aggregate_traits<K,V>::has_trivial_move }; }; 260 261// --------------------------------------------------------------------------- 262 263/* 264 * Hash codes. 265 */ 266typedef uint32_t hash_t; 267 268template <typename TKey> 269hash_t hash_type(const TKey& key); 270 271/* Built-in hash code specializations. 272 * Assumes pointers are 32bit. */ 273#define ANDROID_INT32_HASH(T) \ 274 template <> inline hash_t hash_type(const T& value) { return hash_t(value); } 275#define ANDROID_INT64_HASH(T) \ 276 template <> inline hash_t hash_type(const T& value) { \ 277 return hash_t((value >> 32) ^ value); } 278#define ANDROID_REINTERPRET_HASH(T, R) \ 279 template <> inline hash_t hash_type(const T& value) { \ 280 return hash_type(*reinterpret_cast<const R*>(&value)); } 281 282ANDROID_INT32_HASH(bool) 283ANDROID_INT32_HASH(int8_t) 284ANDROID_INT32_HASH(uint8_t) 285ANDROID_INT32_HASH(int16_t) 286ANDROID_INT32_HASH(uint16_t) 287ANDROID_INT32_HASH(int32_t) 288ANDROID_INT32_HASH(uint32_t) 289ANDROID_INT64_HASH(int64_t) 290ANDROID_INT64_HASH(uint64_t) 291ANDROID_REINTERPRET_HASH(float, uint32_t) 292ANDROID_REINTERPRET_HASH(double, uint64_t) 293 294template <typename T> inline hash_t hash_type(T* const & value) { 295 return hash_type(uintptr_t(value)); 296} 297 298}; // namespace android 299 300// --------------------------------------------------------------------------- 301 302#endif // ANDROID_TYPE_HELPERS_H 303