diff options
Diffstat (limited to 'include/oox/helper/containerhelper.hxx')
-rw-r--r-- | include/oox/helper/containerhelper.hxx | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/include/oox/helper/containerhelper.hxx b/include/oox/helper/containerhelper.hxx new file mode 100644 index 000000000000..f3b27f05b1e2 --- /dev/null +++ b/include/oox/helper/containerhelper.hxx @@ -0,0 +1,410 @@ +/* -*- 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 OOX_HELPER_CONTAINERHELPER_HXX +#define OOX_HELPER_CONTAINERHELPER_HXX + +#include <map> +#include <vector> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.h> +#include "oox/dllapi.h" + + +namespace com { namespace sun { namespace star { + namespace container { class XIndexAccess; } + namespace container { class XIndexContainer; } + namespace container { class XNameAccess; } + namespace container { class XNameContainer; } + namespace uno { class XComponentContext; } +} } } + +namespace oox { + +// ============================================================================ + +/** A range of signed 32-bit integer values. */ +struct ValueRange +{ + sal_Int32 mnFirst; + sal_Int32 mnLast; + + inline explicit ValueRange( sal_Int32 nValue = 0 ) : mnFirst( nValue ), mnLast( nValue ) {} + inline explicit ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {} + + inline bool operator==( const ValueRange& rRange ) const { return (mnFirst == rRange.mnFirst) && (mnLast == rRange.mnLast); } + inline bool operator!=( const ValueRange& rRange ) const { return !(*this == rRange); } + inline bool contains( sal_Int32 nValue ) const { return (mnFirst <= nValue) && (nValue <= mnLast); } + inline bool contains( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnFirst) && (rRange.mnLast <= mnLast); } + inline bool intersects( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnLast) && (rRange.mnFirst <= mnLast); } +}; + +// ---------------------------------------------------------------------------- + +typedef ::std::vector< ValueRange > ValueRangeVector; + +// ---------------------------------------------------------------------------- + +/** An ordered list of value ranges. The insertion operation will merge + consecutive value ranges. + */ +class OOX_DLLPUBLIC ValueRangeSet +{ +public: + inline explicit ValueRangeSet() {} + + /** Inserts the passed value into the range list. */ + inline void insert( sal_Int32 nValue ) { insert( ValueRange( nValue ) ); } + /** Inserts the passed value range into the range list. */ + void insert( const ValueRange& rRange ); + + /** Returns the ordered list of all value ranges. */ + inline const ValueRangeVector& getRanges() const { return maRanges; } + +private: + ValueRangeVector maRanges; +}; + +// ============================================================================ + +/** Template for a 2-dimensional array of objects. + + This class template provides a similar interface to the ::std::vector + template. + */ +template< typename Type > +class Matrix +{ +public: + typedef ::std::vector< Type > container_type; + typedef typename container_type::value_type value_type; + typedef typename container_type::pointer pointer; + typedef typename container_type::reference reference; + typedef typename container_type::const_reference const_reference; + typedef typename container_type::size_type size_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + + inline explicit Matrix() : mnWidth( 0 ) {} + inline explicit Matrix( size_type nWidth, size_type nHeight ) { this->resize( nWidth, nHeight ); } + inline explicit Matrix( size_type nWidth, size_type nHeight, const_reference rData ) { this->resize( nWidth, nHeight, rData ); } + + inline size_type capacity() const { return maData.capacity(); } + inline bool empty() const { return maData.empty(); } + inline size_type size() const { return maData.size(); } + inline size_type width() const { return mnWidth; } + inline size_type height() const { return this->empty() ? 0 : (this->size() / this->width()); } + inline bool has( size_type nX, size_type nY ) const { return (nX < this->width()) && (nY < this->height()); } + + inline void reserve( size_type nWidth, size_type nHeight ) { maData.reserve( nWidth * nHeight ); } + inline void clear() { this->resize( 0, 0 ); } + inline void resize( size_type nWidth, size_type nHeight ) { mnWidth = nWidth; maData.resize( nWidth * nHeight ); } + inline void resize( size_type nWidth, size_type nHeight, const_reference rData ) { mnWidth = nWidth; maData.resize( nWidth * nHeight, rData ); } + + inline iterator at( size_type nX, size_type nY ) { return maData.begin() + mnWidth * nY + nX; } + inline const_iterator at( size_type nX, size_type nY ) const { return maData.begin() + mnWidth * nY + nX; } + + inline reference operator()( size_type nX, size_type nY ) { return *this->at( nX, nY ); } + inline const_reference operator()( size_type nX, size_type nY ) const { return *this->at( nX, nY ); } + + inline iterator begin() { return maData.begin(); } + inline const_iterator begin() const { return maData.begin(); } + inline iterator end() { return maData.end(); } + inline const_iterator end() const { return maData.end(); } + + inline reference front() { return maData.front(); } + inline const_reference front() const { return maData.front(); } + inline reference back() { return maData.back(); } + inline const_reference back() const { return maData.back(); } + + inline iterator row_begin( size_type nY ) { return this->at( 0, nY ); } + inline const_iterator row_begin( size_type nY ) const { return this->at( 0, nY ); } + inline iterator row_end( size_type nY ) { return this->at( mnWidth, nY ); } + inline const_iterator row_end( size_type nY ) const { return this->at( mnWidth, nY ); } + + inline reference row_front( size_type nY ) { return (*this)( 0, nY ); } + inline const_reference row_front( size_type nY ) const { return (*this)( 0, nY ); } + inline reference row_back( size_type nY ) { return (*this)( mnWidth - 1, nY ); } + inline const_reference row_back( size_type nY ) const { return (*this)( mnWidth - 1, nY ); } + + inline void swap( Matrix& rMatrix ) { maData.swap( rMatrix.maData ); } + +private: + container_type maData; + size_type mnWidth; +}; + +// ============================================================================ + +/** Static helper functions for improved API container handling. */ +class OOX_DLLPUBLIC ContainerHelper +{ +public: + + /** Returns a name that is not used in the passed name container. + + @param rxNameAccess com.sun.star.container.XNameAccess interface of + the name container. + + @param rSuggestedName Suggested name for the object. + + @return An unused name. Will be equal to the suggested name, if not + contained, otherwise a numerical index will be appended. + */ + static OUString getUnusedName( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxNameAccess, + const OUString& rSuggestedName, + sal_Unicode cSeparator, + sal_Int32 nFirstIndexToAppend = 1 ); + + /** Inserts an object into a name container. + + @param rxNameContainer com.sun.star.container.XNameContainer interface + of the name container. + + @param rName Exact name for the object. + + @param rObject The object to be inserted. + + @return True = object successfully inserted. + */ + static bool insertByName( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxNameContainer, + const OUString& rName, + const ::com::sun::star::uno::Any& rObject, + bool bReplaceOldExisting = true ); + + /** Inserts an object into a name container. + + The function will use an unused name to insert the object, based on the + suggested object name. It is possible to specify whether the existing + object or the new inserted object will be renamed, if the container + already has an object with the name suggested for the new object. + + @param rxNameContainer com.sun.star.container.XNameContainer interface + of the name container. + + @param rSuggestedName Suggested name for the object. + + @param rObject The object to be inserted. + + @param bRenameOldExisting Specifies behaviour if an object with the + suggested name already exists. If false (default), the new object + will be inserted with a name not yet extant in the container (this + is done by appending a numerical index to the suggested name). If + true, the existing object will be removed and inserted with an + unused name, and the new object will be inserted with the suggested + name. + + @return The final name the object is inserted with. Will always be + equal to the suggested name, if parameter bRenameOldExisting is + true. + */ + static OUString insertByUnusedName( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxNameContainer, + const OUString& rSuggestedName, + sal_Unicode cSeparator, + const ::com::sun::star::uno::Any& rObject, + bool bRenameOldExisting = false ); + + // std::vector and std::map element access -------------------------------- + + /** Returns the pointer to an existing element of the passed vector, or a + null pointer, if the passed index is out of bounds. */ + template< typename VectorType > + static const typename VectorType::value_type* + getVectorElement( const VectorType& rVector, sal_Int32 nIndex ); + + /** Returns the pointer to an existing element of the passed vector, or a + null pointer, if the passed index is out of bounds. */ + template< typename VectorType > + static typename VectorType::value_type* + getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex ); + + /** Returns the reference to an existing element of the passed vector, or + the passed default value, if the passed index is out of bounds. */ + template< typename VectorType > + static const typename VectorType::value_type& + getVectorElement( const VectorType& rVector, sal_Int32 nIndex, const typename VectorType::value_type& rDefault ); + + /** Returns the reference to an existing element of the passed vector, or + the passed default value, if the passed index is out of bounds. */ + template< typename VectorType > + static typename VectorType::value_type& + getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex, typename VectorType::value_type& rDefault ); + + /** Returns the pointer to an existing element of the passed map, or a null + pointer, if an element with the passed key does not exist. */ + template< typename MapType > + static const typename MapType::mapped_type* + getMapElement( const MapType& rMap, const typename MapType::key_type& rKey ); + + /** Returns the pointer to an existing element of the passed map, or a null + pointer, if an element with the passed key does not exist. */ + template< typename MapType > + static typename MapType::mapped_type* + getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey ); + + /** Returns the reference to an existing element of the passed map, or the + passed default value, if an element with the passed key does not exist. */ + template< typename MapType > + static const typename MapType::mapped_type& + getMapElement( const MapType& rMap, const typename MapType::key_type& rKey, const typename MapType::mapped_type& rDefault ); + + /** Returns the reference to an existing element of the passed map, or the + passed default value, if an element with the passed key does not exist. */ + template< typename MapType > + static typename MapType::mapped_type& + getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey, typename MapType::mapped_type& rDefault ); + + // vector/map/matrix to UNO sequence -------------------------------------- + + /** Creates a UNO sequence from a std::vector with copies of all elements. + + @param rVector The vector to be converted to a sequence. + + @return A com.sun.star.uno.Sequence object with copies of all objects + contained in the passed vector. + */ + template< typename VectorType > + static ::com::sun::star::uno::Sequence< typename VectorType::value_type > + vectorToSequence( const VectorType& rVector ); + + /** Creates a UNO sequence from a std::map with copies of all elements. + + @param rMap The map to be converted to a sequence. + + @return A com.sun.star.uno.Sequence object with copies of all objects + contained in the passed map. + */ + template< typename MapType > + static ::com::sun::star::uno::Sequence< typename MapType::mapped_type > + mapToSequence( const MapType& rMap ); + + /** Creates a UNO sequence of sequences from a matrix with copies of all elements. + + @param rMatrix The matrix to be converted to a sequence of sequences. + + @return A com.sun.star.uno.Sequence object containing + com.sun.star.uno.Sequence objects with copies of all objects + contained in the passed matrix. + */ + template< typename MatrixType > + static ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< typename MatrixType::value_type > > + matrixToSequenceSequence( const MatrixType& rMatrix ); +}; + +// ---------------------------------------------------------------------------- + +template< typename VectorType > +/*static*/ const typename VectorType::value_type* ContainerHelper::getVectorElement( const VectorType& rVector, sal_Int32 nIndex ) +{ + return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? &rVector[ static_cast< size_t >( nIndex ) ] : 0; +} + +template< typename VectorType > +/*static*/ typename VectorType::value_type* ContainerHelper::getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex ) +{ + return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? &rVector[ static_cast< size_t >( nIndex ) ] : 0; +} + +template< typename VectorType > +/*static*/ const typename VectorType::value_type& ContainerHelper::getVectorElement( const VectorType& rVector, sal_Int32 nIndex, const typename VectorType::value_type& rDefault ) +{ + return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? rVector[ static_cast< size_t >( nIndex ) ] : rDefault; +} + +template< typename VectorType > +/*static*/ typename VectorType::value_type& ContainerHelper::getVectorElementAccess( VectorType& rVector, sal_Int32 nIndex, typename VectorType::value_type& rDefault ) +{ + return ((0 <= nIndex) && (static_cast< size_t >( nIndex ) < rVector.size())) ? rVector[ static_cast< size_t >( nIndex ) ] : rDefault; +} + +template< typename MapType > +/*static*/ const typename MapType::mapped_type* ContainerHelper::getMapElement( const MapType& rMap, const typename MapType::key_type& rKey ) +{ + typename MapType::const_iterator aIt = rMap.find( rKey ); + return (aIt == rMap.end()) ? 0 : &aIt->second; +} + +template< typename MapType > +/*static*/ typename MapType::mapped_type* ContainerHelper::getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey ) +{ + typename MapType::iterator aIt = rMap.find( rKey ); + return (aIt == rMap.end()) ? 0 : &aIt->second; +} + +template< typename MapType > +/*static*/ const typename MapType::mapped_type& ContainerHelper::getMapElement( const MapType& rMap, const typename MapType::key_type& rKey, const typename MapType::mapped_type& rDefault ) +{ + typename MapType::const_iterator aIt = rMap.find( rKey ); + return (aIt == rMap.end()) ? rDefault : aIt->second; +} + +template< typename MapType > +/*static*/ typename MapType::mapped_type& ContainerHelper::getMapElementAccess( MapType& rMap, const typename MapType::key_type& rKey, typename MapType::mapped_type& rDefault ) +{ + typename MapType::iterator aIt = rMap.find( rKey ); + return (aIt == rMap.end()) ? rDefault : aIt->second; +} + +template< typename VectorType > +/*static*/ ::com::sun::star::uno::Sequence< typename VectorType::value_type > ContainerHelper::vectorToSequence( const VectorType& rVector ) +{ + typedef typename VectorType::value_type ValueType; + if( rVector.empty() ) + return ::com::sun::star::uno::Sequence< ValueType >(); + return ::com::sun::star::uno::Sequence< ValueType >( &rVector.front(), static_cast< sal_Int32 >( rVector.size() ) ); +} + +template< typename MapType > +/*static*/ ::com::sun::star::uno::Sequence< typename MapType::mapped_type > ContainerHelper::mapToSequence( const MapType& rMap ) +{ + typedef typename MapType::mapped_type ValueType; + if( rMap.empty() ) + return ::com::sun::star::uno::Sequence< ValueType >(); + ::com::sun::star::uno::Sequence< ValueType > aSeq( static_cast< sal_Int32 >( rMap.size() ) ); + sal_Int32 nIndex = 0; + for( typename MapType::const_iterator aIt = rMap.begin(), aEnd = rMap.end(); aIt != aEnd; ++aIt, ++nIndex ) + aSeq[ nIndex ] = *aIt; + return aSeq; +} + +template< typename MatrixType > +/*static*/ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< typename MatrixType::value_type > > ContainerHelper::matrixToSequenceSequence( const MatrixType& rMatrix ) +{ + typedef typename MatrixType::value_type ValueType; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ValueType > > aSeq; + if( !rMatrix.empty() ) + { + aSeq.realloc( static_cast< sal_Int32 >( rMatrix.height() ) ); + for( size_t nRow = 0, nHeight = rMatrix.height(); nRow < nHeight; ++nRow ) + aSeq[ static_cast< sal_Int32 >( nRow ) ] = + ::com::sun::star::uno::Sequence< ValueType >( &rMatrix.row_front( nRow ), static_cast< sal_Int32 >( rMatrix.width() ) ); + } + return aSeq; +} + +// ============================================================================ + +} // namespace oox + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |