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