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 <type_traits> 22 23 #include <stdint.h> 24 #include <string.h> 25 #include <sys/types.h> 26 27 // --------------------------------------------------------------------------- 28 29 namespace android { 30 31 /* 32 * Types traits 33 */ 34 35 template <typename T> struct trait_trivial_ctor { enum { value = false }; }; 36 template <typename T> struct trait_trivial_dtor { enum { value = false }; }; 37 template <typename T> struct trait_trivial_copy { enum { value = false }; }; 38 template <typename T> struct trait_trivial_move { enum { value = false }; }; 39 template <typename T> struct trait_pointer { enum { value = false }; }; 40 template <typename T> struct trait_pointer<T*> { enum { value = true }; }; 41 42 template <typename TYPE> 43 struct traits { 44 enum { 45 // whether this type is a pointer 46 is_pointer = trait_pointer<TYPE>::value, 47 // whether this type's constructor is a no-op 48 has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value, 49 // whether this type's destructor is a no-op 50 has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value, 51 // whether this type type can be copy-constructed with memcpy 52 has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value, 53 // whether this type can be moved with memmove 54 has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value 55 }; 56 }; 57 58 template <typename T, typename U> 59 struct aggregate_traits { 60 enum { 61 is_pointer = false, 62 has_trivial_ctor = 63 traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor, 64 has_trivial_dtor = 65 traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor, 66 has_trivial_copy = 67 traits<T>::has_trivial_copy && traits<U>::has_trivial_copy, 68 has_trivial_move = 69 traits<T>::has_trivial_move && traits<U>::has_trivial_move 70 }; 71 }; 72 73 #define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ 74 template<> struct trait_trivial_ctor< T > { enum { value = true }; }; 75 76 #define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ 77 template<> struct trait_trivial_dtor< T > { enum { value = true }; }; 78 79 #define ANDROID_TRIVIAL_COPY_TRAIT( T ) \ 80 template<> struct trait_trivial_copy< T > { enum { value = true }; }; 81 82 #define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \ 83 template<> struct trait_trivial_move< T > { enum { value = true }; }; 84 85 #define ANDROID_BASIC_TYPES_TRAITS( T ) \ 86 ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ 87 ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ 88 ANDROID_TRIVIAL_COPY_TRAIT( T ) \ 89 ANDROID_TRIVIAL_MOVE_TRAIT( T ) 90 91 // --------------------------------------------------------------------------- 92 93 /* 94 * basic types traits 95 */ 96 97 ANDROID_BASIC_TYPES_TRAITS( void ) 98 ANDROID_BASIC_TYPES_TRAITS( bool ) 99 ANDROID_BASIC_TYPES_TRAITS( char ) 100 ANDROID_BASIC_TYPES_TRAITS( unsigned char ) 101 ANDROID_BASIC_TYPES_TRAITS( short ) 102 ANDROID_BASIC_TYPES_TRAITS( unsigned short ) 103 ANDROID_BASIC_TYPES_TRAITS( int ) 104 ANDROID_BASIC_TYPES_TRAITS( unsigned int ) 105 ANDROID_BASIC_TYPES_TRAITS( long ) 106 ANDROID_BASIC_TYPES_TRAITS( unsigned long ) 107 ANDROID_BASIC_TYPES_TRAITS( long long ) 108 ANDROID_BASIC_TYPES_TRAITS( unsigned long long ) 109 ANDROID_BASIC_TYPES_TRAITS( float ) 110 ANDROID_BASIC_TYPES_TRAITS( double ) 111 112 // --------------------------------------------------------------------------- 113 114 115 /* 116 * compare and order types 117 */ 118 119 template<typename TYPE> inline 120 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { 121 return (lhs < rhs) ? 1 : 0; 122 } 123 124 template<typename TYPE> inline 125 int compare_type(const TYPE& lhs, const TYPE& rhs) { 126 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs); 127 } 128 129 /* 130 * create, destroy, copy and move types... 131 */ 132 133 template<typename TYPE> inline 134 void construct_type(TYPE* p, size_t n) { 135 if (!traits<TYPE>::has_trivial_ctor) { 136 while (n > 0) { 137 n--; 138 new(p++) TYPE; 139 } 140 } 141 } 142 143 template<typename TYPE> inline 144 void destroy_type(TYPE* p, size_t n) { 145 if (!traits<TYPE>::has_trivial_dtor) { 146 while (n > 0) { 147 n--; 148 p->~TYPE(); 149 p++; 150 } 151 } 152 } 153 154 template<typename TYPE> 155 typename std::enable_if<traits<TYPE>::has_trivial_copy>::type 156 inline 157 copy_type(TYPE* d, const TYPE* s, size_t n) { 158 memcpy(d,s,n*sizeof(TYPE)); 159 } 160 161 template<typename TYPE> 162 typename std::enable_if<!traits<TYPE>::has_trivial_copy>::type 163 inline 164 copy_type(TYPE* d, const TYPE* s, size_t n) { 165 while (n > 0) { 166 n--; 167 new(d) TYPE(*s); 168 d++, s++; 169 } 170 } 171 172 template<typename TYPE> inline 173 void splat_type(TYPE* where, const TYPE* what, size_t n) { 174 if (!traits<TYPE>::has_trivial_copy) { 175 while (n > 0) { 176 n--; 177 new(where) TYPE(*what); 178 where++; 179 } 180 } else { 181 while (n > 0) { 182 n--; 183 *where++ = *what; 184 } 185 } 186 } 187 188 template<typename TYPE> 189 struct use_trivial_move : public std::integral_constant<bool, 190 (traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 191 || traits<TYPE>::has_trivial_move 192 > {}; 193 194 template<typename TYPE> 195 typename std::enable_if<use_trivial_move<TYPE>::value>::type 196 inline 197 move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 198 memmove(d, s, n*sizeof(TYPE)); 199 } 200 201 template<typename TYPE> 202 typename std::enable_if<!use_trivial_move<TYPE>::value>::type 203 inline 204 move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 205 d += n; 206 s += n; 207 while (n > 0) { 208 n--; 209 --d, --s; 210 if (!traits<TYPE>::has_trivial_copy) { 211 new(d) TYPE(*s); 212 } else { 213 *d = *s; 214 } 215 if (!traits<TYPE>::has_trivial_dtor) { 216 s->~TYPE(); 217 } 218 } 219 } 220 221 template<typename TYPE> 222 typename std::enable_if<use_trivial_move<TYPE>::value>::type 223 inline 224 move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 225 memmove(d, s, n*sizeof(TYPE)); 226 } 227 228 template<typename TYPE> 229 typename std::enable_if<!use_trivial_move<TYPE>::value>::type 230 inline 231 move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 232 while (n > 0) { 233 n--; 234 if (!traits<TYPE>::has_trivial_copy) { 235 new(d) TYPE(*s); 236 } else { 237 *d = *s; 238 } 239 if (!traits<TYPE>::has_trivial_dtor) { 240 s->~TYPE(); 241 } 242 d++, s++; 243 } 244 } 245 246 // --------------------------------------------------------------------------- 247 248 /* 249 * a key/value pair 250 */ 251 252 template <typename KEY, typename VALUE> 253 struct key_value_pair_t { 254 typedef KEY key_t; 255 typedef VALUE value_t; 256 257 KEY key; 258 VALUE value; 259 key_value_pair_t() { } 260 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } 261 key_value_pair_t& operator=(const key_value_pair_t& o) { 262 key = o.key; 263 value = o.value; 264 return *this; 265 } 266 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } 267 explicit key_value_pair_t(const KEY& k) : key(k) { } 268 inline bool operator < (const key_value_pair_t& o) const { 269 return strictly_order_type(key, o.key); 270 } 271 inline const KEY& getKey() const { 272 return key; 273 } 274 inline const VALUE& getValue() const { 275 return value; 276 } 277 }; 278 279 template <typename K, typename V> 280 struct trait_trivial_ctor< key_value_pair_t<K, V> > 281 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; 282 template <typename K, typename V> 283 struct trait_trivial_dtor< key_value_pair_t<K, V> > 284 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; 285 template <typename K, typename V> 286 struct trait_trivial_copy< key_value_pair_t<K, V> > 287 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; 288 template <typename K, typename V> 289 struct trait_trivial_move< key_value_pair_t<K, V> > 290 { enum { value = aggregate_traits<K,V>::has_trivial_move }; }; 291 292 // --------------------------------------------------------------------------- 293 294 /* 295 * Hash codes. 296 */ 297 typedef uint32_t hash_t; 298 299 template <typename TKey> 300 hash_t hash_type(const TKey& key); 301 302 /* Built-in hash code specializations */ 303 #define ANDROID_INT32_HASH(T) \ 304 template <> inline hash_t hash_type(const T& value) { return hash_t(value); } 305 #define ANDROID_INT64_HASH(T) \ 306 template <> inline hash_t hash_type(const T& value) { \ 307 return hash_t((value >> 32) ^ value); } 308 #define ANDROID_REINTERPRET_HASH(T, R) \ 309 template <> inline hash_t hash_type(const T& value) { \ 310 R newValue; \ 311 static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \ 312 memcpy(&newValue, &value, sizeof(newValue)); \ 313 return hash_type(newValue); \ 314 } 315 316 ANDROID_INT32_HASH(bool) 317 ANDROID_INT32_HASH(int8_t) 318 ANDROID_INT32_HASH(uint8_t) 319 ANDROID_INT32_HASH(int16_t) 320 ANDROID_INT32_HASH(uint16_t) 321 ANDROID_INT32_HASH(int32_t) 322 ANDROID_INT32_HASH(uint32_t) 323 ANDROID_INT64_HASH(int64_t) 324 ANDROID_INT64_HASH(uint64_t) 325 ANDROID_REINTERPRET_HASH(float, uint32_t) 326 ANDROID_REINTERPRET_HASH(double, uint64_t) 327 328 template <typename T> inline hash_t hash_type(T* const & value) { 329 return hash_type(uintptr_t(value)); 330 } 331 332 } // namespace android 333 334 // --------------------------------------------------------------------------- 335 336 #endif // ANDROID_TYPE_HELPERS_H 337