diff options
Diffstat (limited to '')
-rw-r--r-- | include/com/sun/star/uno/Sequence.h | 335 | ||||
-rw-r--r-- | include/com/sun/star/uno/Sequence.hxx | 371 |
2 files changed, 706 insertions, 0 deletions
diff --git a/include/com/sun/star/uno/Sequence.h b/include/com/sun/star/uno/Sequence.h new file mode 100644 index 000000000..2ba8c71f8 --- /dev/null +++ b/include/com/sun/star/uno/Sequence.h @@ -0,0 +1,335 @@ +/* -*- 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_COM_SUN_STAR_UNO_SEQUENCE_H +#define INCLUDED_COM_SUN_STAR_UNO_SEQUENCE_H + +#include "typelib/typedescription.h" +#include "uno/sequence2.h" +#include "com/sun/star/uno/Type.h" +#include "rtl/alloc.h" + +#include <new> + +#if defined LIBO_INTERNAL_ONLY +#include <cassert> +#include <initializer_list> +#endif + +namespace rtl +{ +class ByteSequence; +} + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace uno +{ + +/** Template C++ class representing an IDL sequence. Template argument is the + sequence element type. C++ Sequences are reference counted and shared, + so the sequence keeps a handle to its data. To keep value semantics, + copies are only generated if the sequence is to be modified (new handle). + + @tparam E element type of sequence +*/ +template< class E > +class SAL_WARN_UNUSED SAL_DLLPUBLIC_RTTI Sequence +{ + /** sequence handle + */ + uno_Sequence * _pSequence; + +public: + /// @cond INTERNAL + + // these are here to force memory de/allocation to sal lib. + static void * SAL_CALL operator new ( ::size_t nSize ) + { return ::rtl_allocateMemory( nSize ); } + static void SAL_CALL operator delete ( void * pMem ) + { ::rtl_freeMemory( pMem ); } + static void * SAL_CALL operator new ( ::size_t, void * pMem ) + { return pMem; } + static void SAL_CALL operator delete ( void *, void * ) + {} + + /** Static pointer to typelib type of sequence. + Don't use directly, call getCppuType(). + */ + static typelib_TypeDescriptionReference * s_pType; + + /// @endcond + + /** typedefs the element type of the sequence + */ + typedef E ElementType; + + /** Default constructor: Creates an empty sequence. + */ + inline Sequence(); + + /** Copy constructor: Creates a copy of given sequence. + + @param rSeq another sequence of same type + */ + inline Sequence( const Sequence & rSeq ); + + /** Constructor: Takes over ownership of given sequence. + + @param pSequence a sequence + @param dummy SAL_NO_ACQUIRE to force obvious distinction to other + constructors + */ + inline Sequence( uno_Sequence * pSequence, __sal_NoAcquire dummy ); + + /** Constructor: Creates a copy of given elements. + + @param pElements an array of elements + @param len length of array + */ + inline Sequence( const E * pElements, sal_Int32 len ); + + /** Constructor: Creates a default constructed sequence of given length. + + @param len initial sequence length + */ + inline explicit Sequence( sal_Int32 len ); + +#if defined LIBO_INTERNAL_ONLY + /** Create a sequence with the given elements. + + @param init an initializer_list + + @since LibreOffice 5.0 + */ + inline Sequence(std::initializer_list<E> init); +#endif + + /** Destructor: Releases sequence handle. Last handle will destruct + elements and free memory. + */ + inline ~Sequence(); + + /** Assignment operator: Acquires given sequence handle and releases + previously set handle. + + @param rSeq another sequence of same type + @return this sequence + */ + inline Sequence & SAL_CALL operator = ( const Sequence & rSeq ); + + /** Gets length of the sequence. + + @return length of sequence + */ + sal_Int32 SAL_CALL getLength() const + { return _pSequence->nElements; } + + /** Tests whether the sequence has elements, i.e. elements count is + greater than zero. + + @return true, if elements count is greater than zero + */ + bool SAL_CALL hasElements() const + { return (_pSequence->nElements > 0); } + +#if defined LIBO_INTERNAL_ONLY + /** This function allows to use Sequence in cases where std::size is needed, and the like. + + @since LibreOffice 6.4 + */ + sal_uInt32 size() const + { assert(getLength() >= 0); return static_cast<sal_uInt32>(getLength()); } +#endif + + /** Gets a pointer to elements array for reading. + If the sequence has a length of 0, then the returned pointer is + undefined. + + @return pointer to elements array + */ + const E * SAL_CALL getConstArray() const + { return reinterpret_cast< const E * >( _pSequence->elements ); } + + /** Gets a pointer to elements array for reading and writing. + In general if the sequence has a handle acquired by other sequences + (reference count > 1), then a new sequence is created copy constructing + all elements to keep value semantics! + If the sequence has a length of 0, then the returned pointer is + undefined. + + @return pointer to elements array + */ + inline E * SAL_CALL getArray(); + + /** This function allows to use Sequence in standard algorithms, like std::find + and others. + + @since LibreOffice 4.2 + */ + inline E * begin(); + + /** This function allows to use Sequence in standard algorithms, like std::find + and others. + + @since LibreOffice 4.2 + */ + inline E const * begin() const; + + /** This function allows to use Sequence in standard algorithms, like std::find + and others. + + @since LibreOffice 4.2 + */ + inline E * end(); + + /** This function allows to use Sequence in standard algorithms, like std::find + and others. + + @since LibreOffice 4.2 + */ + inline E const * end() const; + + /** Non-const index operator: Obtains a reference to element indexed at + given position. + The implementation does not check for array bounds! + In general if the sequence has a handle acquired by other sequences + (reference count > 1), then a new sequence is created copy constructing + all elements to keep value semantics! + + @param nIndex index + @return non-const C++ reference to element + */ + inline E & SAL_CALL operator [] ( sal_Int32 nIndex ); + + /** Const index operator: Obtains a reference to element indexed at + given position. The implementation does not check for array bounds! + + @param nIndex index + @return const C++ reference to element + */ + inline const E & SAL_CALL operator [] ( sal_Int32 nIndex ) const; + + /** Equality operator: Compares two sequences. + + @param rSeq another sequence of same type (right side) + @return true if both sequences are equal, false otherwise + */ + inline bool SAL_CALL operator == ( const Sequence & rSeq ) const; + + /** Inequality operator: Compares two sequences. + + @param rSeq another sequence of same type (right side) + @return false if both sequences are equal, true otherwise + */ + inline bool SAL_CALL operator != ( const Sequence & rSeq ) const; + + /** Reallocates sequence to new length. + If the new length is smaller than the former, then upper elements will + be destructed (and their memory freed). If the new length is greater + than the former, then upper (new) elements are default constructed. + If the sequence has a handle acquired by other sequences + (reference count > 1), then the remaining elements are copy constructed + to a new sequence handle to keep value semantics! + + @param nSize new size of sequence + */ + inline void SAL_CALL realloc( sal_Int32 nSize ); + + /** Provides UNacquired sequence handle. + + @return UNacquired sequence handle + */ + uno_Sequence * SAL_CALL get() const + { return _pSequence; } +}; + +// Find uses of illegal Sequence<bool> (instead of Sequence<sal_Bool>) during +// compilation: +template<> class Sequence<bool> { + Sequence(Sequence<bool> const &) SAL_DELETED_FUNCTION; +}; + +/** Creates a UNO byte sequence from a SAL byte sequence. + + @param rByteSequence a byte sequence + @return a UNO byte sequence +*/ +inline ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL toUnoSequence( + const ::rtl::ByteSequence & rByteSequence ); + +} +} +} +} + +/** Gets the meta type of IDL sequence. + + There are cases (involving templates) where uses of getCppuType are known to + not compile. Use cppu::UnoType or cppu::getTypeFavourUnsigned instead. + + The dummy parameter is just a typed pointer for function signature. + + @tparam E element type of sequence + @return type of IDL sequence + + @deprecated + Use cppu::UnoType instead. +*/ +template< class E > SAL_DEPRECATED("use cppu::UnoType") +inline const ::com::sun::star::uno::Type & +SAL_CALL getCppuType( const ::com::sun::star::uno::Sequence< E > * ); + +/** Gets the meta type of IDL sequence. + This function has been introduced, because one cannot get the (templated) + cppu type out of C++ array types. + + @attention + the given element type must be the same as the template argument type! + @tparam E element type of sequence + @param rElementType element type of sequence + @return type of IDL sequence + + @deprecated + Use cppu::UnoType instead. +*/ +template< class E > SAL_DEPRECATED("use cppu::UnoType") +inline const ::com::sun::star::uno::Type & +SAL_CALL getCppuSequenceType( const ::com::sun::star::uno::Type & rElementType ); + +/** Gets the meta type of IDL sequence< char >. + This function has been introduced due to ambiguities with unsigned short. + + The dummy parameter is just a typed pointer for function signature. + + @return type of IDL sequence< char > + + @deprecated + Use cppu::UnoType instead. +*/ +SAL_DEPRECATED("use cppu::UnoType") +inline const ::com::sun::star::uno::Type & +SAL_CALL getCharSequenceCppuType(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/com/sun/star/uno/Sequence.hxx b/include/com/sun/star/uno/Sequence.hxx new file mode 100644 index 000000000..373d97624 --- /dev/null +++ b/include/com/sun/star/uno/Sequence.hxx @@ -0,0 +1,371 @@ +/* -*- 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_COM_SUN_STAR_UNO_SEQUENCE_HXX +#define INCLUDED_COM_SUN_STAR_UNO_SEQUENCE_HXX + +#include "sal/config.h" + +#include <cassert> +#include <cstddef> +#if defined LIBO_INTERNAL_ONLY +# include <type_traits> +# include <ostream> +#endif + +#include "osl/interlck.h" +#include "com/sun/star/uno/Sequence.h" +#include "typelib/typedescription.h" +#include "uno/data.h" +#include "com/sun/star/uno/genfunc.hxx" +#include "cppu/unotype.hxx" + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace uno +{ + +/// @cond INTERNAL +template< class E > +typelib_TypeDescriptionReference * Sequence< E >::s_pType = NULL; +/// @endcond + +template< class E > +inline Sequence< E >::Sequence() +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + ::uno_type_sequence_construct( + &_pSequence, rType.getTypeLibType(), + NULL, 0, cpp_acquire ); + // no bad_alloc, because empty sequence is statically allocated in cppu +} + +template< class E > +inline Sequence< E >::Sequence( const Sequence & rSeq ) +{ + osl_atomic_increment( &rSeq._pSequence->nRefCount ); + _pSequence = rSeq._pSequence; +} + +template< class E > +inline Sequence< E >::Sequence( + uno_Sequence * pSequence, __sal_NoAcquire ) + : _pSequence( pSequence ) +{ +} + +#if defined(__COVERITY__) +extern "C" void __coverity_tainted_data_sanitize__(void *); +#endif + +template< class E > +inline Sequence< E >::Sequence( const E * pElements, sal_Int32 len ) +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + +#if defined(__COVERITY__) + // cid#1448292 coverity has difficulty with css::uno::Sequence + __coverity_tainted_data_sanitize__(pElements); +#endif + + bool success = + ::uno_type_sequence_construct( + &_pSequence, rType.getTypeLibType(), + const_cast< E * >( pElements ), len, cpp_acquire ); + if (! success) + throw ::std::bad_alloc(); +} + +template< class E > +inline Sequence< E >::Sequence( sal_Int32 len ) +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + bool success = + ::uno_type_sequence_construct( + &_pSequence, rType.getTypeLibType(), + NULL, len, cpp_acquire ); + if (! success) + throw ::std::bad_alloc(); +} + +#if defined LIBO_INTERNAL_ONLY +template<typename E> Sequence<E>::Sequence(std::initializer_list<E> init) { + if (!uno_type_sequence_construct( + &_pSequence, cppu::getTypeFavourUnsigned(this).getTypeLibType(), + const_cast<E *>(init.begin()), init.size(), cpp_acquire)) + { + throw std::bad_alloc(); + } +} +#endif + +template< class E > +inline Sequence< E >::~Sequence() +{ + if (osl_atomic_decrement( &_pSequence->nRefCount ) == 0) + { + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + uno_type_sequence_destroy( + _pSequence, rType.getTypeLibType(), cpp_release ); + } +} + +template< class E > +inline Sequence< E > & Sequence< E >::operator = ( const Sequence & rSeq ) +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + ::uno_type_sequence_assign( + &_pSequence, rSeq._pSequence, rType.getTypeLibType(), cpp_release ); + return *this; +} + +template< class E > +inline bool Sequence< E >::operator == ( const Sequence & rSeq ) const +{ + if (_pSequence == rSeq._pSequence) + return true; + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + return ::uno_type_equalData( + const_cast< Sequence * >( this ), rType.getTypeLibType(), + const_cast< Sequence * >( &rSeq ), rType.getTypeLibType(), + cpp_queryInterface, + cpp_release ); +} + +template< class E > +inline bool Sequence< E >::operator != ( const Sequence & rSeq ) const +{ + return (! operator == ( rSeq )); +} + +template< class E > +inline E * Sequence< E >::getArray() +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + bool success = + ::uno_type_sequence_reference2One( + &_pSequence, rType.getTypeLibType(), + cpp_acquire, cpp_release ); + if (! success) + throw ::std::bad_alloc(); + return reinterpret_cast< E * >( _pSequence->elements ); +} + +template<class E> E * Sequence<E>::begin() { return getArray(); } + +template<class E> E const * Sequence<E>::begin() const +{ return getConstArray(); } + +template<class E> E * Sequence<E>::end() { return begin() + getLength(); } + +template<class E> E const * Sequence<E>::end() const +{ return begin() + getLength(); } + +template< class E > +inline E & Sequence< E >::operator [] ( sal_Int32 nIndex ) +{ + // silence spurious -Werror=strict-overflow warnings from GCC 4.8.2 + assert(nIndex >= 0 && static_cast<sal_uInt32>(nIndex) < static_cast<sal_uInt32>(getLength())); + return getArray()[ nIndex ]; +} + +template< class E > +inline const E & Sequence< E >::operator [] ( sal_Int32 nIndex ) const +{ + // silence spurious -Werror=strict-overflow warnings from GCC 4.8.2 + assert(nIndex >= 0 && static_cast<sal_uInt32>(nIndex) < static_cast<sal_uInt32>(getLength())); + return reinterpret_cast< const E * >( _pSequence->elements )[ nIndex ]; +} + +template< class E > +inline void Sequence< E >::realloc( sal_Int32 nSize ) +{ + const Type & rType = ::cppu::getTypeFavourUnsigned( this ); + bool success = + ::uno_type_sequence_realloc( + &_pSequence, rType.getTypeLibType(), nSize, + cpp_acquire, cpp_release ); + if (!success) + throw ::std::bad_alloc(); +} + +inline ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL toUnoSequence( + const ::rtl::ByteSequence & rByteSequence ) +{ + return * reinterpret_cast< const ::com::sun::star::uno::Sequence< sal_Int8 > * >( &rByteSequence ); +} + +#if defined LIBO_INTERNAL_ONLY + +/// @cond INTERNAL + +namespace uno_detail { + +template< typename value_t, typename charT, typename traits > +void sequence_output_elems( std::basic_ostream<charT, traits> &os, const value_t *pAry, sal_Int32 nLen, std::true_type ) +{ + // for integral types, use hex notation + auto const flags = os.setf(std::ios_base::hex); + for(sal_Int32 i=0; i<nLen-1; ++i) + os << "0x" << *pAry++ << ", "; + if( nLen > 1 ) + os << "0x" << *pAry++; + os.setf(flags); +} + +template< typename value_t, typename charT, typename traits > +void sequence_output_elems( std::basic_ostream<charT, traits> &os, const value_t *pAry, sal_Int32 nLen, std::false_type ) +{ + // every other type: rely on their own ostream operator<< + for(sal_Int32 i=0; i<nLen-1; ++i) + os << *pAry++ << ", "; + if( nLen > 1 ) + os << *pAry++; +} + +template< typename value_t, typename charT, typename traits > +void sequence_output_bytes( std::basic_ostream<charT, traits> &os, const value_t *pAry, sal_Int32 nLen ) +{ + // special case bytes - ostream operator<< outputs those as char + // values, but we need raw ints here + auto const flags = os.setf(std::ios_base::hex); + for(sal_Int32 i=0; i<nLen-1; ++i) + os << "0x" << (0xFF & +*pAry++) << ", "; + if( nLen > 1 ) + os << "0x" << (0xFF & +*pAry++); + os.setf(flags); +} + +} + +/** + Support for Sequence in std::ostream (and thus in CPPUNIT_ASSERT or SAL_INFO + macros, for example). + + @since LibreOffice 6.1 +*/ +template< typename value_t, typename charT, typename traits > +inline std::basic_ostream<charT, traits> &operator<<(std::basic_ostream<charT, traits> &os, css::uno::Sequence<value_t> const& v) +{ + const value_t *pAry = v.getConstArray(); + sal_Int32 nLen = v.getLength(); + if constexpr (std::is_same<sal_Int8, value_t>::value) { + uno_detail::sequence_output_bytes(os, pAry, nLen); + } else { + uno_detail::sequence_output_elems(os, pAry, nLen, std::is_integral<value_t>()); + } + return os; +} + +/// @endcond + +#endif + +} +} +} +} + +namespace cppu { + +template< typename T > inline ::com::sun::star::uno::Type const & +getTypeFavourUnsigned( + SAL_UNUSED_PARAMETER ::com::sun::star::uno::Sequence< T > const *) +{ + if (::com::sun::star::uno::Sequence< T >::s_pType == 0) { + ::typelib_static_sequence_type_init( + &::com::sun::star::uno::Sequence< T >::s_pType, + (::cppu::getTypeFavourUnsigned( + static_cast< + typename ::com::sun::star::uno::Sequence< T >::ElementType * >( + 0)). + getTypeLibType())); + } + return detail::getTypeFromTypeDescriptionReference( + &::com::sun::star::uno::Sequence< T >::s_pType); +} + +template< typename T > inline ::com::sun::star::uno::Type const & +getTypeFavourChar( + SAL_UNUSED_PARAMETER ::com::sun::star::uno::Sequence< T > const *) +{ + //TODO On certain platforms with weak memory models, the following code can + // result in some threads observing that td points to garbage: + static typelib_TypeDescriptionReference * td = NULL; + if (td == NULL) { + ::typelib_static_sequence_type_init( + &td, + (::cppu::getTypeFavourChar( + static_cast< + typename ::com::sun::star::uno::Sequence< T >::ElementType * >( + 0)). + getTypeLibType())); + } + return detail::getTypeFromTypeDescriptionReference(&td); +} + +} + +// generic sequence template +template< class E > +inline const ::com::sun::star::uno::Type & +SAL_CALL getCppuType( + SAL_UNUSED_PARAMETER const ::com::sun::star::uno::Sequence< E > * ) +{ + return ::cppu::getTypeFavourUnsigned( + static_cast< ::com::sun::star::uno::Sequence< E > * >(0)); +} + +// generic sequence template for given element type (e.g. C++ arrays) +template< class E > +inline const ::com::sun::star::uno::Type & +SAL_CALL getCppuSequenceType( const ::com::sun::star::uno::Type & rElementType ) +{ + if (! ::com::sun::star::uno::Sequence< E >::s_pType) + { + ::typelib_static_sequence_type_init( + & ::com::sun::star::uno::Sequence< E >::s_pType, + rElementType.getTypeLibType() ); + } + return * reinterpret_cast< const ::com::sun::star::uno::Type * >( + & ::com::sun::star::uno::Sequence< E >::s_pType ); +} + +// char sequence +inline const ::com::sun::star::uno::Type & +SAL_CALL getCharSequenceCppuType() +{ + static typelib_TypeDescriptionReference * s_pType_com_sun_star_uno_Sequence_Char = NULL; + if (! s_pType_com_sun_star_uno_Sequence_Char) + { + const ::com::sun::star::uno::Type & rElementType = cppu::UnoType<cppu::UnoCharType>::get(); + ::typelib_static_sequence_type_init( + & s_pType_com_sun_star_uno_Sequence_Char, + rElementType.getTypeLibType() ); + } + return * reinterpret_cast< const ::com::sun::star::uno::Type * >( + & s_pType_com_sun_star_uno_Sequence_Char ); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |