Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2013 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 RS_TYPE_HELPERS_H
     18 #define RS_TYPE_HELPERS_H
     19 
     20 #include <new>
     21 #include <stdint.h>
     22 #include <string.h>
     23 #include <sys/types.h>
     24 
     25 // ---------------------------------------------------------------------------
     26 namespace android {
     27 namespace RSC {
     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 RS_TRIVIAL_CTOR_TRAIT( T ) \
     72     template<> struct trait_trivial_ctor< T >   { enum { value = true }; };
     73 
     74 #define RS_TRIVIAL_DTOR_TRAIT( T ) \
     75     template<> struct trait_trivial_dtor< T >   { enum { value = true }; };
     76 
     77 #define RS_TRIVIAL_COPY_TRAIT( T ) \
     78     template<> struct trait_trivial_copy< T >   { enum { value = true }; };
     79 
     80 #define RS_TRIVIAL_MOVE_TRAIT( T ) \
     81     template<> struct trait_trivial_move< T >   { enum { value = true }; };
     82 
     83 #define RS_BASIC_TYPES_TRAITS( T ) \
     84     RS_TRIVIAL_CTOR_TRAIT( T ) \
     85     RS_TRIVIAL_DTOR_TRAIT( T ) \
     86     RS_TRIVIAL_COPY_TRAIT( T ) \
     87     RS_TRIVIAL_MOVE_TRAIT( T )
     88 
     89 // ---------------------------------------------------------------------------
     90 
     91 /*
     92  * basic types traits
     93  */
     94 
     95 RS_BASIC_TYPES_TRAITS( void )
     96 RS_BASIC_TYPES_TRAITS( bool )
     97 RS_BASIC_TYPES_TRAITS( char )
     98 RS_BASIC_TYPES_TRAITS( unsigned char )
     99 RS_BASIC_TYPES_TRAITS( short )
    100 RS_BASIC_TYPES_TRAITS( unsigned short )
    101 RS_BASIC_TYPES_TRAITS( int )
    102 RS_BASIC_TYPES_TRAITS( unsigned int )
    103 RS_BASIC_TYPES_TRAITS( long )
    104 RS_BASIC_TYPES_TRAITS( unsigned long )
    105 RS_BASIC_TYPES_TRAITS( long long )
    106 RS_BASIC_TYPES_TRAITS( unsigned long long )
    107 RS_BASIC_TYPES_TRAITS( float )
    108 RS_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  * a key/value pair
    224  */
    225 
    226 template <typename KEY, typename VALUE>
    227 struct key_value_pair_t {
    228     typedef KEY key_t;
    229     typedef VALUE value_t;
    230 
    231     KEY     key;
    232     VALUE   value;
    233     key_value_pair_t() { }
    234     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
    235     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
    236     explicit key_value_pair_t(const KEY& k) : key(k) { }
    237     inline bool operator < (const key_value_pair_t& o) const {
    238         return strictly_order_type(key, o.key);
    239     }
    240     inline const KEY& getKey() const {
    241         return key;
    242     }
    243     inline const VALUE& getValue() const {
    244         return value;
    245     }
    246 };
    247 
    248 template <typename K, typename V>
    249 struct trait_trivial_ctor< key_value_pair_t<K, V> >
    250 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
    251 template <typename K, typename V>
    252 struct trait_trivial_dtor< key_value_pair_t<K, V> >
    253 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
    254 template <typename K, typename V>
    255 struct trait_trivial_copy< key_value_pair_t<K, V> >
    256 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
    257 template <typename K, typename V>
    258 struct trait_trivial_move< key_value_pair_t<K, V> >
    259 { enum { value = aggregate_traits<K,V>::has_trivial_move }; };
    260 
    261 // ---------------------------------------------------------------------------
    262 
    263 /*
    264  * Hash codes.
    265  */
    266 typedef uint32_t hash_t;
    267 
    268 template <typename TKey>
    269 hash_t hash_type(const TKey& key);
    270 
    271 /* Built-in hash code specializations.
    272  * Assumes pointers are 32bit. */
    273 #define RS_INT32_HASH(T) \
    274         template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
    275 #define RS_INT64_HASH(T) \
    276         template <> inline hash_t hash_type(const T& value) { \
    277                 return hash_t((value >> 32) ^ value); }
    278 #define RS_REINTERPRET_HASH(T, R) \
    279         template <> inline hash_t hash_type(const T& value) { \
    280                 return hash_type(*reinterpret_cast<const R*>(&value)); }
    281 
    282 RS_INT32_HASH(bool)
    283 RS_INT32_HASH(int8_t)
    284 RS_INT32_HASH(uint8_t)
    285 RS_INT32_HASH(int16_t)
    286 RS_INT32_HASH(uint16_t)
    287 RS_INT32_HASH(int32_t)
    288 RS_INT32_HASH(uint32_t)
    289 RS_INT64_HASH(int64_t)
    290 RS_INT64_HASH(uint64_t)
    291 RS_REINTERPRET_HASH(float, uint32_t)
    292 RS_REINTERPRET_HASH(double, uint64_t)
    293 
    294 template <typename T> inline hash_t hash_type(T* const & value) {
    295     return hash_type(uintptr_t(value));
    296 }
    297 
    298 }; // namespace RSC
    299 }; // namespace android
    300 // ---------------------------------------------------------------------------
    301 
    302 #endif // RS_TYPE_HELPERS_H
    303