/* * Copyright (C) 2005 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_TYPE_HELPERS_H #define ANDROID_TYPE_HELPERS_H #include <new> #include <type_traits> #include <stdint.h> #include <string.h> #include <sys/types.h> // --------------------------------------------------------------------------- namespace android { /* * Types traits */ template <typename T> struct trait_trivial_ctor { enum { value = false }; }; template <typename T> struct trait_trivial_dtor { enum { value = false }; }; template <typename T> struct trait_trivial_copy { enum { value = false }; }; template <typename T> struct trait_trivial_move { enum { value = false }; }; template <typename T> struct trait_pointer { enum { value = false }; }; template <typename T> struct trait_pointer<T*> { enum { value = true }; }; template <typename TYPE> struct traits { enum { // whether this type is a pointer is_pointer = trait_pointer<TYPE>::value, // whether this type's constructor is a no-op has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value, // whether this type's destructor is a no-op has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value, // whether this type type can be copy-constructed with memcpy has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value, // whether this type can be moved with memmove has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value }; }; template <typename T, typename U> struct aggregate_traits { enum { is_pointer = false, has_trivial_ctor = traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor, has_trivial_dtor = traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor, has_trivial_copy = traits<T>::has_trivial_copy && traits<U>::has_trivial_copy, has_trivial_move = traits<T>::has_trivial_move && traits<U>::has_trivial_move }; }; #define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ template<> struct trait_trivial_ctor< T > { enum { value = true }; }; #define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ template<> struct trait_trivial_dtor< T > { enum { value = true }; }; #define ANDROID_TRIVIAL_COPY_TRAIT( T ) \ template<> struct trait_trivial_copy< T > { enum { value = true }; }; #define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \ template<> struct trait_trivial_move< T > { enum { value = true }; }; #define ANDROID_BASIC_TYPES_TRAITS( T ) \ ANDROID_TRIVIAL_CTOR_TRAIT( T ) \ ANDROID_TRIVIAL_DTOR_TRAIT( T ) \ ANDROID_TRIVIAL_COPY_TRAIT( T ) \ ANDROID_TRIVIAL_MOVE_TRAIT( T ) // --------------------------------------------------------------------------- /* * basic types traits */ ANDROID_BASIC_TYPES_TRAITS( void ) ANDROID_BASIC_TYPES_TRAITS( bool ) ANDROID_BASIC_TYPES_TRAITS( char ) ANDROID_BASIC_TYPES_TRAITS( unsigned char ) ANDROID_BASIC_TYPES_TRAITS( short ) ANDROID_BASIC_TYPES_TRAITS( unsigned short ) ANDROID_BASIC_TYPES_TRAITS( int ) ANDROID_BASIC_TYPES_TRAITS( unsigned int ) ANDROID_BASIC_TYPES_TRAITS( long ) ANDROID_BASIC_TYPES_TRAITS( unsigned long ) ANDROID_BASIC_TYPES_TRAITS( long long ) ANDROID_BASIC_TYPES_TRAITS( unsigned long long ) ANDROID_BASIC_TYPES_TRAITS( float ) ANDROID_BASIC_TYPES_TRAITS( double ) // --------------------------------------------------------------------------- /* * compare and order types */ template<typename TYPE> inline int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { return (lhs < rhs) ? 1 : 0; } template<typename TYPE> inline int compare_type(const TYPE& lhs, const TYPE& rhs) { return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs); } /* * create, destroy, copy and move types... */ template<typename TYPE> inline void construct_type(TYPE* p, size_t n) { if (!traits<TYPE>::has_trivial_ctor) { while (n > 0) { n--; new(p++) TYPE; } } } template<typename TYPE> inline void destroy_type(TYPE* p, size_t n) { if (!traits<TYPE>::has_trivial_dtor) { while (n > 0) { n--; p->~TYPE(); p++; } } } template<typename TYPE> typename std::enable_if<traits<TYPE>::has_trivial_copy>::type inline copy_type(TYPE* d, const TYPE* s, size_t n) { memcpy(d,s,n*sizeof(TYPE)); } template<typename TYPE> typename std::enable_if<!traits<TYPE>::has_trivial_copy>::type inline copy_type(TYPE* d, const TYPE* s, size_t n) { while (n > 0) { n--; new(d) TYPE(*s); d++, s++; } } template<typename TYPE> inline void splat_type(TYPE* where, const TYPE* what, size_t n) { if (!traits<TYPE>::has_trivial_copy) { while (n > 0) { n--; new(where) TYPE(*what); where++; } } else { while (n > 0) { n--; *where++ = *what; } } } template<typename TYPE> struct use_trivial_move : public std::integral_constant<bool, (traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) || traits<TYPE>::has_trivial_move > {}; template<typename TYPE> typename std::enable_if<use_trivial_move<TYPE>::value>::type inline move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { memmove(d, s, n*sizeof(TYPE)); } template<typename TYPE> typename std::enable_if<!use_trivial_move<TYPE>::value>::type inline move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { d += n; s += n; while (n > 0) { n--; --d, --s; if (!traits<TYPE>::has_trivial_copy) { new(d) TYPE(*s); } else { *d = *s; } if (!traits<TYPE>::has_trivial_dtor) { s->~TYPE(); } } } template<typename TYPE> typename std::enable_if<use_trivial_move<TYPE>::value>::type inline move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { memmove(d, s, n*sizeof(TYPE)); } template<typename TYPE> typename std::enable_if<!use_trivial_move<TYPE>::value>::type inline move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { while (n > 0) { n--; if (!traits<TYPE>::has_trivial_copy) { new(d) TYPE(*s); } else { *d = *s; } if (!traits<TYPE>::has_trivial_dtor) { s->~TYPE(); } d++, s++; } } // --------------------------------------------------------------------------- /* * a key/value pair */ template <typename KEY, typename VALUE> struct key_value_pair_t { typedef KEY key_t; typedef VALUE value_t; KEY key; VALUE value; key_value_pair_t() { } key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } key_value_pair_t& operator=(const key_value_pair_t& o) { key = o.key; value = o.value; return *this; } key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } explicit key_value_pair_t(const KEY& k) : key(k) { } inline bool operator < (const key_value_pair_t& o) const { return strictly_order_type(key, o.key); } inline const KEY& getKey() const { return key; } inline const VALUE& getValue() const { return value; } }; template <typename K, typename V> struct trait_trivial_ctor< key_value_pair_t<K, V> > { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; template <typename K, typename V> struct trait_trivial_dtor< key_value_pair_t<K, V> > { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; template <typename K, typename V> struct trait_trivial_copy< key_value_pair_t<K, V> > { enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; template <typename K, typename V> struct trait_trivial_move< key_value_pair_t<K, V> > { enum { value = aggregate_traits<K,V>::has_trivial_move }; }; // --------------------------------------------------------------------------- /* * Hash codes. */ typedef uint32_t hash_t; template <typename TKey> hash_t hash_type(const TKey& key); /* Built-in hash code specializations */ #define ANDROID_INT32_HASH(T) \ template <> inline hash_t hash_type(const T& value) { return hash_t(value); } #define ANDROID_INT64_HASH(T) \ template <> inline hash_t hash_type(const T& value) { \ return hash_t((value >> 32) ^ value); } #define ANDROID_REINTERPRET_HASH(T, R) \ template <> inline hash_t hash_type(const T& value) { \ R newValue; \ static_assert(sizeof(newValue) == sizeof(value), "size mismatch"); \ memcpy(&newValue, &value, sizeof(newValue)); \ return hash_type(newValue); \ } ANDROID_INT32_HASH(bool) ANDROID_INT32_HASH(int8_t) ANDROID_INT32_HASH(uint8_t) ANDROID_INT32_HASH(int16_t) ANDROID_INT32_HASH(uint16_t) ANDROID_INT32_HASH(int32_t) ANDROID_INT32_HASH(uint32_t) ANDROID_INT64_HASH(int64_t) ANDROID_INT64_HASH(uint64_t) ANDROID_REINTERPRET_HASH(float, uint32_t) ANDROID_REINTERPRET_HASH(double, uint64_t) template <typename T> inline hash_t hash_type(T* const & value) { return hash_type(uintptr_t(value)); } }; // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_TYPE_HELPERS_H