Home | History | Annotate | Download | only in utils
      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