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 27namespace android { 28 29/* 30 * Types traits 31 */ 32 33template <typename T> struct trait_trivial_ctor { enum { value = false }; }; 34template <typename T> struct trait_trivial_dtor { enum { value = false }; }; 35template <typename T> struct trait_trivial_copy { enum { value = false }; }; 36template <typename T> struct trait_trivial_move { enum { value = false }; }; 37template <typename T> struct trait_pointer { enum { value = false }; }; 38template <typename T> struct trait_pointer<T*> { enum { value = true }; }; 39 40template <typename TYPE> 41struct 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 56template <typename T, typename U> 57struct 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_BASIC_TYPES_TRAITS( T ) \ 72 template<> struct trait_trivial_ctor< T > { enum { value = true }; }; \ 73 template<> struct trait_trivial_dtor< T > { enum { value = true }; }; \ 74 template<> struct trait_trivial_copy< T > { enum { value = true }; }; \ 75 template<> struct trait_trivial_move< T > { enum { value = true }; }; 76 77// --------------------------------------------------------------------------- 78 79/* 80 * basic types traits 81 */ 82 83ANDROID_BASIC_TYPES_TRAITS( void ) 84ANDROID_BASIC_TYPES_TRAITS( bool ) 85ANDROID_BASIC_TYPES_TRAITS( char ) 86ANDROID_BASIC_TYPES_TRAITS( unsigned char ) 87ANDROID_BASIC_TYPES_TRAITS( short ) 88ANDROID_BASIC_TYPES_TRAITS( unsigned short ) 89ANDROID_BASIC_TYPES_TRAITS( int ) 90ANDROID_BASIC_TYPES_TRAITS( unsigned int ) 91ANDROID_BASIC_TYPES_TRAITS( long ) 92ANDROID_BASIC_TYPES_TRAITS( unsigned long ) 93ANDROID_BASIC_TYPES_TRAITS( long long ) 94ANDROID_BASIC_TYPES_TRAITS( unsigned long long ) 95ANDROID_BASIC_TYPES_TRAITS( float ) 96ANDROID_BASIC_TYPES_TRAITS( double ) 97 98// --------------------------------------------------------------------------- 99 100 101/* 102 * compare and order types 103 */ 104 105template<typename TYPE> inline 106int strictly_order_type(const TYPE& lhs, const TYPE& rhs) { 107 return (lhs < rhs) ? 1 : 0; 108} 109 110template<typename TYPE> inline 111int compare_type(const TYPE& lhs, const TYPE& rhs) { 112 return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs); 113} 114 115/* 116 * create, destroy, copy and move types... 117 */ 118 119template<typename TYPE> inline 120void construct_type(TYPE* p, size_t n) { 121 if (!traits<TYPE>::has_trivial_ctor) { 122 while (n--) { 123 new(p++) TYPE; 124 } 125 } 126} 127 128template<typename TYPE> inline 129void destroy_type(TYPE* p, size_t n) { 130 if (!traits<TYPE>::has_trivial_dtor) { 131 while (n--) { 132 p->~TYPE(); 133 p++; 134 } 135 } 136} 137 138template<typename TYPE> inline 139void copy_type(TYPE* d, const TYPE* s, size_t n) { 140 if (!traits<TYPE>::has_trivial_copy) { 141 while (n--) { 142 new(d) TYPE(*s); 143 d++, s++; 144 } 145 } else { 146 memcpy(d,s,n*sizeof(TYPE)); 147 } 148} 149 150template<typename TYPE> inline 151void splat_type(TYPE* where, const TYPE* what, size_t n) { 152 if (!traits<TYPE>::has_trivial_copy) { 153 while (n--) { 154 new(where) TYPE(*what); 155 where++; 156 } 157 } else { 158 while (n--) { 159 *where++ = *what; 160 } 161 } 162} 163 164template<typename TYPE> inline 165void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) { 166 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 167 || traits<TYPE>::has_trivial_move) 168 { 169 memmove(d,s,n*sizeof(TYPE)); 170 } else { 171 d += n; 172 s += n; 173 while (n--) { 174 --d, --s; 175 if (!traits<TYPE>::has_trivial_copy) { 176 new(d) TYPE(*s); 177 } else { 178 *d = *s; 179 } 180 if (!traits<TYPE>::has_trivial_dtor) { 181 s->~TYPE(); 182 } 183 } 184 } 185} 186 187template<typename TYPE> inline 188void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) { 189 if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 190 || traits<TYPE>::has_trivial_move) 191 { 192 memmove(d,s,n*sizeof(TYPE)); 193 } else { 194 while (n--) { 195 if (!traits<TYPE>::has_trivial_copy) { 196 new(d) TYPE(*s); 197 } else { 198 *d = *s; 199 } 200 if (!traits<TYPE>::has_trivial_dtor) { 201 s->~TYPE(); 202 } 203 d++, s++; 204 } 205 } 206} 207 208// --------------------------------------------------------------------------- 209 210/* 211 * a key/value pair 212 */ 213 214template <typename KEY, typename VALUE> 215struct key_value_pair_t { 216 KEY key; 217 VALUE value; 218 key_value_pair_t() { } 219 key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { } 220 key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v) { } 221 key_value_pair_t(const KEY& k) : key(k) { } 222 inline bool operator < (const key_value_pair_t& o) const { 223 return strictly_order_type(key, o.key); 224 } 225}; 226 227template<> 228template <typename K, typename V> 229struct trait_trivial_ctor< key_value_pair_t<K, V> > 230{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; }; 231template<> 232template <typename K, typename V> 233struct trait_trivial_dtor< key_value_pair_t<K, V> > 234{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; }; 235template<> 236template <typename K, typename V> 237struct trait_trivial_copy< key_value_pair_t<K, V> > 238{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; }; 239template<> 240template <typename K, typename V> 241struct trait_trivial_move< key_value_pair_t<K, V> > 242{ enum { value = aggregate_traits<K,V>::has_trivial_move }; }; 243 244// --------------------------------------------------------------------------- 245 246}; // namespace android 247 248// --------------------------------------------------------------------------- 249 250#endif // ANDROID_TYPE_HELPERS_H 251