1 //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains some templates that are useful if you are working with the 11 // STL at all. 12 // 13 // No library is required when using these functions. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_ADT_STLEXTRAS_H 18 #define LLVM_ADT_STLEXTRAS_H 19 20 #include <cstddef> // for std::size_t 21 #include <cstdlib> // for qsort 22 #include <functional> 23 #include <iterator> 24 #include <utility> // for std::pair 25 26 namespace llvm { 27 28 //===----------------------------------------------------------------------===// 29 // Extra additions to <functional> 30 //===----------------------------------------------------------------------===// 31 32 template<class Ty> 33 struct less_ptr : public std::binary_function<Ty, Ty, bool> { 34 bool operator()(const Ty* left, const Ty* right) const { 35 return *left < *right; 36 } 37 }; 38 39 template<class Ty> 40 struct greater_ptr : public std::binary_function<Ty, Ty, bool> { 41 bool operator()(const Ty* left, const Ty* right) const { 42 return *right < *left; 43 } 44 }; 45 46 // deleter - Very very very simple method that is used to invoke operator 47 // delete on something. It is used like this: 48 // 49 // for_each(V.begin(), B.end(), deleter<Interval>); 50 // 51 template <class T> 52 static inline void deleter(T *Ptr) { 53 delete Ptr; 54 } 55 56 57 58 //===----------------------------------------------------------------------===// 59 // Extra additions to <iterator> 60 //===----------------------------------------------------------------------===// 61 62 // mapped_iterator - This is a simple iterator adapter that causes a function to 63 // be dereferenced whenever operator* is invoked on the iterator. 64 // 65 template <class RootIt, class UnaryFunc> 66 class mapped_iterator { 67 RootIt current; 68 UnaryFunc Fn; 69 public: 70 typedef typename std::iterator_traits<RootIt>::iterator_category 71 iterator_category; 72 typedef typename std::iterator_traits<RootIt>::difference_type 73 difference_type; 74 typedef typename UnaryFunc::result_type value_type; 75 76 typedef void pointer; 77 //typedef typename UnaryFunc::result_type *pointer; 78 typedef void reference; // Can't modify value returned by fn 79 80 typedef RootIt iterator_type; 81 typedef mapped_iterator<RootIt, UnaryFunc> _Self; 82 83 inline const RootIt &getCurrent() const { return current; } 84 inline const UnaryFunc &getFunc() const { return Fn; } 85 86 inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) 87 : current(I), Fn(F) {} 88 inline mapped_iterator(const mapped_iterator &It) 89 : current(It.current), Fn(It.Fn) {} 90 91 inline value_type operator*() const { // All this work to do this 92 return Fn(*current); // little change 93 } 94 95 _Self& operator++() { ++current; return *this; } 96 _Self& operator--() { --current; return *this; } 97 _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } 98 _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } 99 _Self operator+ (difference_type n) const { 100 return _Self(current + n, Fn); 101 } 102 _Self& operator+= (difference_type n) { current += n; return *this; } 103 _Self operator- (difference_type n) const { 104 return _Self(current - n, Fn); 105 } 106 _Self& operator-= (difference_type n) { current -= n; return *this; } 107 reference operator[](difference_type n) const { return *(*this + n); } 108 109 inline bool operator!=(const _Self &X) const { return !operator==(X); } 110 inline bool operator==(const _Self &X) const { return current == X.current; } 111 inline bool operator< (const _Self &X) const { return current < X.current; } 112 113 inline difference_type operator-(const _Self &X) const { 114 return current - X.current; 115 } 116 }; 117 118 template <class _Iterator, class Func> 119 inline mapped_iterator<_Iterator, Func> 120 operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, 121 const mapped_iterator<_Iterator, Func>& X) { 122 return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); 123 } 124 125 126 // map_iterator - Provide a convenient way to create mapped_iterators, just like 127 // make_pair is useful for creating pairs... 128 // 129 template <class ItTy, class FuncTy> 130 inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { 131 return mapped_iterator<ItTy, FuncTy>(I, F); 132 } 133 134 135 // next/prior - These functions unlike std::advance do not modify the 136 // passed iterator but return a copy. 137 // 138 // next(myIt) returns copy of myIt incremented once 139 // next(myIt, n) returns copy of myIt incremented n times 140 // prior(myIt) returns copy of myIt decremented once 141 // prior(myIt, n) returns copy of myIt decremented n times 142 143 template <typename ItTy, typename Dist> 144 inline ItTy next(ItTy it, Dist n) 145 { 146 std::advance(it, n); 147 return it; 148 } 149 150 template <typename ItTy> 151 inline ItTy next(ItTy it) 152 { 153 return ++it; 154 } 155 156 template <typename ItTy, typename Dist> 157 inline ItTy prior(ItTy it, Dist n) 158 { 159 std::advance(it, -n); 160 return it; 161 } 162 163 template <typename ItTy> 164 inline ItTy prior(ItTy it) 165 { 166 return --it; 167 } 168 169 //===----------------------------------------------------------------------===// 170 // Extra additions to <utility> 171 //===----------------------------------------------------------------------===// 172 173 // tie - this function ties two objects and returns a temporary object 174 // that is assignable from a std::pair. This can be used to make code 175 // more readable when using values returned from functions bundled in 176 // a std::pair. Since an example is worth 1000 words: 177 // 178 // typedef std::map<int, int> Int2IntMap; 179 // 180 // Int2IntMap myMap; 181 // Int2IntMap::iterator where; 182 // bool inserted; 183 // tie(where, inserted) = myMap.insert(std::make_pair(123,456)); 184 // 185 // if (inserted) 186 // // do stuff 187 // else 188 // // do other stuff 189 190 namespace 191 { 192 template <typename T1, typename T2> 193 struct tier { 194 typedef T1 &first_type; 195 typedef T2 &second_type; 196 197 first_type first; 198 second_type second; 199 200 tier(first_type f, second_type s) : first(f), second(s) { } 201 tier& operator=(const std::pair<T1, T2>& p) { 202 first = p.first; 203 second = p.second; 204 return *this; 205 } 206 }; 207 } 208 209 template <typename T1, typename T2> 210 inline tier<T1, T2> tie(T1& f, T2& s) { 211 return tier<T1, T2>(f, s); 212 } 213 214 //===----------------------------------------------------------------------===// 215 // Extra additions for arrays 216 //===----------------------------------------------------------------------===// 217 218 /// Find where an array ends (for ending iterators) 219 /// This returns a pointer to the byte immediately 220 /// after the end of an array. 221 template<class T, std::size_t N> 222 inline T *array_endof(T (&x)[N]) { 223 return x+N; 224 } 225 226 /// Find the length of an array. 227 template<class T, std::size_t N> 228 inline size_t array_lengthof(T (&)[N]) { 229 return N; 230 } 231 232 /// array_pod_sort_comparator - This is helper function for array_pod_sort, 233 /// which just uses operator< on T. 234 template<typename T> 235 static inline int array_pod_sort_comparator(const void *P1, const void *P2) { 236 if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2)) 237 return -1; 238 if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1)) 239 return 1; 240 return 0; 241 } 242 243 /// get_array_pad_sort_comparator - This is an internal helper function used to 244 /// get type deduction of T right. 245 template<typename T> 246 static int (*get_array_pad_sort_comparator(const T &)) 247 (const void*, const void*) { 248 return array_pod_sort_comparator<T>; 249 } 250 251 252 /// array_pod_sort - This sorts an array with the specified start and end 253 /// extent. This is just like std::sort, except that it calls qsort instead of 254 /// using an inlined template. qsort is slightly slower than std::sort, but 255 /// most sorts are not performance critical in LLVM and std::sort has to be 256 /// template instantiated for each type, leading to significant measured code 257 /// bloat. This function should generally be used instead of std::sort where 258 /// possible. 259 /// 260 /// This function assumes that you have simple POD-like types that can be 261 /// compared with operator< and can be moved with memcpy. If this isn't true, 262 /// you should use std::sort. 263 /// 264 /// NOTE: If qsort_r were portable, we could allow a custom comparator and 265 /// default to std::less. 266 template<class IteratorTy> 267 static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 268 // Don't dereference start iterator of empty sequence. 269 if (Start == End) return; 270 qsort(&*Start, End-Start, sizeof(*Start), 271 get_array_pad_sort_comparator(*Start)); 272 } 273 274 template<class IteratorTy> 275 static inline void array_pod_sort(IteratorTy Start, IteratorTy End, 276 int (*Compare)(const void*, const void*)) { 277 // Don't dereference start iterator of empty sequence. 278 if (Start == End) return; 279 qsort(&*Start, End-Start, sizeof(*Start), Compare); 280 } 281 282 //===----------------------------------------------------------------------===// 283 // Extra additions to <algorithm> 284 //===----------------------------------------------------------------------===// 285 286 /// For a container of pointers, deletes the pointers and then clears the 287 /// container. 288 template<typename Container> 289 void DeleteContainerPointers(Container &C) { 290 for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 291 delete *I; 292 C.clear(); 293 } 294 295 /// In a container of pairs (usually a map) whose second element is a pointer, 296 /// deletes the second elements and then clears the container. 297 template<typename Container> 298 void DeleteContainerSeconds(Container &C) { 299 for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) 300 delete I->second; 301 C.clear(); 302 } 303 304 } // End llvm namespace 305 306 #endif 307