1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #ifndef INCLUDED_COM_SUN_STAR_UNO_SEQUENCE_HXX
20 #define INCLUDED_COM_SUN_STAR_UNO_SEQUENCE_HXX
22 #include "sal/config.h"
26 #if defined LIBO_INTERNAL_ONLY
27 # include <type_traits>
31 #include "osl/interlck.h"
32 #include "com/sun/star/uno/Sequence.h"
33 #include "typelib/typedescription.h"
35 #include "com/sun/star/uno/genfunc.hxx"
36 #include "cppu/unotype.hxx"
49 typelib_TypeDescriptionReference
* Sequence
< E
>::s_pType
= NULL
;
53 inline Sequence
< E
>::Sequence()
55 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
56 ::uno_type_sequence_construct(
57 &_pSequence
, rType
.getTypeLibType(),
59 // no bad_alloc, because empty sequence is statically allocated in cppu
63 inline Sequence
< E
>::Sequence( const Sequence
& rSeq
)
65 osl_atomic_increment( &rSeq
._pSequence
->nRefCount
);
66 _pSequence
= rSeq
._pSequence
;
70 inline Sequence
< E
>::Sequence(
71 uno_Sequence
* pSequence
, __sal_NoAcquire
)
72 : _pSequence( pSequence
)
77 inline Sequence
< E
>::Sequence( const E
* pElements
, sal_Int32 len
)
79 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
81 ::uno_type_sequence_construct(
82 &_pSequence
, rType
.getTypeLibType(),
83 const_cast< E
* >( pElements
), len
, cpp_acquire
);
85 throw ::std::bad_alloc();
89 inline Sequence
< E
>::Sequence( sal_Int32 len
)
91 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
93 ::uno_type_sequence_construct(
94 &_pSequence
, rType
.getTypeLibType(),
95 0, len
, cpp_acquire
);
97 throw ::std::bad_alloc();
100 #if defined LIBO_INTERNAL_ONLY
101 template<typename E
> Sequence
<E
>::Sequence(std::initializer_list
<E
> init
) {
102 if (!uno_type_sequence_construct(
103 &_pSequence
, cppu::getTypeFavourUnsigned(this).getTypeLibType(),
104 const_cast<E
*>(init
.begin()), init
.size(), cpp_acquire
))
106 throw std::bad_alloc();
112 inline Sequence
< E
>::~Sequence()
114 if (osl_atomic_decrement( &_pSequence
->nRefCount
) == 0)
116 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
117 uno_type_sequence_destroy(
118 _pSequence
, rType
.getTypeLibType(), cpp_release
);
123 inline Sequence
< E
> & Sequence
< E
>::operator = ( const Sequence
& rSeq
)
125 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
126 ::uno_type_sequence_assign(
127 &_pSequence
, rSeq
._pSequence
, rType
.getTypeLibType(), cpp_release
);
132 inline bool Sequence
< E
>::operator == ( const Sequence
& rSeq
) const
134 if (_pSequence
== rSeq
._pSequence
)
136 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
137 return ::uno_type_equalData(
138 const_cast< Sequence
* >( this ), rType
.getTypeLibType(),
139 const_cast< Sequence
* >( &rSeq
), rType
.getTypeLibType(),
145 inline bool Sequence
< E
>::operator != ( const Sequence
& rSeq
) const
147 return (! operator == ( rSeq
));
151 inline E
* Sequence
< E
>::getArray()
153 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
155 ::uno_type_sequence_reference2One(
156 &_pSequence
, rType
.getTypeLibType(),
157 cpp_acquire
, cpp_release
);
159 throw ::std::bad_alloc();
160 return reinterpret_cast< E
* >( _pSequence
->elements
);
163 template<class E
> E
* Sequence
<E
>::begin() { return getArray(); }
165 template<class E
> E
const * Sequence
<E
>::begin() const
166 { return getConstArray(); }
168 template<class E
> E
* Sequence
<E
>::end() { return begin() + getLength(); }
170 template<class E
> E
const * Sequence
<E
>::end() const
171 { return begin() + getLength(); }
174 inline E
& Sequence
< E
>::operator [] ( sal_Int32 nIndex
)
176 // silence spurious -Werror=strict-overflow warnings from GCC 4.8.2
177 assert(nIndex
>= 0 && static_cast<sal_uInt32
>(nIndex
) < static_cast<sal_uInt32
>(getLength()));
178 return getArray()[ nIndex
];
182 inline const E
& Sequence
< E
>::operator [] ( sal_Int32 nIndex
) const
184 // silence spurious -Werror=strict-overflow warnings from GCC 4.8.2
185 assert(nIndex
>= 0 && static_cast<sal_uInt32
>(nIndex
) < static_cast<sal_uInt32
>(getLength()));
186 return reinterpret_cast< const E
* >( _pSequence
->elements
)[ nIndex
];
190 inline void Sequence
< E
>::realloc( sal_Int32 nSize
)
192 const Type
& rType
= ::cppu::getTypeFavourUnsigned( this );
194 ::uno_type_sequence_realloc(
195 &_pSequence
, rType
.getTypeLibType(), nSize
,
196 cpp_acquire
, cpp_release
);
198 throw ::std::bad_alloc();
201 inline ::com::sun::star::uno::Sequence
< sal_Int8
> SAL_CALL
toUnoSequence(
202 const ::rtl::ByteSequence
& rByteSequence
)
204 return * reinterpret_cast< const ::com::sun::star::uno::Sequence
< sal_Int8
> * >( &rByteSequence
);
207 #if defined LIBO_INTERNAL_ONLY
211 namespace uno_detail
{
213 template< typename value_t
, typename charT
, typename traits
>
214 void sequence_output_elems( std::basic_ostream
<charT
, traits
> &os
, const value_t
*pAry
, sal_Int32 nLen
, std::true_type
)
216 // for integral types, use hex notation
217 auto const flags
= os
.setf(std::ios_base::hex
);
218 for(sal_Int32 i
=0; i
<nLen
-1; ++i
)
219 os
<< "0x" << *pAry
++ << ", ";
221 os
<< "0x" << *pAry
++;
225 template< typename value_t
, typename charT
, typename traits
>
226 void sequence_output_elems( std::basic_ostream
<charT
, traits
> &os
, const value_t
*pAry
, sal_Int32 nLen
, std::false_type
)
228 // every other type: rely on their own ostream operator<<
229 for(sal_Int32 i
=0; i
<nLen
-1; ++i
)
230 os
<< *pAry
++ << ", ";
235 template< typename value_t
, typename charT
, typename traits
>
236 void sequence_output_bytes( std::basic_ostream
<charT
, traits
> &os
, const value_t
*pAry
, sal_Int32 nLen
)
238 // special case bytes - ostream operator<< outputs those as char
239 // values, but we need raw ints here
240 auto const flags
= os
.setf(std::ios_base::hex
);
241 for(sal_Int32 i
=0; i
<nLen
-1; ++i
)
242 os
<< "0x" << (0xFF & +*pAry
++) << ", ";
244 os
<< "0x" << (0xFF & +*pAry
++);
251 Support for Sequence in std::ostream (and thus in CPPUNIT_ASSERT or SAL_INFO
252 macros, for example).
254 @since LibreOffice 6.1
256 template< typename value_t
, typename charT
, typename traits
>
257 inline std::basic_ostream
<charT
, traits
> &operator<<(std::basic_ostream
<charT
, traits
> &os
, css::uno::Sequence
<value_t
> const& v
)
259 const value_t
*pAry
= v
.getConstArray();
260 sal_Int32 nLen
= v
.getLength();
261 if constexpr (std::is_same
<sal_Int8
, value_t
>::value
) {
262 uno_detail::sequence_output_bytes(os
, pAry
, nLen
);
264 uno_detail::sequence_output_elems(os
, pAry
, nLen
, std::is_integral
<value_t
>());
280 template< typename T
> inline ::com::sun::star::uno::Type
const &
281 getTypeFavourUnsigned(
282 SAL_UNUSED_PARAMETER ::com::sun::star::uno::Sequence
< T
> const *)
284 if (::com::sun::star::uno::Sequence
< T
>::s_pType
== 0) {
285 ::typelib_static_sequence_type_init(
286 &::com::sun::star::uno::Sequence
< T
>::s_pType
,
287 (::cppu::getTypeFavourUnsigned(
289 typename ::com::sun::star::uno::Sequence
< T
>::ElementType
* >(
293 return detail::getTypeFromTypeDescriptionReference(
294 &::com::sun::star::uno::Sequence
< T
>::s_pType
);
297 template< typename T
> inline ::com::sun::star::uno::Type
const &
299 SAL_UNUSED_PARAMETER ::com::sun::star::uno::Sequence
< T
> const *)
301 //TODO On certain platforms with weak memory models, the following code can
302 // result in some threads observing that td points to garbage:
303 static typelib_TypeDescriptionReference
* td
= NULL
;
305 ::typelib_static_sequence_type_init(
307 (::cppu::getTypeFavourChar(
309 typename ::com::sun::star::uno::Sequence
< T
>::ElementType
* >(
313 return detail::getTypeFromTypeDescriptionReference(&td
);
318 // generic sequence template
320 inline const ::com::sun::star::uno::Type
&
321 SAL_CALL
getCppuType(
322 SAL_UNUSED_PARAMETER
const ::com::sun::star::uno::Sequence
< E
> * )
324 return ::cppu::getTypeFavourUnsigned(
325 static_cast< ::com::sun::star::uno::Sequence
< E
> * >(0));
328 // generic sequence template for given element type (e.g. C++ arrays)
330 inline const ::com::sun::star::uno::Type
&
331 SAL_CALL
getCppuSequenceType( const ::com::sun::star::uno::Type
& rElementType
)
333 if (! ::com::sun::star::uno::Sequence
< E
>::s_pType
)
335 ::typelib_static_sequence_type_init(
336 & ::com::sun::star::uno::Sequence
< E
>::s_pType
,
337 rElementType
.getTypeLibType() );
339 return * reinterpret_cast< const ::com::sun::star::uno::Type
* >(
340 & ::com::sun::star::uno::Sequence
< E
>::s_pType
);
344 inline const ::com::sun::star::uno::Type
&
345 SAL_CALL
getCharSequenceCppuType()
347 static typelib_TypeDescriptionReference
* s_pType_com_sun_star_uno_Sequence_Char
= NULL
;
348 if (! s_pType_com_sun_star_uno_Sequence_Char
)
350 const ::com::sun::star::uno::Type
& rElementType
= cppu::UnoType
<cppu::UnoCharType
>::get();
351 ::typelib_static_sequence_type_init(
352 & s_pType_com_sun_star_uno_Sequence_Char
,
353 rElementType
.getTypeLibType() );
355 return * reinterpret_cast< const ::com::sun::star::uno::Type
* >(
356 & s_pType_com_sun_star_uno_Sequence_Char
);
361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */