diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llcommon/llstl.h | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llstl.h b/linden/indra/llcommon/llstl.h new file mode 100644 index 0000000..ae0dc25 --- /dev/null +++ b/linden/indra/llcommon/llstl.h | |||
@@ -0,0 +1,472 @@ | |||
1 | /** | ||
2 | * @file llstl.h | ||
3 | * @brief helper object & functions for use with the stl. | ||
4 | * | ||
5 | * Copyright (c) 2003-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #ifndef LL_LLSTL_H | ||
29 | #define LL_LLSTL_H | ||
30 | |||
31 | #include <functional> | ||
32 | #include <algorithm> | ||
33 | #include <map> | ||
34 | #include <vector> | ||
35 | #include <set> | ||
36 | #include <deque> | ||
37 | |||
38 | #include <stdio.h> | ||
39 | #include <stdarg.h> | ||
40 | |||
41 | // Use to compare the first element only of a pair | ||
42 | // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t; | ||
43 | template <typename T1, typename T2> | ||
44 | struct compare_pair_first | ||
45 | { | ||
46 | bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const | ||
47 | { | ||
48 | return a.first < b.first; | ||
49 | } | ||
50 | }; | ||
51 | |||
52 | template <typename T1, typename T2> | ||
53 | struct compare_pair_greater | ||
54 | { | ||
55 | bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const | ||
56 | { | ||
57 | if (!(a.first < b.first)) | ||
58 | return true; | ||
59 | else if (!(b.first < a.first)) | ||
60 | return false; | ||
61 | else | ||
62 | return !(a.second < b.second); | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | // Use to compare the contents of two pointers (e.g. std::string*) | ||
67 | template <typename T> | ||
68 | struct compare_pointer_contents | ||
69 | { | ||
70 | typedef const T* Tptr; | ||
71 | bool operator()(const Tptr& a, const Tptr& b) const | ||
72 | { | ||
73 | return *a < *b; | ||
74 | } | ||
75 | }; | ||
76 | |||
77 | // DeletePointer is a simple helper for deleting all pointers in a container. | ||
78 | // The general form is: | ||
79 | // | ||
80 | // std::for_each(cont.begin(), cont.end(), DeletePointer()); | ||
81 | |||
82 | struct DeletePointer | ||
83 | { | ||
84 | template<typename T> void operator()(T* ptr) const | ||
85 | { | ||
86 | delete ptr; | ||
87 | } | ||
88 | }; | ||
89 | struct DeletePointerArray | ||
90 | { | ||
91 | template<typename T> void operator()(T* ptr) const | ||
92 | { | ||
93 | delete[] ptr; | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | // DeletePointer is a simple helper for deleting all pointers in a map. | ||
98 | // The general form is: | ||
99 | // | ||
100 | // std::for_each(somemap.begin(), somemap.end(), DeletePairedPointer()); | ||
101 | |||
102 | struct DeletePairedPointer | ||
103 | { | ||
104 | template<typename T> void operator()(T &ptr) const | ||
105 | { | ||
106 | delete ptr.second; | ||
107 | } | ||
108 | }; | ||
109 | struct DeletePairedPointerArray | ||
110 | { | ||
111 | template<typename T> void operator()(T &ptr) const | ||
112 | { | ||
113 | delete[] ptr.second; | ||
114 | } | ||
115 | }; | ||
116 | |||
117 | |||
118 | // Alternate version of the above so that has a more cumbersome | ||
119 | // syntax, but it can be used with compositional functors. | ||
120 | // NOTE: The functor retuns a bool because msdev bombs during the | ||
121 | // composition if you return void. Once we upgrade to a newer | ||
122 | // compiler, the second unary_function template parameter can be set | ||
123 | // to void. | ||
124 | // | ||
125 | // Here's a snippit showing how you use this object: | ||
126 | // | ||
127 | // typedef std::map<int, widget*> map_type; | ||
128 | // map_type widget_map; | ||
129 | // ... // add elements | ||
130 | // // delete them all | ||
131 | // for_each(widget_map.begin(), | ||
132 | // widget_map.end(), | ||
133 | // llcompose1(DeletePointerFunctor<widget>(), | ||
134 | // llselect2nd<map_type::value_type>())); | ||
135 | |||
136 | template<typename T> | ||
137 | struct DeletePointerFunctor : public std::unary_function<T*, bool> | ||
138 | { | ||
139 | bool operator()(T* ptr) const | ||
140 | { | ||
141 | delete ptr; | ||
142 | return true; | ||
143 | } | ||
144 | }; | ||
145 | |||
146 | // See notes about DeleteArray for why you should consider avoiding this. | ||
147 | template<typename T> | ||
148 | struct DeleteArrayFunctor : public std::unary_function<T*, bool> | ||
149 | { | ||
150 | bool operator()(T* ptr) const | ||
151 | { | ||
152 | delete[] ptr; | ||
153 | return true; | ||
154 | } | ||
155 | }; | ||
156 | |||
157 | // CopyNewPointer is a simple helper which accepts a pointer, and | ||
158 | // returns a new pointer built with the copy constructor. Example: | ||
159 | // | ||
160 | // transform(in.begin(), in.end(), out.end(), CopyNewPointer()); | ||
161 | |||
162 | struct CopyNewPointer | ||
163 | { | ||
164 | template<typename T> T* operator()(const T* ptr) const | ||
165 | { | ||
166 | return new T(*ptr); | ||
167 | } | ||
168 | }; | ||
169 | |||
170 | // Simple function to help with finding pointers in maps. | ||
171 | // For example: | ||
172 | // typedef map_t; | ||
173 | // std::map<int, const char*> foo; | ||
174 | // foo[18] = "there"; | ||
175 | // foo[2] = "hello"; | ||
176 | // const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello" | ||
177 | // const char* baz = get_ptr_in_map(foo, 3); // baz == NULL | ||
178 | template <typename K, typename T> | ||
179 | inline T* get_ptr_in_map(const std::map<K,T*>& inmap, const K& key) | ||
180 | { | ||
181 | // Typedef here avoids warnings because of new c++ naming rules. | ||
182 | typedef typename std::map<K,T*>::const_iterator map_iter; | ||
183 | map_iter iter = inmap.find(key); | ||
184 | if(iter == inmap.end()) | ||
185 | { | ||
186 | return NULL; | ||
187 | } | ||
188 | else | ||
189 | { | ||
190 | return iter->second; | ||
191 | } | ||
192 | }; | ||
193 | |||
194 | // helper function which returns true if key is in inmap. | ||
195 | template <typename K, typename T> | ||
196 | inline bool is_in_map(const std::map<K,T>& inmap, const K& key) | ||
197 | { | ||
198 | typedef typename std::map<K,T>::const_iterator map_iter; | ||
199 | if(inmap.find(key) == inmap.end()) | ||
200 | { | ||
201 | return false; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | return true; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | // Similar to get_ptr_in_map, but for any type with a valid T(0) constructor. | ||
210 | // To replace LLSkipMap getIfThere, use: | ||
211 | // get_if_there(map, key, 0) | ||
212 | // WARNING: Make sure default_value (generally 0) is not a valid map entry! | ||
213 | template <typename K, typename T> | ||
214 | inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value) | ||
215 | { | ||
216 | // Typedef here avoids warnings because of new c++ naming rules. | ||
217 | typedef typename std::map<K,T>::const_iterator map_iter; | ||
218 | map_iter iter = inmap.find(key); | ||
219 | if(iter == inmap.end()) | ||
220 | { | ||
221 | return default_value; | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | return iter->second; | ||
226 | } | ||
227 | }; | ||
228 | |||
229 | // Useful for replacing the removeObj() functionality of LLDynamicArray | ||
230 | // Example: | ||
231 | // for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); ) | ||
232 | // { | ||
233 | // if ((*iter)->isMarkedForRemoval()) | ||
234 | // iter = vector_replace_with_last(mList, iter); | ||
235 | // else | ||
236 | // ++iter; | ||
237 | // } | ||
238 | template <typename T, typename Iter> | ||
239 | inline Iter vector_replace_with_last(std::vector<T>& invec, Iter iter) | ||
240 | { | ||
241 | typename std::vector<T>::iterator last = invec.end(); --last; | ||
242 | if (iter == invec.end()) | ||
243 | { | ||
244 | return iter; | ||
245 | } | ||
246 | else if (iter == last) | ||
247 | { | ||
248 | invec.pop_back(); | ||
249 | return invec.end(); | ||
250 | } | ||
251 | else | ||
252 | { | ||
253 | *iter = *last; | ||
254 | invec.pop_back(); | ||
255 | return iter; | ||
256 | } | ||
257 | }; | ||
258 | |||
259 | // Useful for replacing the removeObj() functionality of LLDynamicArray | ||
260 | // Example: | ||
261 | // vector_replace_with_last(mList, x); | ||
262 | template <typename T> | ||
263 | inline bool vector_replace_with_last(std::vector<T>& invec, const T& val) | ||
264 | { | ||
265 | typename std::vector<T>::iterator iter = std::find(invec.begin(), invec.end(), val); | ||
266 | if (iter != invec.end()) | ||
267 | { | ||
268 | typename std::vector<T>::iterator last = invec.end(); --last; | ||
269 | *iter = *last; | ||
270 | invec.pop_back(); | ||
271 | return true; | ||
272 | } | ||
273 | return false; | ||
274 | } | ||
275 | |||
276 | // Append N elements to the vector and return a pointer to the first new element. | ||
277 | template <typename T> | ||
278 | inline T* vector_append(std::vector<T>& invec, S32 N) | ||
279 | { | ||
280 | U32 sz = invec.size(); | ||
281 | invec.resize(sz+N); | ||
282 | return &(invec[sz]); | ||
283 | } | ||
284 | |||
285 | // call function f to n members starting at first. similar to std::for_each | ||
286 | template <class InputIter, class Size, class Function> | ||
287 | Function ll_for_n(InputIter first, Size n, Function f) | ||
288 | { | ||
289 | for ( ; n > 0; --n, ++first) | ||
290 | f(*first); | ||
291 | return f; | ||
292 | } | ||
293 | |||
294 | // copy first to result n times, incrementing each as we go | ||
295 | template <class InputIter, class Size, class OutputIter> | ||
296 | OutputIter ll_copy_n(InputIter first, Size n, OutputIter result) | ||
297 | { | ||
298 | for ( ; n > 0; --n, ++result, ++first) | ||
299 | *result = *first; | ||
300 | return result; | ||
301 | } | ||
302 | |||
303 | // set *result = op(*f) for n elements of f | ||
304 | template <class InputIter, class OutputIter, class Size, class UnaryOp> | ||
305 | OutputIter ll_transform_n( | ||
306 | InputIter first, | ||
307 | Size n, | ||
308 | OutputIter result, | ||
309 | UnaryOp op) | ||
310 | { | ||
311 | for ( ; n > 0; --n, ++result, ++first) | ||
312 | *result = op(*first); | ||
313 | return result; | ||
314 | } | ||
315 | |||
316 | |||
317 | |||
318 | /* | ||
319 | * | ||
320 | * Copyright (c) 1994 | ||
321 | * Hewlett-Packard Company | ||
322 | * | ||
323 | * Permission to use, copy, modify, distribute and sell this software | ||
324 | * and its documentation for any purpose is hereby granted without fee, | ||
325 | * provided that the above copyright notice appear in all copies and | ||
326 | * that both that copyright notice and this permission notice appear | ||
327 | * in supporting documentation. Hewlett-Packard Company makes no | ||
328 | * representations about the suitability of this software for any | ||
329 | * purpose. It is provided "as is" without express or implied warranty. | ||
330 | * | ||
331 | * | ||
332 | * Copyright (c) 1996-1998 | ||
333 | * Silicon Graphics Computer Systems, Inc. | ||
334 | * | ||
335 | * Permission to use, copy, modify, distribute and sell this software | ||
336 | * and its documentation for any purpose is hereby granted without fee, | ||
337 | * provided that the above copyright notice appear in all copies and | ||
338 | * that both that copyright notice and this permission notice appear | ||
339 | * in supporting documentation. Silicon Graphics makes no | ||
340 | * representations about the suitability of this software for any | ||
341 | * purpose. It is provided "as is" without express or implied warranty. | ||
342 | */ | ||
343 | |||
344 | |||
345 | // helper to deal with the fact that MSDev does not package | ||
346 | // select... with the stl. Look up usage on the sgi website. | ||
347 | |||
348 | template <class _Pair> | ||
349 | struct _LLSelect1st : public std::unary_function<_Pair, typename _Pair::first_type> { | ||
350 | const typename _Pair::first_type& operator()(const _Pair& __x) const { | ||
351 | return __x.first; | ||
352 | } | ||
353 | }; | ||
354 | |||
355 | template <class _Pair> | ||
356 | struct _LLSelect2nd : public std::unary_function<_Pair, typename _Pair::second_type> | ||
357 | { | ||
358 | const typename _Pair::second_type& operator()(const _Pair& __x) const { | ||
359 | return __x.second; | ||
360 | } | ||
361 | }; | ||
362 | |||
363 | template <class _Pair> struct llselect1st : public _LLSelect1st<_Pair> {}; | ||
364 | template <class _Pair> struct llselect2nd : public _LLSelect2nd<_Pair> {}; | ||
365 | |||
366 | // helper to deal with the fact that MSDev does not package | ||
367 | // compose... with the stl. Look up usage on the sgi website. | ||
368 | |||
369 | template <class _Operation1, class _Operation2> | ||
370 | class ll_unary_compose : | ||
371 | public std::unary_function<typename _Operation2::argument_type, | ||
372 | typename _Operation1::result_type> | ||
373 | { | ||
374 | protected: | ||
375 | _Operation1 __op1; | ||
376 | _Operation2 __op2; | ||
377 | public: | ||
378 | ll_unary_compose(const _Operation1& __x, const _Operation2& __y) | ||
379 | : __op1(__x), __op2(__y) {} | ||
380 | typename _Operation1::result_type | ||
381 | operator()(const typename _Operation2::argument_type& __x) const { | ||
382 | return __op1(__op2(__x)); | ||
383 | } | ||
384 | }; | ||
385 | |||
386 | template <class _Operation1, class _Operation2> | ||
387 | inline ll_unary_compose<_Operation1,_Operation2> | ||
388 | llcompose1(const _Operation1& __op1, const _Operation2& __op2) | ||
389 | { | ||
390 | return ll_unary_compose<_Operation1,_Operation2>(__op1, __op2); | ||
391 | } | ||
392 | |||
393 | template <class _Operation1, class _Operation2, class _Operation3> | ||
394 | class ll_binary_compose | ||
395 | : public std::unary_function<typename _Operation2::argument_type, | ||
396 | typename _Operation1::result_type> { | ||
397 | protected: | ||
398 | _Operation1 _M_op1; | ||
399 | _Operation2 _M_op2; | ||
400 | _Operation3 _M_op3; | ||
401 | public: | ||
402 | ll_binary_compose(const _Operation1& __x, const _Operation2& __y, | ||
403 | const _Operation3& __z) | ||
404 | : _M_op1(__x), _M_op2(__y), _M_op3(__z) { } | ||
405 | typename _Operation1::result_type | ||
406 | operator()(const typename _Operation2::argument_type& __x) const { | ||
407 | return _M_op1(_M_op2(__x), _M_op3(__x)); | ||
408 | } | ||
409 | }; | ||
410 | |||
411 | template <class _Operation1, class _Operation2, class _Operation3> | ||
412 | inline ll_binary_compose<_Operation1, _Operation2, _Operation3> | ||
413 | llcompose2(const _Operation1& __op1, const _Operation2& __op2, | ||
414 | const _Operation3& __op3) | ||
415 | { | ||
416 | return ll_binary_compose<_Operation1,_Operation2,_Operation3> | ||
417 | (__op1, __op2, __op3); | ||
418 | } | ||
419 | |||
420 | // helpers to deal with the fact that MSDev does not package | ||
421 | // bind... with the stl. Again, this is from sgi. | ||
422 | template <class _Operation> | ||
423 | class llbinder1st : | ||
424 | public std::unary_function<typename _Operation::second_argument_type, | ||
425 | typename _Operation::result_type> { | ||
426 | protected: | ||
427 | _Operation op; | ||
428 | typename _Operation::first_argument_type value; | ||
429 | public: | ||
430 | llbinder1st(const _Operation& __x, | ||
431 | const typename _Operation::first_argument_type& __y) | ||
432 | : op(__x), value(__y) {} | ||
433 | typename _Operation::result_type | ||
434 | operator()(const typename _Operation::second_argument_type& __x) const { | ||
435 | return op(value, __x); | ||
436 | } | ||
437 | }; | ||
438 | |||
439 | template <class _Operation, class _Tp> | ||
440 | inline llbinder1st<_Operation> | ||
441 | llbind1st(const _Operation& __oper, const _Tp& __x) | ||
442 | { | ||
443 | typedef typename _Operation::first_argument_type _Arg1_type; | ||
444 | return llbinder1st<_Operation>(__oper, _Arg1_type(__x)); | ||
445 | } | ||
446 | |||
447 | template <class _Operation> | ||
448 | class llbinder2nd | ||
449 | : public std::unary_function<typename _Operation::first_argument_type, | ||
450 | typename _Operation::result_type> { | ||
451 | protected: | ||
452 | _Operation op; | ||
453 | typename _Operation::second_argument_type value; | ||
454 | public: | ||
455 | llbinder2nd(const _Operation& __x, | ||
456 | const typename _Operation::second_argument_type& __y) | ||
457 | : op(__x), value(__y) {} | ||
458 | typename _Operation::result_type | ||
459 | operator()(const typename _Operation::first_argument_type& __x) const { | ||
460 | return op(__x, value); | ||
461 | } | ||
462 | }; | ||
463 | |||
464 | template <class _Operation, class _Tp> | ||
465 | inline llbinder2nd<_Operation> | ||
466 | llbind2nd(const _Operation& __oper, const _Tp& __x) | ||
467 | { | ||
468 | typedef typename _Operation::second_argument_type _Arg2_type; | ||
469 | return llbinder2nd<_Operation>(__oper, _Arg2_type(__x)); | ||
470 | } | ||
471 | |||
472 | #endif // LL_LLSTL_H | ||