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