PageRenderTime 86ms CodeModel.GetById 40ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llstl.h

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