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 // sp<> can be trivially moved
     41 template <typename T> class sp;
     42 template <typename T> struct trait_trivial_move< sp<T> >{
     43     enum { value = true };
     44 };
     45 
     46 // wp<> can be trivially moved
     47 template <typename T> class wp;
     48 template <typename T> struct trait_trivial_move< wp<T> >{
     49     enum { value = true };
     50 };
     51 
     52 template <typename TYPE>
     53 struct traits {
     54     enum {
     55         // whether this type is a pointer
     56         is_pointer          = trait_pointer<TYPE>::value,
     57         // whether this type's constructor is a no-op
     58         has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
     59         // whether this type's destructor is a no-op
     60         has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
     61         // whether this type type can be copy-constructed with memcpy
     62         has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
     63         // whether this type can be moved with memmove
     64         has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
     65     };
     66 };
     67 
     68 template <typename T, typename U>
     69 struct aggregate_traits {
     70     enum {
     71         is_pointer          = false,
     72         has_trivial_ctor    =
     73             traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
     74         has_trivial_dtor    =
     75             traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
     76         has_trivial_copy    =
     77             traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
     78         has_trivial_move    =
     79             traits<T>::has_trivial_move && traits<U>::has_trivial_move
     80     };
     81 };
     82 
     83 #define ANDROID_BASIC_TYPES_TRAITS( T )                                     \
     84     template<> struct trait_trivial_ctor< T >   { enum { value = true }; }; \
     85     template<> struct trait_trivial_dtor< T >   { enum { value = true }; }; \
     86     template<> struct trait_trivial_copy< T >   { enum { value = true }; }; \
     87     template<> struct trait_trivial_move< T >   { enum { value = true }; };
     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--) {
    135             new(p++) TYPE;
    136         }
    137     }
    138 }
    139 
    140 template<typename TYPE> inline
    141 void destroy_type(TYPE* p, size_t n) {
    142     if (!traits<TYPE>::has_trivial_dtor) {
    143         while (n--) {
    144             p->~TYPE();
    145             p++;
    146         }
    147     }
    148 }
    149 
    150 template<typename TYPE> inline
    151 void copy_type(TYPE* d, const TYPE* s, size_t n) {
    152     if (!traits<TYPE>::has_trivial_copy) {
    153         while (n--) {
    154             new(d) TYPE(*s);
    155             d++, s++;
    156         }
    157     } else {
    158         memcpy(d,s,n*sizeof(TYPE));
    159     }
    160 }
    161 
    162 template<typename TYPE> inline
    163 void splat_type(TYPE* where, const TYPE* what, size_t n) {
    164     if (!traits<TYPE>::has_trivial_copy) {
    165         while (n--) {
    166             new(where) TYPE(*what);
    167             where++;
    168         }
    169     } else {
    170         while (n--) {
    171             *where++ = *what;
    172         }
    173     }
    174 }
    175 
    176 template<typename TYPE> inline
    177 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
    178     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
    179             || traits<TYPE>::has_trivial_move)
    180     {
    181         memmove(d,s,n*sizeof(TYPE));
    182     } else {
    183         d += n;
    184         s += n;
    185         while (n--) {
    186             --d, --s;
    187             if (!traits<TYPE>::has_trivial_copy) {
    188                 new(d) TYPE(*s);
    189             } else {
    190                 *d = *s;
    191             }
    192             if (!traits<TYPE>::has_trivial_dtor) {
    193                 s->~TYPE();
    194             }
    195         }
    196     }
    197 }
    198 
    199 template<typename TYPE> inline
    200 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
    201     if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
    202             || traits<TYPE>::has_trivial_move)
    203     {
    204         memmove(d,s,n*sizeof(TYPE));
    205     } else {
    206         while (n--) {
    207             if (!traits<TYPE>::has_trivial_copy) {
    208                 new(d) TYPE(*s);
    209             } else {
    210                 *d = *s;
    211             }
    212             if (!traits<TYPE>::has_trivial_dtor) {
    213                 s->~TYPE();
    214             }
    215             d++, s++;
    216         }
    217     }
    218 }
    219 
    220 
    221 // ---------------------------------------------------------------------------
    222 
    223 /*
    224  * a key/value pair
    225  */
    226 
    227 template <typename KEY, typename VALUE>
    228 struct key_value_pair_t {
    229     KEY     key;
    230     VALUE   value;
    231     key_value_pair_t() { }
    232     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
    233     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
    234     key_value_pair_t(const KEY& k) : key(k) { }
    235     inline bool operator < (const key_value_pair_t& o) const {
    236         return strictly_order_type(key, o.key);
    237     }
    238 };
    239 
    240 template<>
    241 template <typename K, typename V>
    242 struct trait_trivial_ctor< key_value_pair_t<K, V> >
    243 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
    244 template<>
    245 template <typename K, typename V>
    246 struct trait_trivial_dtor< key_value_pair_t<K, V> >
    247 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
    248 template<>
    249 template <typename K, typename V>
    250 struct trait_trivial_copy< key_value_pair_t<K, V> >
    251 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
    252 template<>
    253 template <typename K, typename V>
    254 struct trait_trivial_move< key_value_pair_t<K, V> >
    255 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
    256 
    257 // ---------------------------------------------------------------------------
    258 
    259 }; // namespace android
    260 
    261 // ---------------------------------------------------------------------------
    262 
    263 #endif // ANDROID_TYPE_HELPERS_H
    264