1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_OOX_HELPER_REFVECTOR_HXX
21 #define INCLUDED_OOX_HELPER_REFVECTOR_HXX
22 
23 #include <algorithm>
24 #include <functional>
25 #include <memory>
26 #include <vector>
27 
28 #include <sal/types.h>
29 
30 namespace oox {
31 
32 
33 /** Template for a vector of ref-counted objects with additional accessor functions.
34 
35     An instance of the class RefVector< Type > stores elements of the type
36     std::shared_ptr< Type >. The new accessor functions has() and get()
37     work correctly for indexes out of the current range, there is no need to
38     check the passed index before.
39  */
40 template< typename ObjType >
41 class RefVector : public ::std::vector< std::shared_ptr< ObjType > >
42 {
43 public:
44     typedef ::std::vector< std::shared_ptr< ObjType > > container_type;
45     typedef typename container_type::value_type             value_type;
46     typedef typename container_type::size_type              size_type;
47 
48 public:
49 
50     /** Returns a reference to the object with the passed index, or 0 on error. */
get(sal_Int32 nIndex) const51     value_type          get( sal_Int32 nIndex ) const
52                         {
53                             if( const value_type* pxRef = getRef( nIndex ) ) return *pxRef;
54                             return value_type();
55                         }
56 
57     /** Calls the passed functor for every contained object, automatically
58         skips all elements that are empty references. */
59     template< typename FunctorType >
forEach(FunctorType aFunctor) const60     void                forEach( FunctorType aFunctor ) const
61                         {
62                             ::std::for_each( this->begin(), this->end(), ForEachFunctor< FunctorType >( aFunctor ) );
63                         }
64 
65     /** Calls the passed member function of ObjType on every contained object,
66         automatically skips all elements that are empty references. */
67     template< typename FuncType >
forEachMem(FuncType pFunc) const68     void                forEachMem( FuncType pFunc ) const
69                         {
70                             forEach( ::std::bind( pFunc, std::placeholders::_1 ) );
71                         }
72 
73     /** Calls the passed member function of ObjType on every contained object,
74         automatically skips all elements that are empty references. */
75     template< typename FuncType, typename ParamType >
forEachMem(FuncType pFunc,ParamType aParam) const76     void                forEachMem( FuncType pFunc, ParamType aParam ) const
77                         {
78                             forEach( ::std::bind( pFunc, std::placeholders::_1, aParam ) );
79                         }
80 
81     /** Calls the passed member function of ObjType on every contained object,
82         automatically skips all elements that are empty references. */
83     template< typename FuncType, typename ParamType1, typename ParamType2 >
forEachMem(FuncType pFunc,ParamType1 aParam1,ParamType2 aParam2) const84     void                forEachMem( FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2 ) const
85                         {
86                             forEach( ::std::bind( pFunc, std::placeholders::_1, aParam1, aParam2 ) );
87                         }
88 
89     /** Calls the passed member function of ObjType on every contained object,
90         automatically skips all elements that are empty references. */
91     template< typename FuncType, typename ParamType1, typename ParamType2, typename ParamType3 >
forEachMem(FuncType pFunc,ParamType1 aParam1,ParamType2 aParam2,ParamType3 aParam3) const92     void                forEachMem( FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2, ParamType3 aParam3 ) const
93                         {
94                             forEach( ::std::bind( pFunc, std::placeholders::_1, aParam1, aParam2, aParam3 ) );
95                         }
96 
97     /** Calls the passed functor for every contained object. Passes the index as
98         first argument and the object reference as second argument to rFunctor. */
99     template< typename FunctorType >
forEachWithIndex(const FunctorType & rFunctor) const100     void                forEachWithIndex( const FunctorType& rFunctor ) const
101                         {
102                             ::std::for_each( this->begin(), this->end(), ForEachFunctorWithIndex< FunctorType >( rFunctor ) );
103                         }
104 
105     /** Calls the passed member function of ObjType on every contained object.
106         Passes the vector index as first argument to the member function. */
107     template< typename FuncType, typename ParamType1, typename ParamType2 >
forEachMemWithIndex(FuncType pFunc,ParamType1 aParam1,ParamType2 aParam2) const108     void                forEachMemWithIndex( FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2 ) const
109                         {
110                             forEachWithIndex( ::std::bind( pFunc, std::placeholders::_2, std::placeholders::_1, aParam1, aParam2 ) );
111                         }
112 
113     /** Searches for an element by using the passed functor that takes a
114         constant reference of the object type (const ObjType&). */
115     template< typename FunctorType >
findIf(const FunctorType & rFunctor) const116     value_type          findIf( const FunctorType& rFunctor ) const
117                         {
118                             typename container_type::const_iterator aIt = ::std::find_if( this->begin(), this->end(), FindFunctor< FunctorType >( rFunctor ) );
119                             return (aIt == this->end()) ? value_type() : *aIt;
120                         }
121 
122 private:
123     template< typename FunctorType >
124     struct ForEachFunctor
125     {
126         FunctorType         maFunctor;
ForEachFunctoroox::RefVector::ForEachFunctor127         explicit            ForEachFunctor( const FunctorType& rFunctor ) : maFunctor( rFunctor ) {}
operator ()oox::RefVector::ForEachFunctor128         void                operator()( const value_type& rxValue ) { if( rxValue.get() ) maFunctor( *rxValue ); }
129     };
130 
131     template< typename FunctorType >
132     struct ForEachFunctorWithIndex
133     {
134         FunctorType         maFunctor;
135         sal_Int32           mnIndex;
ForEachFunctorWithIndexoox::RefVector::ForEachFunctorWithIndex136         explicit            ForEachFunctorWithIndex( const FunctorType& rFunctor ) : maFunctor( rFunctor ), mnIndex( 0 ) {}
operator ()oox::RefVector::ForEachFunctorWithIndex137         void                operator()( const value_type& rxValue ) {
138             if( rxValue.get() ) maFunctor( mnIndex, *rxValue );
139             ++mnIndex;
140         }
141     };
142 
143     template< typename FunctorType >
144     struct FindFunctor
145     {
146         FunctorType         maFunctor;
FindFunctoroox::RefVector::FindFunctor147         explicit            FindFunctor( const FunctorType& rFunctor ) : maFunctor( rFunctor ) {}
operator ()oox::RefVector::FindFunctor148         bool                operator()( const value_type& rxValue ) { return rxValue.get() && maFunctor( *rxValue ); }
149     };
150 
getRef(sal_Int32 nIndex) const151     const value_type*   getRef( sal_Int32 nIndex ) const
152                         {
153                             return ((0 <= nIndex) && (static_cast< size_type >( nIndex ) < this->size())) ?
154                                 &(*this)[ static_cast< size_type >( nIndex ) ] : 0;
155                         }
156 };
157 
158 
159 } // namespace oox
160 
161 #endif
162 
163 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
164