diff options
author | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2013-04-18 18:26:28 +0200 |
---|---|---|
committer | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2013-04-23 22:20:31 +0200 |
commit | b9337e22ce1dbf2eba0e8c8db294ae99f4111f91 (patch) | |
tree | 53ee1bd3dfd213815a21579151983cb997922b05 /include/o3tl | |
parent | f4e1642a1761d5eab6ccdd89928869c2b2f1528a (diff) |
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.hxx | 151 | ||||
-rw-r--r-- | include/o3tl/cow_wrapper.hxx | 322 | ||||
-rw-r--r-- | include/o3tl/heap_ptr.hxx | 305 | ||||
-rw-r--r-- | include/o3tl/lazy_update.hxx | 265 | ||||
-rw-r--r-- | include/o3tl/range.hxx | 183 | ||||
-rw-r--r-- | include/o3tl/sorted_vector.hxx | 237 | ||||
-rw-r--r-- | include/o3tl/vector_pool.hxx | 123 |
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. Usefl 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: */ |