1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef OOX_HELPER_CONTAINERHELPER_HXX
25 #define OOX_HELPER_CONTAINERHELPER_HXX
26 
27 #include <map>
28 #include <vector>
29 #include <com/sun/star/uno/Reference.h>
30 #include <com/sun/star/uno/Sequence.h>
31 
32 namespace rtl { class OUString; }
33 
34 namespace com { namespace sun { namespace star {
35     namespace container { class XIndexAccess; }
36     namespace container { class XIndexContainer; }
37     namespace container { class XNameAccess; }
38     namespace container { class XNameContainer; }
39     namespace uno { class XComponentContext; }
40 } } }
41 
42 namespace oox {
43 
44 // ============================================================================
45 
46 /** A range of signed 32-bit integer values. */
47 struct ValueRange
48 {
49     sal_Int32           mnFirst;
50     sal_Int32           mnLast;
51 
ValueRangeoox::ValueRange52     inline explicit     ValueRange( sal_Int32 nValue = 0 ) : mnFirst( nValue ), mnLast( nValue ) {}
ValueRangeoox::ValueRange53     inline explicit     ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {}
54 
operator ==oox::ValueRange55     inline bool         operator==( const ValueRange& rRange ) const { return (mnFirst == rRange.mnFirst) && (mnLast == rRange.mnLast); }
operator !=oox::ValueRange56     inline bool         operator!=( const ValueRange& rRange ) const { return !(*this == rRange); }
containsoox::ValueRange57     inline bool         contains( sal_Int32 nValue ) const { return (mnFirst <= nValue) && (nValue <= mnLast); }
containsoox::ValueRange58     inline bool         contains( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnFirst) && (rRange.mnLast <= mnLast); }
intersectsoox::ValueRange59     inline bool         intersects( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnLast) && (rRange.mnFirst <= mnLast); }
60 };
61 
62 // ----------------------------------------------------------------------------
63 
64 typedef ::std::vector< ValueRange > ValueRangeVector;
65 
66 // ----------------------------------------------------------------------------
67 
68 /** An ordered list of value ranges. The insertion operation will merge
69     consecutive value ranges.
70  */
71 class ValueRangeSet
72 {
73 public:
ValueRangeSet()74     inline explicit     ValueRangeSet() {}
75 
76     /** Inserts the passed value into the range list. */
insert(sal_Int32 nValue)77     inline void         insert( sal_Int32 nValue ) { insert( ValueRange( nValue ) ); }
78     /** Inserts the passed value range into the range list. */
79     void                insert( const ValueRange& rRange );
80 
81     /** Returns the ordered list of all value ranges. */
getRanges() const82     inline const ValueRangeVector& getRanges() const { return maRanges; }
83     /** Returns an intersection of the range list and the passed range. */
84     ValueRangeVector    getIntersection( const ValueRange& rRange ) const;
85 
86 private:
87     ValueRangeVector    maRanges;
88 };
89 
90 // ============================================================================
91 
92 /** Template for a 2-dimensional array of objects.
93 
94     This class template provides a similar interface to the ::std::vector
95     template.
96  */
97 template< typename Type >
98 class Matrix
99 {
100 public:
101     typedef ::std::vector< Type >                       container_type;
102     typedef typename container_type::value_type         value_type;
103     typedef typename container_type::pointer            pointer;
104     typedef typename container_type::reference          reference;
105     typedef typename container_type::const_reference    const_reference;
106     typedef typename container_type::size_type          size_type;
107     typedef typename container_type::iterator           iterator;
108     typedef typename container_type::const_iterator     const_iterator;
109 
Matrix()110     inline explicit     Matrix() : mnWidth( 0 ) {}
Matrix(size_type nWidth,size_type nHeight)111     inline explicit     Matrix( size_type nWidth, size_type nHeight ) { this->resize( nWidth, nHeight ); }
Matrix(size_type nWidth,size_type nHeight,const_reference rData)112     inline explicit     Matrix( size_type nWidth, size_type nHeight, const_reference rData ) { this->resize( nWidth, nHeight, rData ); }
113 
capacity() const114     inline size_type    capacity() const { return maData.capacity(); }
empty() const115     inline bool         empty() const { return maData.empty(); }
size() const116     inline size_type    size() const { return maData.size(); }
width() const117     inline size_type    width() const { return mnWidth; }
height() const118     inline size_type    height() const { return this->empty() ? 0 : (this->size() / this->width()); }
has(size_type nX,size_type nY) const119     inline bool         has( size_type nX, size_type nY ) const { return (nX < this->width()) && (nY < this->height()); }
120 
reserve(size_type nWidth,size_type nHeight)121     inline void         reserve( size_type nWidth, size_type nHeight ) { maData.reserve( nWidth * nHeight ); }
clear()122     inline void         clear() { this->resize( 0, 0 ); }
resize(size_type nWidth,size_type nHeight)123     inline void         resize( size_type nWidth, size_type nHeight ) { mnWidth = nWidth; maData.resize( nWidth * nHeight ); }
resize(size_type nWidth,size_type nHeight,const_reference rData)124     inline void         resize( size_type nWidth, size_type nHeight, const_reference rData ) { mnWidth = nWidth; maData.resize( nWidth * nHeight, rData ); }
125 
at(size_type nX,size_type nY)126     inline iterator     at( size_type nX, size_type nY ) { return maData.begin() + mnWidth * nY + nX; }
at(size_type nX,size_type nY) const127     inline const_iterator at( size_type nX, size_type nY ) const { return maData.begin() + mnWidth * nY + nX; }
128 
operator ()(size_type nX,size_type nY)129     inline reference    operator()( size_type nX, size_type nY ) { return *this->at( nX, nY ); }
operator ()(size_type nX,size_type nY) const130     inline const_reference operator()( size_type nX, size_type nY ) const { return *this->at( nX, nY ); }
131 
begin()132     inline iterator     begin() { return maData.begin(); }
begin() const133     inline const_iterator begin() const { return maData.begin(); }
end()134     inline iterator     end() { return maData.end(); }
end() const135     inline const_iterator end() const { return maData.end(); }
136 
front()137     inline reference    front() { return maData.front(); }
front() const138     inline const_reference front() const { return maData.front(); }
back()139     inline reference    back() { return maData.back(); }
back() const140     inline const_reference back() const { return maData.back(); }
141 
row_begin(size_type nY)142     inline iterator     row_begin( size_type nY ) { return this->at( 0, nY ); }
row_begin(size_type nY) const143     inline const_iterator row_begin( size_type nY ) const { return this->at( 0, nY ); }
row_end(size_type nY)144     inline iterator     row_end( size_type nY ) { return this->at( mnWidth, nY ); }
row_end(size_type nY) const145     inline const_iterator row_end( size_type nY ) const { return this->at( mnWidth, nY ); }
146 
row_front(size_type nY)147     inline reference    row_front( size_type nY ) { return (*this)( 0, nY ); }
row_front(size_type nY) const148     inline const_reference row_front( size_type nY ) const { return (*this)( 0, nY ); }
row_back(size_type nY)149     inline reference    row_back( size_type nY ) { return (*this)( mnWidth - 1, nY ); }
row_back(size_type nY) const150     inline const_reference row_back( size_type nY ) const { return (*this)( mnWidth - 1, nY ); }
151 
swap(Matrix & rMatrix)152     inline void         swap( Matrix& rMatrix ) { maData.swap( rMatrix.maData ); }
153 
154 private:
155     container_type      maData;
156     size_type           mnWidth;
157 };
158 
159 // ============================================================================
160 
161 /** Static helper functions for improved API container handling. */
162 class ContainerHelper
163 {
164 public:
165     // com.sun.star.container.XIndexContainer ---------------------------------
166 
167     /** Creates a new index container object from scratch. */
168     static ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer >
169                         createIndexContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext );
170 
171     /** Inserts an object into an indexed container.
172 
173         @param rxIndexContainer  com.sun.star.container.XIndexContainer
174             interface of the indexed container.
175 
176         @param nIndex  Insertion index for the object.
177 
178         @param rObject  The object to be inserted.
179 
180         @return  True = object successfully inserted.
181      */
182     static bool         insertByIndex(
183                             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer >& rxIndexContainer,
184                             sal_Int32 nIndex,
185                             const ::com::sun::star::uno::Any& rObject );
186 
187     // com.sun.star.container.XNameContainer ----------------------------------
188 
189     /** Creates a new name container object from scratch. */
190     static ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
191                         createNameContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext );
192 
193     /** Returns a name that is not used in the passed name container.
194 
195         @param rxNameAccess  com.sun.star.container.XNameAccess interface of
196             the name container.
197 
198         @param rSuggestedName  Suggested name for the object.
199 
200         @return  An unused name. Will be equal to the suggested name, if not
201             contained, otherwise a numerical index will be appended.
202      */
203     static ::rtl::OUString getUnusedName(
204                             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxNameAccess,
205                             const ::rtl::OUString& rSuggestedName,
206                             sal_Unicode cSeparator,
207                             sal_Int32 nFirstIndexToAppend = 1 );
208 
209     /** Inserts an object into a name container.
210 
211         @param rxNameContainer  com.sun.star.container.XNameContainer interface
212             of the name container.
213 
214         @param rName  Exact name for the object.
215 
216         @param rObject  The object to be inserted.
217 
218         @return  True = object successfully inserted.
219      */
220     static bool         insertByName(
221                             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxNameContainer,
222                             const ::rtl::OUString& rName,
223                             const ::com::sun::star::uno::Any& rObject,
224                             bool bReplaceOldExisting = true );
225 
226     /** Inserts an object into a name container.
227 
228         The function will use an unused name to insert the object, based on the
229         suggested object name. It is possible to specify whether the existing
230         object or the new inserted object will be renamed, if the container
231         already has an object with the name suggested for the new object.
232 
233         @param rxNameContainer  com.sun.star.container.XNameContainer interface
234             of the name container.
235 
236         @param rSuggestedName  Suggested name for the object.
237 
238         @param rObject  The object to be inserted.
239 
240         @param bRenameOldExisting  Specifies behaviour if an object with the
241             suggested name already exists. If false (default), the new object
242             will be inserted with a name not yet extant in the container (this
243             is done by appending a numerical index to the suggested name). If
244             true, the existing object will be removed and inserted with an
245             unused name, and the new object will be inserted with the suggested
246             name.
247 
248         @return  The final name the object is inserted with. Will always be
249             equal to the suggested name, if parameter bRenameOldExisting is
250             true.
251      */
252     static ::rtl::OUString insertByUnusedName(
253                             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxNameContainer,
254                             const ::rtl::OUString& rSuggestedName,
255                             sal_Unicode cSeparator,
256                             const ::com::sun::star::uno::Any& rObject,
257                             bool bRenameOldExisting = false );
258 
259     // std::vector and std::map element access --------------------------------
260 
261     /** Returns the pointer to an existing element of the passed vector, or a
262         null pointer, if the passed index is out of bounds. */
263     template< typename VectorType >
264     static const typename VectorType::value_type*
265                         getVectorElement( const VectorType& rVector, sal_Int32 nIndex );
266 
267     /** Returns the pointer to an existing element of the passed vector, or a
268         null pointer, if the passed index is out of bounds. */
269     template< typename VectorType >
270     static typename VectorType::value_type*
271                         getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex );
272 
273     /** Returns the reference to an existing element of the passed vector, or
274         the passed default value, if the passed index is out of bounds. */
275     template< typename VectorType >
276     static const typename VectorType::value_type&
277                         getVectorElement( const VectorType& rVector, sal_Int32 nIndex, const typename VectorType::value_type& rDefault );
278 
279     /** Returns the reference to an existing element of the passed vector, or
280         the passed default value, if the passed index is out of bounds. */
281     template< typename VectorType >
282     static typename VectorType::value_type&
283                         getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex, typename VectorType::value_type& rDefault );
284 
285     /** Returns the pointer to an existing element of the passed map, or a null
286         pointer, if an element with the passed key does not exist. */
287     template< typename MapType >
288     static const typename MapType::mapped_type*
289                         getMapElement( const MapType& rMap, const typename MapType::key_type& rKey );
290 
291     /** Returns the pointer to an existing element of the passed map, or a null
292         pointer, if an element with the passed key does not exist. */
293     template< typename MapType >
294     static typename MapType::mapped_type*
295                         getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey );
296 
297     /** Returns the reference to an existing element of the passed map, or the
298         passed default value, if an element with the passed key does not exist. */
299     template< typename MapType >
300     static const typename MapType::mapped_type&
301                         getMapElement( const MapType& rMap, const typename MapType::key_type& rKey, const typename MapType::mapped_type& rDefault );
302 
303     /** Returns the reference to an existing element of the passed map, or the
304         passed default value, if an element with the passed key does not exist. */
305     template< typename MapType >
306     static typename MapType::mapped_type&
307                         getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey, typename MapType::mapped_type& rDefault );
308 
309     // vector/map/matrix to UNO sequence --------------------------------------
310 
311     /** Creates a UNO sequence from a std::vector with copies of all elements.
312 
313         @param rVector  The vector to be converted to a sequence.
314 
315         @return  A com.sun.star.uno.Sequence object with copies of all objects
316             contained in the passed vector.
317      */
318     template< typename VectorType >
319     static ::com::sun::star::uno::Sequence< typename VectorType::value_type >
320                             vectorToSequence( const VectorType& rVector );
321 
322     /** Creates a UNO sequence from a std::map with copies of all elements.
323 
324         @param rMap  The map to be converted to a sequence.
325 
326         @return  A com.sun.star.uno.Sequence object with copies of all objects
327             contained in the passed map.
328      */
329     template< typename MapType >
330     static ::com::sun::star::uno::Sequence< typename MapType::mapped_type >
331                             mapToSequence( const MapType& rMap );
332 
333     /** Creates a UNO sequence of sequences from a matrix with copies of all elements.
334 
335         @param rMatrix  The matrix to be converted to a sequence of sequences.
336 
337         @return  A com.sun.star.uno.Sequence object containing
338             com.sun.star.uno.Sequence objects with copies of all objects
339             contained in the passed matrix.
340      */
341     template< typename MatrixType >
342     static ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< typename MatrixType::value_type > >
343                             matrixToSequenceSequence( const MatrixType& rMatrix );
344 };
345 
346 // ----------------------------------------------------------------------------
347 
348 template< typename VectorType >
getVectorElement(const VectorType & rVector,sal_Int32 nIndex)349 /*static*/ const typename VectorType::value_type* ContainerHelper::getVectorElement( const VectorType& rVector, sal_Int32 nIndex )
350 {
351     return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? &rVector[ static_cast< size_t >( nIndex ) ] : 0;
352 }
353 
354 template< typename VectorType >
getVectorElementAccess(VectorType & rVector,sal_Int32 nIndex)355 /*static*/ typename VectorType::value_type* ContainerHelper::getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex )
356 {
357     return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? &rVector[ static_cast< size_t >( nIndex ) ] : 0;
358 }
359 
360 template< typename VectorType >
getVectorElement(const VectorType & rVector,sal_Int32 nIndex,const typename VectorType::value_type & rDefault)361 /*static*/ const typename VectorType::value_type& ContainerHelper::getVectorElement( const VectorType& rVector, sal_Int32 nIndex, const typename VectorType::value_type& rDefault )
362 {
363     return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? rVector[ static_cast< size_t >( nIndex ) ] : rDefault;
364 }
365 
366 template< typename VectorType >
getVectorElementAccess(VectorType & rVector,sal_Int32 nIndex,typename VectorType::value_type & rDefault)367 /*static*/ typename VectorType::value_type& ContainerHelper::getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex, typename VectorType::value_type& rDefault )
368 {
369     return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? rVector[ static_cast< size_t >( nIndex ) ] : rDefault;
370 }
371 
372 template< typename MapType >
getMapElement(const MapType & rMap,const typename MapType::key_type & rKey)373 /*static*/ const typename MapType::mapped_type* ContainerHelper::getMapElement( const MapType& rMap, const typename MapType::key_type& rKey )
374 {
375     typename MapType::const_iterator aIt = rMap.find( rKey );
376     return (aIt == rMap.end()) ? 0 : &aIt->second;
377 }
378 
379 template< typename MapType >
getMapElementAccess(MapType & rMap,const typename MapType::key_type & rKey)380 /*static*/ typename MapType::mapped_type* ContainerHelper::getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey )
381 {
382     typename MapType::iterator aIt = rMap.find( rKey );
383     return (aIt == rMap.end()) ? 0 : &aIt->second;
384 }
385 
386 template< typename MapType >
getMapElement(const MapType & rMap,const typename MapType::key_type & rKey,const typename MapType::mapped_type & rDefault)387 /*static*/ const typename MapType::mapped_type& ContainerHelper::getMapElement( const MapType& rMap, const typename MapType::key_type& rKey, const typename MapType::mapped_type& rDefault )
388 {
389     typename MapType::const_iterator aIt = rMap.find( rKey );
390     return (aIt == rMap.end()) ? rDefault : aIt->second;
391 }
392 
393 template< typename MapType >
getMapElementAccess(MapType & rMap,const typename MapType::key_type & rKey,typename MapType::mapped_type & rDefault)394 /*static*/ typename MapType::mapped_type& ContainerHelper::getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey, typename MapType::mapped_type& rDefault )
395 {
396     typename MapType::iterator aIt = rMap.find( rKey );
397     return (aIt == rMap.end()) ? rDefault : aIt->second;
398 }
399 
400 template< typename VectorType >
vectorToSequence(const VectorType & rVector)401 /*static*/ ::com::sun::star::uno::Sequence< typename VectorType::value_type > ContainerHelper::vectorToSequence( const VectorType& rVector )
402 {
403     typedef typename VectorType::value_type ValueType;
404     if( rVector.empty() )
405         return ::com::sun::star::uno::Sequence< ValueType >();
406     return ::com::sun::star::uno::Sequence< ValueType >( &rVector.front(), static_cast< sal_Int32 >( rVector.size() ) );
407 }
408 
409 template< typename MapType >
mapToSequence(const MapType & rMap)410 /*static*/ ::com::sun::star::uno::Sequence< typename MapType::mapped_type > ContainerHelper::mapToSequence( const MapType& rMap )
411 {
412     typedef typename MapType::mapped_type ValueType;
413     if( rMap.empty() )
414         return ::com::sun::star::uno::Sequence< ValueType >();
415     ::com::sun::star::uno::Sequence< ValueType > aSeq( static_cast< sal_Int32 >( rMap.size() ) );
416     sal_Int32 nIndex = 0;
417     for( typename MapType::const_iterator aIt = rMap.begin(), aEnd = rMap.end(); aIt != aEnd; ++aIt, ++nIndex )
418         aSeq[ nIndex ] = *aIt;
419     return aSeq;
420 }
421 
422 template< typename MatrixType >
matrixToSequenceSequence(const MatrixType & rMatrix)423 /*static*/ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< typename MatrixType::value_type > > ContainerHelper::matrixToSequenceSequence( const MatrixType& rMatrix )
424 {
425     typedef typename MatrixType::value_type ValueType;
426     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ValueType > > aSeq;
427     if( !rMatrix.empty() )
428     {
429         aSeq.realloc( static_cast< sal_Int32 >( rMatrix.height() ) );
430         for( size_t nRow = 0, nHeight = rMatrix.height(); nRow < nHeight; ++nRow )
431             aSeq[ static_cast< sal_Int32 >( nRow ) ] =
432                 ::com::sun::star::uno::Sequence< ValueType >( &rMatrix.row_front( nRow ), static_cast< sal_Int32 >( rMatrix.width() ) );
433     }
434     return aSeq;
435 }
436 
437 // ============================================================================
438 
439 } // namespace oox
440 
441 #endif
442