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 <stdint.h>
     22 #include <string.h>
     23 #include <sys/types.h>
     24 
     25 // ---------------------------------------------------------------------------
     26 
     27 namespace android {
     28 
     29 /*
     30  * Types traits
     31  */
     32 
     33 template <typename T> struct trait_trivial_ctor { enum { value = false }; };
     34 template <typename T> struct trait_trivial_dtor { enum { value = false }; };
     35 template <typename T> struct trait_trivial_copy { enum { value = false }; };
     36 template <typename T> struct trait_trivial_move { enum { value = false }; };
     37 template <typename T> struct trait_pointer      { enum { value = false }; };
     38 template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
     39 
     40 template <typename TYPE>
     41 struct 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 
     56 template <typename T, typename U>
     57 struct 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 
     95 ANDROID_BASIC_TYPES_TRAITS( void )
     96 ANDROID_BASIC_TYPES_TRAITS( bool )
     97 ANDROID_BASIC_TYPES_TRAITS( char )
     98 ANDROID_BASIC_TYPES_TRAITS( unsigned char )
     99 ANDROID_BASIC_TYPES_TRAITS( short )
    100 ANDROID_BASIC_TYPES_TRAITS( unsigned short )
    101 ANDROID_BASIC_TYPES_TRAITS( int )
    102 ANDROID_BASIC_TYPES_TRAITS( unsigned int )
    103 ANDROID_BASIC_TYPES_TRAITS( long )
    104 ANDROID_BASIC_TYPES_TRAITS( unsigned long )
    105 ANDROID_BASIC_TYPES_TRAITS( long long )
    106 ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
    107 ANDROID_BASIC_TYPES_TRAITS( float )
    108 ANDROID_BASIC_TYPES_TRAITS( double )
    109 
    110 // ---------------------------------------------------------------------------
    111 
    112 
    113 /*
    114  * compare and order types
    115  */
    116 
    117 template<typename TYPE> inline
    118 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
    119     return (lhs < rhs) ? 1 : 0;
    120 }
    121 
    122 template<typename TYPE> inline
    123 int 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 
    131 template<typename TYPE> inline
    132 void construct_type(TYPE* p, size_t n) {
    133     if (!traits<TYPE>::has_trivial_ctor) {
    134         while (n > 0) {
    135             n--;
    136             new(p++) TYPE;
    137         }
    138     }
    139 }
    140 
    141 template<typename TYPE> inline
    142 void destroy_type(TYPE* p, size_t n) {
    143     if (!traits<TYPE>::has_trivial_dtor) {
    144         while (n > 0) {
    145             n--;
    146             p->~TYPE();
    147             p++;
    148         }
    149     }
    150 }
    151 
    152 template<typename TYPE> inline
    153 void copy_type(TYPE* d, const TYPE* s, size_t n) {
    154     if (!traits<TYPE>::has_trivial_copy) {
    155         while (n > 0) {
    156             n--;
    157             new(d) TYPE(*s);
    158             d++, s++;
    159         }
    160     } else {
    161         memcpy(d,s,n*sizeof(TYPE));
    162     }
    163 }
    164 
    165 template<typename TYPE> inline
    166 void splat_type(TYPE* where, const TYPE* what, size_t n) {
    167     if (!traits<TYPE>::has_trivial_copy) {
    168         while (n > 0) {
    169             n--;
    170             new(where) TYPE(*what);
    171             where++;
    172         }
    173     } else {
    174         while (n > 0) {
    175             n--;
    176             *where++ = *what;
    177         }
    178     }
    179 }
    180 
    181 template<typename TYPE> inline
    182 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
    183     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
    184             || traits<TYPE>::has_trivial_move)
    185     {
    186         memmove(d,s,n*sizeof(TYPE));
    187     } else {
    188         d += n;
    189         s += n;
    190         while (n > 0) {
    191             n--;
    192             --d, --s;
    193             if (!traits<TYPE>::has_trivial_copy) {
    194                 new(d) TYPE(*s);
    195             } else {
    196                 *d = *s;
    197             }
    198             if (!traits<TYPE>::has_trivial_dtor) {
    199                 s->~TYPE();
    200             }
    201         }
    202     }
    203 }
    204 
    205 template<typename TYPE> inline
    206 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
    207     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
    208             || traits<TYPE>::has_trivial_move)
    209     {
    210         memmove(d,s,n*sizeof(TYPE));
    211     } else {
    212         while (n > 0) {
    213             n--;
    214             if (!traits<TYPE>::has_trivial_copy) {
    215                 new(d) TYPE(*s);
    216             } else {
    217                 *d = *s;
    218             }
    219             if (!traits<TYPE>::has_trivial_dtor) {
    220                 s->~TYPE();
    221             }
    222             d++, s++;
    223         }
    224     }
    225 }
    226 
    227 // ---------------------------------------------------------------------------
    228 
    229 /*
    230  * a key/value pair
    231  */
    232 
    233 template <typename KEY, typename VALUE>
    234 struct key_value_pair_t {
    235     typedef KEY key_t;
    236     typedef VALUE value_t;
    237 
    238     KEY     key;
    239     VALUE   value;
    240     key_value_pair_t() { }
    241     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
    242     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
    243     key_value_pair_t(const KEY& k) : key(k) { }
    244     inline bool operator < (const key_value_pair_t& o) const {
    245         return strictly_order_type(key, o.key);
    246     }
    247     inline const KEY& getKey() const {
    248         return key;
    249     }
    250     inline const VALUE& getValue() const {
    251         return value;
    252     }
    253 };
    254 
    255 template <typename K, typename V>
    256 struct trait_trivial_ctor< key_value_pair_t<K, V> >
    257 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
    258 template <typename K, typename V>
    259 struct trait_trivial_dtor< key_value_pair_t<K, V> >
    260 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
    261 template <typename K, typename V>
    262 struct trait_trivial_copy< key_value_pair_t<K, V> >
    263 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
    264 template <typename K, typename V>
    265 struct trait_trivial_move< key_value_pair_t<K, V> >
    266 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
    267 
    268 // ---------------------------------------------------------------------------
    269 
    270 /*
    271  * Hash codes.
    272  */
    273 typedef uint32_t hash_t;
    274 
    275 template <typename TKey>
    276 hash_t hash_type(const TKey& key);
    277 
    278 /* Built-in hash code specializations.
    279  * Assumes pointers are 32bit. */
    280 #define ANDROID_INT32_HASH(T) \
    281         template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
    282 #define ANDROID_INT64_HASH(T) \
    283         template <> inline hash_t hash_type(const T& value) { \
    284                 return hash_t((value >> 32) ^ value); }
    285 #define ANDROID_REINTERPRET_HASH(T, R) \
    286         template <> inline hash_t hash_type(const T& value) { \
    287                 return hash_type(*reinterpret_cast<const R*>(&value)); }
    288 
    289 ANDROID_INT32_HASH(bool)
    290 ANDROID_INT32_HASH(int8_t)
    291 ANDROID_INT32_HASH(uint8_t)
    292 ANDROID_INT32_HASH(int16_t)
    293 ANDROID_INT32_HASH(uint16_t)
    294 ANDROID_INT32_HASH(int32_t)
    295 ANDROID_INT32_HASH(uint32_t)
    296 ANDROID_INT64_HASH(int64_t)
    297 ANDROID_INT64_HASH(uint64_t)
    298 ANDROID_REINTERPRET_HASH(float, uint32_t)
    299 ANDROID_REINTERPRET_HASH(double, uint64_t)
    300 
    301 template <typename T> inline hash_t hash_type(T* const & value) {
    302     return hash_type(uintptr_t(value));
    303 }
    304 
    305 }; // namespace android
    306 
    307 // ---------------------------------------------------------------------------
    308 
    309 #endif // ANDROID_TYPE_HELPERS_H
    310