1 // COPY OF TypeHelpers.h from system/core/libutils/include/utils. 2 /* 3 * Copyright (C) 2013 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #ifndef RS_TYPE_HELPERS_H 19 #define RS_TYPE_HELPERS_H 20 21 #include <new> 22 #include <stdint.h> 23 #include <string.h> 24 #include <sys/types.h> 25 26 // --------------------------------------------------------------------------- 27 namespace android { 28 namespace RSC { 29 30 /* 31 * Types traits 32 */ 33 34 template <typename T> struct trait_trivial_ctor { enum { value = false }; }; 35 template <typename T> struct trait_trivial_dtor { enum { value = false }; }; 36 template <typename T> struct trait_trivial_copy { enum { value = false }; }; 37 template <typename T> struct trait_trivial_move { enum { value = false }; }; 38 template <typename T> struct trait_pointer { enum { value = false }; }; 39 template <typename T> struct trait_pointer<T*> { enum { value = true }; }; 40 41 template <typename TYPE> 42 struct traits { 43 enum { 44 // whether this type is a pointer 45 is_pointer = trait_pointer<TYPE>::value, 46 // whether this type's constructor is a no-op 47 has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value, 48 // whether this type's destructor is a no-op 49 has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value, 50 // whether this type type can be copy-constructed with memcpy 51 has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value, 52 // whether this type can be moved with memmove 53 has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value 54 }; 55 }; 56 57 template <typename T, typename U> 58 struct aggregate_traits { 59 enum { 60 is_pointer = false, 61 has_trivial_ctor = 62 traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor, 63 has_trivial_dtor = 64 traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor, 65 has_trivial_copy = 66 traits<T>::has_trivial_copy && traits<U>::has_trivial_copy, 67 has_trivial_move = 68 traits<T>::has_trivial_move && traits<U>::has_trivial_move 69 }; 70 }; 71 72 #define RS_TRIVIAL_CTOR_TRAIT( T ) \ 73 template<> struct trait_trivial_ctor< T > { enum { value = true }; }; 74 75 #define RS_TRIVIAL_DTOR_TRAIT( T ) \ 76 template<> struct trait_trivial_dtor< T > { enum { value = true }; }; 77 78 #define RS_TRIVIAL_COPY_TRAIT( T ) \ 79 template<> struct trait_trivial_copy< T > { enum { value = true }; }; 80 81 #define RS_TRIVIAL_MOVE_TRAIT( T ) \ 82 template<> struct trait_trivial_move< T > { enum { value = true }; }; 83 84 #define RS_BASIC_TYPES_TRAITS( T ) \ 85 RS_TRIVIAL_CTOR_TRAIT( T ) \ 86 RS_TRIVIAL_DTOR_TRAIT( T ) \ 87 RS_TRIVIAL_COPY_TRAIT( T ) \ 88 RS_TRIVIAL_MOVE_TRAIT( T ) 89 90 // --------------------------------------------------------------------------- 91 92 /* 93 * basic types traits 94 */ 95 96 RS_BASIC_TYPES_TRAITS( void ) 97 RS_BASIC_TYPES_TRAITS( bool ) 98 RS_BASIC_TYPES_TRAITS( char ) 99 RS_BASIC_TYPES_TRAITS( unsigned char ) 100 RS_BASIC_TYPES_TRAITS( short ) 101 RS_BASIC_TYPES_TRAITS( unsigned short ) 102 RS_BASIC_TYPES_TRAITS( int ) 103 RS_BASIC_TYPES_TRAITS( unsigned int ) 104 RS_BASIC_TYPES_TRAITS( long ) 105 RS_BASIC_TYPES_TRAITS( unsigned long ) 106 RS_BASIC_TYPES_TRAITS( long long ) 107 RS_BASIC_TYPES_TRAITS( unsigned long long ) 108 RS_BASIC_TYPES_TRAITS( float ) 109 RS_BASIC_TYPES_TRAITS( double ) 110 111 // --------------------------------------------------------------------------- 112 113 114 /* 115 * compare and order types 116 */ 117 118 template<typename TYPE> inline 119 int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { 120 return (lhs < rhs) ? 1 : 0; 121 } 122 123 template<typename TYPE> inline 124 int compare_type(const TYPE& lhs, const TYPE& rhs) { 125 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs); 126 } 127 128 /* 129 * create, destroy, copy and move types... 130 */ 131 132 template<typename TYPE> inline 133 void construct_type(TYPE* p, size_t n) { 134 if (!traits<TYPE>::has_trivial_ctor) { 135 while (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--) { 145 p->~TYPE(); 146 p++; 147 } 148 } 149 } 150 151 template<typename TYPE> inline 152 void copy_type(TYPE* d, const TYPE* s, size_t n) { 153 if (!traits<TYPE>::has_trivial_copy) { 154 while (n--) { 155 new(d) TYPE(*s); 156 d++, s++; 157 } 158 } else { 159 memcpy(d,s,n*sizeof(TYPE)); 160 } 161 } 162 163 template<typename TYPE> inline 164 void splat_type(TYPE* where, const TYPE* what, size_t n) { 165 if (!traits<TYPE>::has_trivial_copy) { 166 while (n--) { 167 new(where) TYPE(*what); 168 where++; 169 } 170 } else { 171 while (n--) { 172 *where++ = *what; 173 } 174 } 175 } 176 177 template<typename TYPE> inline 178 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 179 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 180 || traits<TYPE>::has_trivial_move) 181 { 182 memmove(d,s,n*sizeof(TYPE)); 183 } else { 184 d += n; 185 s += n; 186 while (n--) { 187 --d, --s; 188 if (!traits<TYPE>::has_trivial_copy) { 189 new(d) TYPE(*s); 190 } else { 191 *d = *s; 192 } 193 if (!traits<TYPE>::has_trivial_dtor) { 194 s->~TYPE(); 195 } 196 } 197 } 198 } 199 200 template<typename TYPE> inline 201 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 202 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 203 || traits<TYPE>::has_trivial_move) 204 { 205 memmove(d,s,n*sizeof(TYPE)); 206 } else { 207 while (n--) { 208 if (!traits<TYPE>::has_trivial_copy) { 209 new(d) TYPE(*s); 210 } else { 211 *d = *s; 212 } 213 if (!traits<TYPE>::has_trivial_dtor) { 214 s->~TYPE(); 215 } 216 d++, s++; 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 typedef KEY key_t; 230 typedef VALUE value_t; 231 232 KEY key; 233 VALUE value; 234 key_value_pair_t() { } 235 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } 236 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } 237 explicit key_value_pair_t(const KEY& k) : key(k) { } 238 inline bool operator < (const key_value_pair_t& o) const { 239 return strictly_order_type(key, o.key); 240 } 241 inline const KEY& getKey() const { 242 return key; 243 } 244 inline const VALUE& getValue() const { 245 return value; 246 } 247 }; 248 249 template <typename K, typename V> 250 struct trait_trivial_ctor< key_value_pair_t<K, V> > 251 { enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; 252 template <typename K, typename V> 253 struct trait_trivial_dtor< key_value_pair_t<K, V> > 254 { enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; 255 template <typename K, typename V> 256 struct trait_trivial_copy< key_value_pair_t<K, V> > 257 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; 258 template <typename K, typename V> 259 struct trait_trivial_move< key_value_pair_t<K, V> > 260 { enum { value = aggregate_traits<K,V>::has_trivial_move }; }; 261 262 // --------------------------------------------------------------------------- 263 264 /* 265 * Hash codes. 266 */ 267 typedef uint32_t hash_t; 268 269 template <typename TKey> 270 hash_t hash_type(const TKey& key); 271 272 /* Built-in hash code specializations. 273 * Assumes pointers are 32bit. */ 274 #define RS_INT32_HASH(T) \ 275 template <> inline hash_t hash_type(const T& value) { return hash_t(value); } 276 #define RS_INT64_HASH(T) \ 277 template <> inline hash_t hash_type(const T& value) { \ 278 return hash_t((value >> 32) ^ value); } 279 #define RS_REINTERPRET_HASH(T, R) \ 280 template <> inline hash_t hash_type(const T& value) { \ 281 return hash_type(*reinterpret_cast<const R*>(&value)); } 282 283 RS_INT32_HASH(bool) 284 RS_INT32_HASH(int8_t) 285 RS_INT32_HASH(uint8_t) 286 RS_INT32_HASH(int16_t) 287 RS_INT32_HASH(uint16_t) 288 RS_INT32_HASH(int32_t) 289 RS_INT32_HASH(uint32_t) 290 RS_INT64_HASH(int64_t) 291 RS_INT64_HASH(uint64_t) 292 RS_REINTERPRET_HASH(float, uint32_t) 293 RS_REINTERPRET_HASH(double, uint64_t) 294 295 template <typename T> inline hash_t hash_type(T* const & value) { 296 return hash_type(uintptr_t(value)); 297 } 298 299 }; // namespace RSC 300 }; // namespace android 301 // --------------------------------------------------------------------------- 302 303 #endif // RS_TYPE_HELPERS_H 304