summaryrefslogtreecommitdiffstats
path: root/include/o3tl
diff options
context:
space:
mode:
authorBjoern Michaelsen <bjoern.michaelsen@canonical.com>2013-04-18 18:26:28 +0200
committerBjoern Michaelsen <bjoern.michaelsen@canonical.com>2013-04-23 22:20:31 +0200
commitb9337e22ce1dbf2eba0e8c8db294ae99f4111f91 (patch)
tree53ee1bd3dfd213815a21579151983cb997922b05 /include/o3tl
parentmove global headers script (diff)
downloadcore-b9337e22ce1dbf2eba0e8c8db294ae99f4111f91.tar.gz
core-b9337e22ce1dbf2eba0e8c8db294ae99f4111f91.zip
execute move of global headers
see https://gerrit.libreoffice.org/#/c/3367/ and Change-Id: I00c96fa77d04b33a6f8c8cd3490dfcd9bdc9e84a for details Change-Id: I199a75bc4042af20817265d5ef85b1134a96ff5a
Diffstat (limited to 'include/o3tl')
-rw-r--r--include/o3tl/compat_functional.hxx151
-rw-r--r--include/o3tl/cow_wrapper.hxx322
-rw-r--r--include/o3tl/heap_ptr.hxx305
-rw-r--r--include/o3tl/lazy_update.hxx265
-rw-r--r--include/o3tl/range.hxx183
-rw-r--r--include/o3tl/sorted_vector.hxx237
-rw-r--r--include/o3tl/vector_pool.hxx123
7 files changed, 1586 insertions, 0 deletions
diff --git a/include/o3tl/compat_functional.hxx b/include/o3tl/compat_functional.hxx
new file mode 100644
index 000000000000..00ae33cb23bb
--- /dev/null
+++ b/include/o3tl/compat_functional.hxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Copyright (c) 1996-1998
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1997
+ * Moscow Center for SPARC Technology
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+ * Lifted and paraphrased from STLport - with additions from Fridrich
+ * Strba and Thorsten Behrens
+ */
+
+#ifndef INCLUDED_O3TL_COMPAT_FUNCTIONAL_HXX
+#define INCLUDED_O3TL_COMPAT_FUNCTIONAL_HXX
+
+#include <functional>
+
+namespace o3tl
+{
+
+/// Identity functor - return the input value
+template<class T>
+struct identity : public std::unary_function<T, T>
+{
+ T operator()(const T& y) const
+ {
+ return (y);
+ }
+};
+
+/// Functor, given two parameters, return the first
+template<class T1,class T2>
+struct project1st : public std::binary_function<T1, T2, T1>
+{
+ T1 operator()(const T1& y, const T2&) const
+ {
+ return (y);
+ }
+};
+
+/// Functor, given two parameters, return the second
+template<class T1,class T2>
+struct project2nd : public std::binary_function<T1, T2, T2>
+{
+ T2 operator()(const T1&, const T2& x) const
+ {
+ return (x);
+ }
+};
+
+/// Select first value of a pair
+template<class P>
+struct select1st : public std::unary_function<P, typename P::first_type>
+{
+ const typename P::first_type& operator()(const P& y) const
+ {
+ return (y.first);
+ }
+};
+
+/// Select second value of a pair
+template<class P>
+struct select2nd : public std::unary_function<P, typename P::second_type>
+{
+ const typename P::second_type& operator()(const P& y) const
+ {
+ return (y.second);
+ }
+};
+
+/// Call F1 with the result of F2 applied to the one input parameter
+template<class F1, class F2>
+class unary_compose : public std::unary_function<typename F2::argument_type, typename F1::result_type>
+{
+ public:
+ unary_compose(const F1& fnction1, const F2& fnction2) : ftor1(fnction1), ftor2(fnction2) {}
+
+ typename F1::result_type operator()(const typename F2::argument_type& y) const
+ {
+ return (ftor1(ftor2(y)));
+ }
+
+ protected:
+ F1 ftor1;
+ F2 ftor2;
+};
+
+/// Create functor that calls F1 with the result of F2 applied to the one input parameter
+template<class F1, class F2>
+inline unary_compose<F1, F2> compose1(const F1& fnction1, const F2& fnction2)
+{
+ return (unary_compose<F1, F2>(fnction1, fnction2));
+}
+
+/// Calls F2 and F3 for the two args of F1, respectively
+template<class F1, class F2, class F3>
+class binary_compose : public std::unary_function<typename F2::argument_type,typename F1::result_type>
+{
+ public:
+ binary_compose(const F1& fnction1, const F2& fnction2, const F3& fnction3) : ftor1(fnction1), ftor2(fnction2), ftor3(fnction3) {}
+
+ typename F1::result_type operator()(const typename F2::argument_type& y) const
+ {
+ return (ftor1(ftor2(y), ftor3(y)));
+ }
+
+ protected:
+ F1 ftor1;
+ F2 ftor2;
+ F3 ftor3;
+};
+
+/// Creates functor that calls F2 and F3 for the two args of F1, respectively
+template<class F1, class F2, class F3>
+inline binary_compose<F1, F2, F3> compose2(const F1& fnction1, const F2& fnction2, const F3& fnction3)
+{
+ return (binary_compose<F1, F2, F3>(fnction1, fnction2, fnction3));
+}
+
+/// Algo that assigns val, val+1, ... to the given range
+template<typename FwdIter, typename ValueType>
+inline void iota(FwdIter first, FwdIter last, ValueType val)
+{
+ while(first != last)
+ *first++ = val++;
+}
+
+} // namespace o3tl
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/cow_wrapper.hxx b/include/o3tl/cow_wrapper.hxx
new file mode 100644
index 000000000000..b54f99d0f190
--- /dev/null
+++ b/include/o3tl/cow_wrapper.hxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_O3TL_COW_WRAPPER_HXX
+#define INCLUDED_O3TL_COW_WRAPPER_HXX
+
+#include <osl/interlck.h>
+
+#include <algorithm>
+
+#include <boost/utility.hpp>
+#include <boost/checked_delete.hpp>
+
+namespace o3tl
+{
+ /** Thread-unsafe refcounting
+
+ This is the default locking policy for cow_wrapper. No
+ locking/guarding against concurrent access is performed
+ whatsoever.
+ */
+ struct UnsafeRefCountingPolicy
+ {
+ typedef sal_uInt32 ref_count_t;
+ static void incrementCount( ref_count_t& rCount ) { ++rCount; }
+ static bool decrementCount( ref_count_t& rCount ) { return --rCount != 0; }
+ };
+
+ /** Thread-safe refcounting
+
+ Use this to have the cow_wrapper refcounting mechanisms employ
+ the thread-safe oslInterlockedCount .
+ */
+ struct ThreadSafeRefCountingPolicy
+ {
+ typedef oslInterlockedCount ref_count_t;
+ static void incrementCount( ref_count_t& rCount ) { osl_atomic_increment(&rCount); }
+ static bool decrementCount( ref_count_t& rCount )
+ {
+ if( rCount == 1 ) // caller is already the only/last reference
+ return false;
+ else
+ return osl_atomic_decrement(&rCount) != 0;
+ }
+ };
+
+ /** Copy-on-write wrapper.
+
+ This template provides copy-on-write semantics for the wrapped
+ type: when copying, the operation is performed shallow,
+ i.e. different cow_wrapper objects share the same underlying
+ instance. Only when accessing the underlying object via
+ non-const methods, a unique copy is provided.
+
+ The type parameter <code>T</code> must satisfy the following
+ requirements: it must be default-constructible, copyable (it
+ need not be assignable), and be of non-reference type. Note
+ that, despite the fact that this template provides access to
+ the wrapped type via pointer-like methods
+ (<code>operator->()</code> and <code>operator*()</code>), it does
+ <em>not</em> work like e.g. the boost pointer wrappers
+ (shared_ptr, scoped_ptr, etc.). Internally, the cow_wrapper
+ holds a by-value instance of the wrapped object. This is to
+ avoid one additional heap allocation, and providing access via
+ <code>operator->()</code>/<code>operator*()</code> is because
+ <code>operator.()</code> cannot be overridden.
+
+ Regarding thread safety: this wrapper is <em>not</em>
+ thread-safe per se, because cow_wrapper has no way of
+ syncronizing the potentially many different cow_wrapper
+ instances, that reference a single shared value_type
+ instance. That said, when passing
+ <code>ThreadSafeRefCountingPolicy</code> as the
+ <code>MTPolicy</code> parameter, accessing a thread-safe
+ pointee through multiple cow_wrapper instances might be
+ thread-safe, if the individual pointee methods are
+ thread-safe, <em>including</em> pointee's copy
+ constructor. Any wrapped object that needs external
+ synchronisation (e.g. via an external mutex, which arbitrates
+ access to object methods, and can be held across multiple
+ object method calls) cannot easily be dealt with in a
+ thread-safe way, because, as noted, objects are shared behind
+ the client's back.
+
+ @attention if one wants to use the pimpl idiom together with
+ cow_wrapper (i.e. put an opaque type into the cow_wrapper),
+ then <em>all<em> methods in the surrounding class needs to be
+ non-inline (<em>including</em> destructor, copy constructor
+ and assignment operator).
+
+ @example
+ <pre>
+class cow_wrapper_client_impl;
+
+class cow_wrapper_client
+{
+public:
+ cow_wrapper_client();
+ cow_wrapper_client( const cow_wrapper_client& );
+ ~cow_wrapper_client();
+
+ cow_wrapper_client& operator=( const cow_wrapper_client& );
+
+ void modify( int nVal );
+ int queryUnmodified() const;
+
+private:
+ otl::cow_wrapper< cow_wrapper_client_impl > maImpl;
+};
+ </pre>
+ and the implementation file would look like this:
+ <pre>
+class cow_wrapper_client_impl
+{
+public:
+ void setValue( int nVal ) { mnValue = nVal; }
+ int getValue() const { return mnValue; }
+
+private:
+ int mnValue;
+}
+
+cow_wrapper_client::cow_wrapper_client() :
+ maImpl()
+{
+}
+cow_wrapper_client::cow_wrapper_client( const cow_wrapper_client& rSrc ) :
+ maImpl( rSrc.maImpl )
+{
+}
+cow_wrapper_client::~cow_wrapper_client()
+{
+}
+cow_wrapper_client& cow_wrapper_client::operator=( const cow_wrapper_client& rSrc )
+{
+ maImpl = rSrc.maImpl;
+ return *this;
+}
+void cow_wrapper_client::modify( int nVal )
+{
+ maImpl->setValue( nVal );
+}
+int cow_wrapper_client::queryUnmodified() const
+{
+ return maImpl->getValue();
+}
+ </pre>
+ */
+ template<typename T, class MTPolicy=UnsafeRefCountingPolicy> class cow_wrapper
+ {
+ /** shared value object - gets cloned before cow_wrapper hands
+ out a non-const reference to it
+ */
+ struct impl_t : private boost::noncopyable
+ {
+ impl_t() :
+ m_value(),
+ m_ref_count(1)
+ {
+ }
+
+ explicit impl_t( const T& v ) :
+ m_value(v),
+ m_ref_count(1)
+ {
+ }
+
+ T m_value;
+ typename MTPolicy::ref_count_t m_ref_count;
+ };
+
+ void release()
+ {
+ if( !MTPolicy::decrementCount(m_pimpl->m_ref_count) )
+ boost::checked_delete(m_pimpl), m_pimpl=0;
+ }
+
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef MTPolicy mt_policy;
+
+ /** Default-construct wrapped type instance
+ */
+ cow_wrapper() :
+ m_pimpl( new impl_t() )
+ {
+ }
+
+ /** Copy-construct wrapped type instance from given object
+ */
+ explicit cow_wrapper( const value_type& r ) :
+ m_pimpl( new impl_t(r) )
+ {
+ }
+
+ /** Shallow-copy given cow_wrapper
+ */
+ explicit cow_wrapper( const cow_wrapper& rSrc ) : // nothrow
+ m_pimpl( rSrc.m_pimpl )
+ {
+ MTPolicy::incrementCount( m_pimpl->m_ref_count );
+ }
+
+ ~cow_wrapper() // nothrow, if ~T does not throw
+ {
+ release();
+ }
+
+ /// now sharing rSrc cow_wrapper instance with us
+ cow_wrapper& operator=( const cow_wrapper& rSrc ) // nothrow
+ {
+ // this already guards against self-assignment
+ MTPolicy::incrementCount( rSrc.m_pimpl->m_ref_count );
+
+ release();
+ m_pimpl = rSrc.m_pimpl;
+
+ return *this;
+ }
+
+ /// unshare with any other cow_wrapper instance
+ value_type& make_unique()
+ {
+ if( m_pimpl->m_ref_count > 1 )
+ {
+ impl_t* pimpl = new impl_t(m_pimpl->m_value);
+ release();
+ m_pimpl = pimpl;
+ }
+
+ return m_pimpl->m_value;
+ }
+
+ /// true, if not shared with any other cow_wrapper instance
+ bool is_unique() const // nothrow
+ {
+ return m_pimpl->m_ref_count == 1;
+ }
+
+ /// return number of shared instances (1 for unique object)
+ typename MTPolicy::ref_count_t use_count() const // nothrow
+ {
+ return m_pimpl->m_ref_count;
+ }
+
+ void swap(cow_wrapper& r) // never throws
+ {
+ std::swap(m_pimpl, r.m_pimpl);
+ }
+
+ pointer operator->() { return &make_unique(); }
+ value_type& operator*() { return make_unique(); }
+ const_pointer operator->() const { return &m_pimpl->m_value; }
+ const value_type& operator*() const { return m_pimpl->m_value; }
+
+ pointer get() { return &make_unique(); }
+ const_pointer get() const { return &m_pimpl->m_value; }
+
+ /// true, if both cow_wrapper internally share the same object
+ bool same_object( const cow_wrapper& rOther ) const
+ {
+ return rOther.m_pimpl == m_pimpl;
+ }
+
+ private:
+ impl_t* m_pimpl;
+ };
+
+
+ template<class T, class P> inline bool operator==( const cow_wrapper<T,P>& a,
+ const cow_wrapper<T,P>& b )
+ {
+ return a.same_object(b) ? true : *a == *b;
+ }
+
+ template<class T, class P> inline bool operator!=( const cow_wrapper<T,P>& a,
+ const cow_wrapper<T,P>& b )
+ {
+ return a.same_object(b) ? false : *a != *b;
+ }
+
+ template<class A, class B, class P> inline bool operator<( const cow_wrapper<A,P>& a,
+ const cow_wrapper<B,P>& b )
+ {
+ return *a < *b;
+ }
+
+ template<class T, class P> inline void swap( cow_wrapper<T,P>& a,
+ cow_wrapper<T,P>& b )
+ {
+ a.swap(b);
+ }
+
+ // to enable boost::mem_fn on cow_wrapper
+ template<class T, class P> inline T * get_pointer( const cow_wrapper<T,P>& r )
+ {
+ return r.get();
+ }
+
+}
+
+#endif /* INCLUDED_O3TL_COW_WRAPPER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/heap_ptr.hxx b/include/o3tl/heap_ptr.hxx
new file mode 100644
index 000000000000..713aa21c41b8
--- /dev/null
+++ b/include/o3tl/heap_ptr.hxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_O3TL_HEAP_PTR_HXX
+#define INCLUDED_O3TL_HEAP_PTR_HXX
+
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+
+
+namespace o3tl
+{
+/** heap_ptr<> owns an object on the heap, which will be automatically
+ deleted, when ~heap_ptr<>() is called.
+
+ Applicability
+ -------------
+ heap_ptr<> can be used for class members on the heap.
+ - One cannot forget to delete them in the destructor.
+ - Constness will be transfered from the owning instance.
+
+ heap_ptr<> can also be used as smart pointer in function bodies to
+ ensure exception safety.
+
+ Special Characteristics
+ -----------------------
+ - heap_ptr<> transfers constness from the owning object to
+ the pointed to object. Such it behaves like if *get() would be
+ a normal member of the owning object, not a pointer member.
+ This is preferable to the normal pointer behaviour, because
+ if an object is owned by another one, it is normally part of
+ its state.
+
+ - heap_ptr<> provides a ->release() function
+
+ - For reasons of simplicity and portability ->is()
+ is preferred over the safe-bool idiom.
+
+ Copyability
+ -----------
+ heap_ptr is non copyable.
+ - It forbids the copyconstructor and operator=(self).
+
+ - Owning classes will automatically be non copyable, if they do not
+ redefine those two functions themselves.
+
+ Incomplete Types
+ ----------------
+ heap_ptr<> also works with incomplete types. You only need to write
+ class T;
+ but need not include <T>.hxx.
+
+ If you use heap_ptr<> with an incomplete type, the owning class
+ needs to define a non-inline destructor. Else the compiler will
+ complain.
+*/
+template <class T>
+class heap_ptr
+{
+ public:
+ typedef T element_type; /// Provided for generic programming.
+ typedef heap_ptr<T> self;
+
+#ifndef __SUNPRO_CC
+ typedef T * (self::* safe_bool )();
+#endif
+
+ /// Now, pass_heapObject is owned by this.
+ explicit heap_ptr(
+ T * pass_heapObject = 0 );
+ ~heap_ptr();
+
+
+ /** Identical to reset(), except of the return value.
+ @see heap_ptr<>::reset()
+ */
+ self & operator=(
+ T * pass_heapObject );
+ const T & operator*() const;
+ T & operator*();
+ const T * operator->() const;
+ T * operator->();
+
+ /// True, if pHeapObject != 0.
+#ifndef __SUNPRO_CC
+ operator safe_bool() const;
+#else // workaround opt bug of Sun C++ compiler, when compiling with -xO3
+ operator bool() const;
+#endif
+
+
+ /** This deletes any prevoiusly existing ->pHeapObject.
+ Now, pass_heapObject, if != 0, is owned by this.
+
+ @onerror
+ Ignores self-assignment.
+ Such, multiple assignment of the same pointer to the same
+ instance of heap_ptr<> is possible (though not recommended).
+ */
+ void reset(
+ T * pass_heapObject );
+ /** @return An object on the heap that must be deleted by the caller,
+ or 0.
+
+ @postcond get() == 0;
+ */
+ T * release();
+ void swap(
+ self & io_other );
+
+ /// True, if pHeapObject != 0.
+ bool is() const;
+ const T * get() const;
+ T * get();
+
+ private:
+ // Forbidden functions:
+ heap_ptr( const self & ); /// Prevent copies.
+ self & operator=( const self & ); /// Prevent copies.
+
+ /// @attention Does not set ->pHeapObject = 0.
+ void internal_delete();
+
+ // DATA
+ /// Will be deleted, when *this is destroyed.
+ T * pHeapObject;
+};
+
+
+/** Supports the semantic of std::swap(). Provided as an aid to
+ generic programming.
+*/
+template<class T>
+inline void
+swap( heap_ptr<T> & io_a,
+ heap_ptr<T> & io_b )
+{
+ io_a.swap(io_b);
+}
+
+
+
+// IMPLEMENTATION
+
+template <class T>
+inline void
+heap_ptr<T>::internal_delete()
+{
+ ::boost::checked_delete(pHeapObject);
+
+ // Do not set pHeapObject to 0, because
+ // that is reset to a value in all code
+ // where internal_delete() is used.
+}
+
+template <class T>
+inline
+heap_ptr<T>::heap_ptr( T * pass_heapObject )
+ : pHeapObject(pass_heapObject)
+{
+}
+
+template <class T>
+inline
+heap_ptr<T>::~heap_ptr()
+{
+ internal_delete();
+}
+
+template <class T>
+inline heap_ptr<T> &
+heap_ptr<T>::operator=(T * pass_heapObject)
+{
+ reset(pass_heapObject);
+ return *this;
+}
+
+template <class T>
+inline const T &
+heap_ptr<T>::operator*() const
+{
+ BOOST_ASSERT( pHeapObject != 0
+ && "Accessing a heap_ptr<>(0)." );
+ return *pHeapObject;
+}
+
+template <class T>
+inline T &
+heap_ptr<T>::operator*()
+{
+ BOOST_ASSERT( pHeapObject != 0
+ && "Accessing a heap_ptr<>(0)." );
+ return *pHeapObject;
+}
+
+template <class T>
+inline const T *
+heap_ptr<T>::operator->() const
+{
+ return pHeapObject;
+}
+
+template <class T>
+inline T *
+heap_ptr<T>::operator->()
+{
+ return pHeapObject;
+}
+
+#ifndef __SUNPRO_CC
+
+template <class T>
+inline
+heap_ptr<T>::operator typename heap_ptr<T>::safe_bool() const
+{
+ return is()
+ ? safe_bool(&self::get)
+ : safe_bool(0);
+}
+
+#else
+
+template <class T>
+inline heap_ptr<T>::operator bool() const
+{
+ return is();
+}
+
+#endif // !defined(__SUNPRO_CC)
+
+
+
+template <class T>
+void
+heap_ptr<T>::reset(T * pass_heapObject)
+{
+ if ( pHeapObject != 0
+ && pHeapObject == pass_heapObject)
+ return;
+
+ internal_delete();
+ pHeapObject = pass_heapObject;
+}
+
+template <class T>
+T *
+heap_ptr<T>::release()
+{
+ T * ret = pHeapObject;
+ pHeapObject = 0;
+ return ret;
+}
+
+template <class T>
+void
+heap_ptr<T>::swap(self & io_other)
+{
+ T * temp = io_other.pHeapObject;
+ io_other.pHeapObject = pHeapObject;
+ pHeapObject = temp;
+}
+
+template <class T>
+inline bool
+heap_ptr<T>::is() const
+{
+ return pHeapObject != 0;
+}
+
+template <class T>
+inline const T *
+heap_ptr<T>::get() const
+{
+ return pHeapObject;
+}
+
+template <class T>
+inline T *
+heap_ptr<T>::get()
+{
+ return pHeapObject;
+}
+
+
+} // namespace o3tl
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/lazy_update.hxx b/include/o3tl/lazy_update.hxx
new file mode 100644
index 000000000000..b05bda37ba40
--- /dev/null
+++ b/include/o3tl/lazy_update.hxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_O3TL_LAZY_UPDATE_HXX
+#define INCLUDED_O3TL_LAZY_UPDATE_HXX
+
+#include <sal/types.h>
+#include <boost/function.hpp>
+
+namespace o3tl
+{
+ /** Update output object lazily
+
+ This template collects data in input type, and updates the
+ output type with the given update functor, but only if the
+ output is requested. Usefúl if updating is expensive, or input
+ changes frequently, but output is only comparatively seldom
+ used.
+
+ @example
+ <pre>
+LazyUpdate<InType,OutType,LAZYUPDATE_DIRECT_TAG> myValue;
+*myValue = newInput;
+myValue->updateInput( this, that, those );
+
+output( *myValue );
+ </pre>
+ or
+ <pre>
+output( myValue.getOutValue() );
+ </pre>
+ if the compiler does not recognize the const context.
+ */
+ template< typename InputType, typename OutputType, typename Tag > class LazyUpdate;
+
+ /// LazyUpdate specialization takes boost::function argument
+ struct LAZYUPDATE_FUNCTOR_TAG {};
+ /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument
+ struct LAZYUPDATE_FUNCTION_TAG {};
+ /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument
+ struct LAZYUPDATE_DIRECT_TAG {};
+
+ // -----------------------------------------------------------------------------------------------------
+
+ namespace detail
+ {
+ /// @internal
+ template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor
+ {
+ public:
+ typedef OutputType output_type;
+ typedef InputType input_type;
+
+ LazyUpdateImpl() :
+ m_aInput()
+ {}
+
+ template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) :
+ Functor(rParm),
+ m_aInput()
+ {}
+
+ enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG };
+ LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) :
+ m_aInput(rInput)
+ {}
+
+ template< typename ParamType > LazyUpdateImpl( ParamType const& rParm,
+ const input_type& rInput ) :
+ Functor(rParm),
+ m_aInput(rInput)
+ {}
+
+ // default copy ctor/assignment operator are ok
+ // LazyUpdate( const LazyUpdate& );
+ // LazyUpdate& operator=( const LazyUpdate& );
+
+ void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; }
+ input_type const& getInValue() const { return m_aInput; }
+ output_type const& getOutValue() const { return this->implUpdateValue(m_aInput); }
+
+ input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; }
+ input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; }
+
+ output_type const& operator*() const { return this->implUpdateValue(m_aInput); }
+ output_type const* operator->() const { return &(this->implUpdateValue(m_aInput)); }
+
+ private:
+ input_type m_aInput;
+ };
+
+ template< typename InputType, typename OutputType > struct DefaultFunctor
+ {
+ protected:
+ typedef OutputType output_type;
+ typedef InputType input_type;
+
+ DefaultFunctor() :
+ m_aOutput(),
+ m_bCacheDirty(true)
+ {}
+
+ OutputType const& implUpdateValue( input_type const& rIn ) const
+ {
+ if( m_bCacheDirty )
+ {
+ m_aOutput = output_type( rIn );
+ m_bCacheDirty = false;
+ }
+
+ return m_aOutput;
+ }
+
+ mutable output_type m_aOutput;
+ mutable bool m_bCacheDirty; // when true, m_aOutput needs update
+ };
+
+ template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer
+ {
+ protected:
+ typedef OutputType output_type;
+ typedef InputType input_type;
+ typedef FunctionType function_type;
+
+ FunctionPointer() :
+ m_pFunc(),
+ m_aOutput(),
+ m_bCacheDirty(true)
+
+ {}
+
+ explicit FunctionPointer( function_type const& pFunc ) :
+ m_pFunc(pFunc),
+ m_aOutput(),
+ m_bCacheDirty(true)
+
+ {}
+
+ output_type const& implUpdateValue( input_type const& rIn ) const
+ {
+ if( m_bCacheDirty )
+ {
+ m_aOutput = m_pFunc( rIn );
+ m_bCacheDirty = false;
+ }
+
+ return m_aOutput;
+ }
+
+ function_type m_pFunc;
+ mutable output_type m_aOutput;
+ mutable bool m_bCacheDirty; // when true, m_aOutput needs update
+ };
+ }
+
+ // -----------------------------------------------------------------------------------------------------
+
+ // partial specializations for the three LAZYUPDATE_* tags
+
+ template< typename InputType, typename OutputType > class LazyUpdate<InputType,
+ OutputType,
+ LAZYUPDATE_DIRECT_TAG> :
+ public detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::DefaultFunctor<InputType, OutputType> >
+ {
+ public:
+ LazyUpdate() {}
+ explicit LazyUpdate( InputType const& rIn ) :
+ detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::DefaultFunctor<InputType, OutputType> >(
+ rIn,
+ detail::LazyUpdateImpl<
+ InputType,
+ OutputType,
+ detail::DefaultFunctor<InputType, OutputType> >::UNARY_CONSTRUCTOR_TAG )
+ {}
+ };
+
+ // -----------------------------------------------------------------------------------------------------
+
+ template< typename InputType, typename OutputType > class LazyUpdate<InputType,
+ OutputType,
+ LAZYUPDATE_FUNCTION_TAG> :
+ public detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ OutputType (*)( InputType const& ) > >
+ {
+ public:
+ explicit LazyUpdate( OutputType (*pFunc)( InputType const& ) ) :
+ detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ OutputType (*)( InputType const& )> >(pFunc)
+ {}
+ LazyUpdate( OutputType (*pFunc)( InputType const& ),
+ InputType const& rIn ) :
+ detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ OutputType (*)( InputType const& )> >(pFunc,rIn)
+ {}
+ };
+
+ // -----------------------------------------------------------------------------------------------------
+
+ template< typename InputType, typename OutputType > class LazyUpdate<InputType,
+ OutputType,
+ LAZYUPDATE_FUNCTOR_TAG> :
+ public detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ boost::function1<OutputType,InputType> > >
+ {
+ public:
+ explicit LazyUpdate( boost::function1<OutputType,InputType> const& rFunc ) :
+ detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ boost::function1<OutputType,InputType> > >(rFunc)
+ {}
+ LazyUpdate( boost::function1<OutputType,InputType> const& rFunc,
+ InputType const& rIn ) :
+ detail::LazyUpdateImpl<InputType,
+ OutputType,
+ detail::FunctionPointer<
+ InputType,
+ OutputType,
+ boost::function1<OutputType,InputType> > >(rFunc,rIn)
+ {}
+ };
+
+}
+
+#endif /* INCLUDED_O3TL_LAZY_UPDATE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/range.hxx b/include/o3tl/range.hxx
new file mode 100644
index 000000000000..a5ebacb4c6b8
--- /dev/null
+++ b/include/o3tl/range.hxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_O3TL_RANGE_HXX
+#define INCLUDED_O3TL_RANGE_HXX
+
+
+#include <cstring> // for std::size_t
+#include <boost/assert.hpp>
+
+
+
+namespace o3tl
+{
+/** Represents a range of integer or iterator values.
+
+ @tpl T
+ Has to be assignable, add- and subtractable. That is:
+ either it is
+ - an integral type
+ - or a random access iterator.
+*/
+template <class T>
+class range
+{
+ public:
+ typedef T element_type; /// Provided for generic programming.
+ typedef range<T> self;
+
+ // LIFECYCLE
+ range(
+ T i_inclusiveLowerBorder,
+ T i_exclusiveUpperBorder );
+ ~range();
+ // INQUIRY
+ T begin() const;
+ T end() const;
+ std::size_t size() const;
+
+ bool contains(
+ T i_value ) const;
+ bool contains(
+ const self & i_other ) const;
+ bool overlaps(
+ const self & i_other ) const;
+ /// @return i_other.begin() - this->end()
+ long distance_to(
+ const self & i_other ) const;
+ private:
+ // DATA
+ T nBegin;
+ T nEnd;
+};
+
+
+template <class T>
+inline range<T>
+make_range(T i1, T i2)
+{
+ return range<T>(i1, i2);
+}
+
+template <class T>
+inline range<typename T::const_iterator>
+range_of(const T & i_container)
+{
+ return make_range( i_container.begin(),
+ i_container.end()
+ );
+}
+
+template <class T>
+inline range<typename T::iterator>
+range_of(T & io_container)
+{
+ return make_range( io_container.begin(),
+ io_container.end()
+ );
+}
+
+
+
+
+
+// IMPLEMENTATION
+
+template <class T>
+range<T>::range( T i_inclusiveLowerBorder,
+ T i_exclusiveUpperBorder )
+ : nBegin(i_inclusiveLowerBorder),
+ nEnd(i_exclusiveUpperBorder)
+{
+ BOOST_ASSERT( nBegin <= nEnd
+ && "Invalid parameters for range<> constructor.");
+}
+
+template <class T>
+range<T>::~range()
+{
+}
+
+template <class T>
+inline T
+range<T>::begin() const
+{
+ return nBegin;
+}
+
+template <class T>
+inline T
+range<T>::end() const
+{
+ return nEnd;
+}
+
+template <class T>
+inline std::size_t
+range<T>::size() const
+{
+ BOOST_ASSERT( nBegin <= nEnd
+ && "Invalid range limits in range<>::size().");
+ return static_cast<std::size_t>( end() - begin() );
+}
+
+template <class T>
+bool
+range<T>::contains(T i_value ) const
+{
+ return begin() <= i_value
+ && i_value < end();
+}
+
+template <class T>
+bool
+range<T>::contains(const self & i_other) const
+{
+ // This is subtle, because this would be wrong:
+ // begin() <= i_other.begin()
+ // && i_other.end() <= end();
+ // An empty range that begins and starts at my end()
+ // must not be contained.
+
+ return contains(i_other.begin())
+ && i_other.end() <= end();
+}
+
+template <class T>
+bool
+range<T>::overlaps(const self & i_other) const
+{
+ return contains(i_other.begin())
+ || i_other.contains(begin());
+}
+
+template <class T>
+long
+range<T>::distance_to(const self & i_other) const
+{
+ return i_other.begin() - end();
+}
+
+
+
+} // namespace o3tl
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/sorted_vector.hxx b/include/o3tl/sorted_vector.hxx
new file mode 100644
index 000000000000..776fd5605e6f
--- /dev/null
+++ b/include/o3tl/sorted_vector.hxx
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_O3TL_SORTED_VECTOR_HXX
+#define INCLUDED_O3TL_SORTED_VECTOR_HXX
+
+#include <vector>
+#include <functional>
+#include <algorithm>
+
+namespace o3tl
+{
+
+// forward declared because it's default tempate arg for sorted_vector
+template<class Value, class Compare>
+struct find_unique;
+
+/** Represents a sorted vector of values.
+
+ @tpl Value class of item to be stored in container
+ @tpl Compare comparison method
+ @tpl Find look up index of a Value in the array
+*/
+template<typename Value, typename Compare = std::less<Value>,
+ template<typename, typename> class Find = find_unique >
+class sorted_vector
+ : private std::vector<Value>
+{
+private:
+ typedef Find<Value, Compare> Find_t;
+ typedef typename std::vector<Value> base_t;
+ typedef typename std::vector<Value>::iterator iterator;
+public:
+ typedef typename std::vector<Value>::const_iterator const_iterator;
+ typedef typename std::vector<Value>::size_type size_type;
+
+ using base_t::clear;
+ using base_t::empty;
+ using base_t::size;
+
+ // MODIFIERS
+
+ std::pair<const_iterator,bool> insert( const Value& x )
+ {
+ std::pair<const_iterator, bool> const ret(Find_t()(begin(), end(), x));
+ if (!ret.second)
+ {
+ const_iterator const it = base_t::insert(
+ begin_nonconst() + (ret.first - begin()), x);
+ return std::make_pair(it, true);
+ }
+ return std::make_pair(ret.first, false);
+ }
+
+ size_type erase( const Value& x )
+ {
+ std::pair<const_iterator, bool> const ret(Find_t()(begin(), end(), x));
+ if (ret.second)
+ {
+ base_t::erase(begin_nonconst() + (ret.first - begin()));
+ return 1;
+ }
+ return 0;
+ }
+
+ void erase( size_t index )
+ {
+ base_t::erase( begin_nonconst() + index );
+ }
+
+ // like C++ 2011: erase with const_iterator (doesn't change sort order)
+ void erase(const_iterator const& position)
+ { // C++98 has vector::erase(iterator), so call that
+ base_t::erase(begin_nonconst() + (position - begin()));
+ }
+
+ void erase(const_iterator const& first, const_iterator const& last)
+ {
+ base_t::erase(begin_nonconst() + (first - begin()),
+ begin_nonconst() + (last - begin()));
+ }
+
+ // ACCESSORS
+
+ // Only return a const iterator, so that the vector cannot be directly updated.
+ const_iterator begin() const
+ {
+ return base_t::begin();
+ }
+
+ // Only return a const iterator, so that the vector cannot be directly updated.
+ const_iterator end() const
+ {
+ return base_t::end();
+ }
+
+ const Value& front() const
+ {
+ return base_t::front();
+ }
+
+ const Value& back() const
+ {
+ return base_t::back();
+ }
+
+ const Value& operator[]( size_t index ) const
+ {
+ return base_t::operator[]( index );
+ }
+
+ // OPERATIONS
+
+ const_iterator lower_bound( const Value& x ) const
+ {
+ return std::lower_bound( base_t::begin(), base_t::end(), x, Compare() );
+ }
+
+ const_iterator upper_bound( const Value& x ) const
+ {
+ return std::upper_bound( base_t::begin(), base_t::end(), x, Compare() );
+ }
+
+ /* Searches the container for an element with a value of x
+ * and returns an iterator to it if found, otherwise it returns an
+ * iterator to sorted_vector::end (the element past the end of the container).
+ *
+ * Only return a const iterator, so that the vector cannot be directly updated.
+ */
+ const_iterator find( const Value& x ) const
+ {
+ std::pair<const_iterator, bool> const ret(Find_t()(begin(), end(), x));
+ return (ret.second) ? ret.first : end();
+ }
+
+ void insert(sorted_vector<Value,Compare,Find> const& rOther)
+ {
+ // optimisation for the rather common case that we are overwriting this with the contents
+ // of another sorted vector
+ if ( empty() )
+ {
+ base_t::insert(begin_nonconst(), rOther.begin(), rOther.end());
+ }
+ else
+ for( const_iterator it = rOther.begin(); it != rOther.end(); ++it )
+ insert( *it );
+ }
+
+ /* Clear() elements in the vector, and free them one by one. */
+ void DeleteAndDestroyAll()
+ {
+ for( const_iterator it = begin(); it != end(); ++it )
+ delete *it;
+ clear();
+ }
+
+ // fdo#58793: some existing code in Writer (SwpHintsArray)
+ // routinely modifies the members of the vector in a way that
+ // violates the sort order, and then re-sorts the array.
+ // This is a kludge to enable that code to work.
+ // If you are calling this function, you are Doing It Wrong!
+ void Resort()
+ {
+ std::stable_sort(begin_nonconst(), end_nonconst(), Compare());
+ }
+
+private:
+
+ typename base_t::iterator begin_nonconst() { return base_t::begin(); }
+ typename base_t::iterator end_nonconst() { return base_t::end(); }
+
+};
+
+
+/** Implements an ordering function over a pointer, where the comparison uses the < operator on the pointed-to types.
+ Very useful for the cases where we put pointers to objects inside a sorted_vector.
+*/
+template <class T> struct less_ptr_to : public std::binary_function <T*,T*,bool>
+{
+ bool operator() ( T* const& lhs, T* const& rhs ) const
+ {
+ return (*lhs) < (*rhs);
+ }
+};
+
+/** the elements are totally ordered by Compare,
+ for no 2 elements !Compare(a,b) && !Compare(b,a) is true
+ */
+template<class Value, class Compare>
+struct find_unique
+{
+ typedef typename sorted_vector<Value, Compare,
+ o3tl::find_unique> ::const_iterator const_iterator;
+ std::pair<const_iterator, bool> operator()(
+ const_iterator first, const_iterator last,
+ Value const& v)
+ {
+ const_iterator const it = std::lower_bound(first, last, v, Compare());
+ return std::make_pair(it, (it != last && !Compare()(v, *it)));
+ }
+};
+
+/** the elements are partially ordered by Compare,
+ 2 elements are allowed if they are not the same element (pointer equal)
+ */
+template<class Value, class Compare>
+struct find_partialorder_ptrequals
+{
+ typedef typename sorted_vector<Value, Compare,
+ o3tl::find_partialorder_ptrequals>::const_iterator const_iterator;
+ std::pair<const_iterator, bool> operator()(
+ const_iterator first, const_iterator last,
+ Value const& v)
+ {
+ std::pair<const_iterator, const_iterator> const its =
+ std::equal_range(first, last, v, Compare());
+ for (const_iterator it = its.first; it != its.second; ++it)
+ {
+ if (v == *it)
+ {
+ return std::make_pair(it, true);
+ }
+ }
+ return std::make_pair(its.first, false);
+ }
+};
+
+} // namespace o3tl
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/vector_pool.hxx b/include/o3tl/vector_pool.hxx
new file mode 100644
index 000000000000..b132289af3ab
--- /dev/null
+++ b/include/o3tl/vector_pool.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_O3TL_VECTOR_POOL_HXX
+#define INCLUDED_O3TL_VECTOR_POOL_HXX
+
+#include <sal/types.h>
+#include <vector>
+
+namespace o3tl
+{
+ namespace detail
+ {
+ template<typename ValueType, class Container> class simple_pool_impl :
+ public Container
+ {
+ typedef typename Container::value_type value_type;
+ std::ptrdiff_t mnFirstFreeIndex;
+
+ public:
+ simple_pool_impl() :
+ mnFirstFreeIndex(-1)
+ {}
+
+ std::ptrdiff_t alloc()
+ {
+ return store(ValueType());
+ }
+
+ std::ptrdiff_t store(const ValueType& rCopy)
+ {
+ if( mnFirstFreeIndex != -1 )
+ {
+ std::ptrdiff_t nIdx=mnFirstFreeIndex;
+ mnFirstFreeIndex = this->at(mnFirstFreeIndex).nextFree;
+ this->at(nIdx).value = rCopy;
+ this->at(nIdx).nextFree = -1;
+
+ return nIdx;
+ }
+ else
+ {
+ this->push_back(value_type(rCopy));
+ return this->size()-1;
+ }
+ }
+
+ void free( std::ptrdiff_t nIdx )
+ {
+ this->at(nIdx).nextFree = mnFirstFreeIndex;
+ mnFirstFreeIndex = nIdx;
+ }
+
+ const ValueType& get( std::ptrdiff_t nIdx ) const
+ {
+ return this->operator[](nIdx).value;
+ }
+ ValueType& get( std::ptrdiff_t nIdx )
+ {
+ return this->operator[](nIdx).value;
+ }
+ };
+
+ template< typename ValueType > struct struct_from_value
+ {
+ struct type
+ {
+ type() :
+ value(),
+ nextFree(-1)
+ {}
+ explicit type( const ValueType& val ) :
+ value(val),
+ nextFree(-1)
+ {}
+
+ ValueType value;
+ std::ptrdiff_t nextFree;
+ };
+ };
+ }
+
+ /** Simple vector-based memory pool allocator
+
+ This template can be used to provide simple pooled memory
+ allocation from a container class that adheres to the stl
+ random access container concept. Note that alloc/free works
+ with _indices_ into the container!
+
+ @example
+ <pre>
+vector_pool<type> myPool;
+int nIdx=myPool.alloc();
+myPool[nIdx] = myVal;
+ ... do stuff ...
+myPool.free(nIdx);
+ </pre>
+ */
+ template<typename ValueType> struct vector_pool :
+ public detail::simple_pool_impl<ValueType,
+ std::vector<typename detail::struct_from_value<ValueType>::type > >
+ {};
+}
+
+#endif /* INCLUDED_O3TL_VECTOR_POOL_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */