office-gobmx/include/comphelper/sequence.hxx
Mike Kaganski 8fc9c698ee Generalize comphelper::concatSequences to accept other container types
... as second and following arguments.

Change-Id: I1c994ec234354805bc702632878fd67a54d271d6
Reviewed-on: https://gerrit.libreoffice.org/78092
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
2019-08-26 07:25:18 +02:00

317 lines
11 KiB
C++

/* -*- 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_COMPHELPER_SEQUENCE_HXX
#define INCLUDED_COMPHELPER_SEQUENCE_HXX
#include <com/sun/star/uno/Sequence.hxx>
#include <osl/diagnose.h>
#include <algorithm>
#include <vector>
namespace comphelper
{
/** Search the given value within the given sequence, return the position of the first occurrence.
Returns -1 if nothing found.
*/
template <class T1, class T2>
inline sal_Int32 findValue(const css::uno::Sequence<T1>& _rList, const T2& _rValue)
{
// at which position do I find the value?
for (sal_Int32 i = 0; i < _rList.getLength(); ++i)
{
if (_rList[i] == _rValue)
return i;
}
return -1;
}
/// concat several sequences
template <class T, class... Ss>
inline css::uno::Sequence<T> concatSequences(const css::uno::Sequence<T>& rS1, const Ss&... rSn)
{
// unary fold to disallow empty parameter pack: at least have one sequence in rSn
css::uno::Sequence<T> aReturn(std::size(rS1) + (... + std::size(rSn)));
T* pReturn = std::copy(std::begin(rS1), std::end(rS1), aReturn.begin());
(..., (pReturn = std::copy(std::begin(rSn), std::end(rSn), pReturn)));
return aReturn;
}
/// concat additional elements from right sequence to left sequence
///
/// be aware that this takes time O(|left| * |right|)
template<typename T> inline css::uno::Sequence<T> combineSequences(
css::uno::Sequence<T> const & left, css::uno::Sequence<T> const & right)
{
sal_Int32 n1 = left.getLength();
css::uno::Sequence<T> ret(n1 + right.getLength());
//TODO: check for overflow
std::copy_n(left.getConstArray(), n1, ret.getArray());
sal_Int32 n2 = n1;
for (sal_Int32 i = 0; i != right.getLength(); ++i) {
bool found = false;
for (sal_Int32 j = 0; j != n1; ++j) {
if (right[i] == left[j]) {
found = true;
break;
}
}
if (!found) {
ret[n2++] = right[i];
}
}
ret.realloc(n2);
return ret;
}
/// remove a specified element from a sequences
template<class T>
inline void removeElementAt(css::uno::Sequence<T>& _rSeq, sal_Int32 _nPos)
{
sal_Int32 nLength = _rSeq.getLength();
OSL_ENSURE(0 <= _nPos && _nPos < nLength, "invalid index");
T* pPos = _rSeq.getArray() + _nPos;
std::move(pPos + 1, pPos + nLength - _nPos, pPos);
_rSeq.realloc(nLength-1);
}
/** Copy from a plain C/C++ array into a Sequence.
@tpl SrcType
Array element type. Must be assignable to DstType
@tpl DstType
Sequence element type. Must be assignable from SrcType
@param i_pArray
Valid pointer to at least num elements of type SrcType
@param nNum
Number of array elements to copy
@return the resulting Sequence
@attention when copying from e.g. a double array to a
Sequence<int>, no proper rounding will be performed, but the
values will be truncated. There's currently no measure to
prevent or detect precision loss, overflow or truncation.
*/
template < typename DstType, typename SrcType >
inline css::uno::Sequence< DstType > arrayToSequence( const SrcType* i_pArray, sal_Int32 nNum )
{
css::uno::Sequence< DstType > result( nNum );
::std::copy( i_pArray, i_pArray+nNum, result.getArray() );
return result;
}
/** Copy from a Sequence into a plain C/C++ array
@tpl SrcType
Sequence element type. Must be assignable to DstType
@tpl DstType
Array element type. Must be assignable from SrcType
@param io_pArray
Valid pointer to at least i_Sequence.getLength() elements of
type DstType
@param i_Sequence
Reference to a Sequence of SrcType elements
@return a pointer to the array
@attention when copying from e.g. a Sequence<double> to an int
array, no proper rounding will be performed, but the values
will be truncated. There's currently no measure to prevent or
detect precision loss, overflow or truncation.
*/
template < typename DstType, typename SrcType >
inline DstType* sequenceToArray( DstType* io_pArray, const css::uno::Sequence< SrcType >& i_Sequence )
{
::std::copy( i_Sequence.begin(), i_Sequence.end(), io_pArray );
return io_pArray;
}
/** Copy from a container into a Sequence
@tpl SrcType
Container type. This type must fulfill the STL container
concept, in particular, the size(), begin() and end() methods
must be available and have the usual semantics.
@tpl DstType
Sequence element type. Must be assignable from SrcType's
elements
@param i_Container
Reference to the input contain with elements of type SrcType
@return the generated Sequence
@attention this function always performs a copy. Furthermore,
when copying from e.g. a vector<double> to a Sequence<int>, no
proper rounding will be performed, but the values will be
truncated. There's currently no measure to prevent or detect
precision loss, overflow or truncation.
*/
template < typename DstElementType, typename SrcType >
inline css::uno::Sequence< DstElementType > containerToSequence( const SrcType& i_Container )
{
css::uno::Sequence< DstElementType > result( i_Container.size() );
::std::copy( i_Container.begin(), i_Container.end(), result.getArray() );
return result;
}
// this one does better type deduction, but does not allow us to copy into a different element type
template < typename SrcType >
inline css::uno::Sequence< typename SrcType::value_type > containerToSequence( const SrcType& i_Container )
{
css::uno::Sequence< typename SrcType::value_type > result( i_Container.size() );
::std::copy( i_Container.begin(), i_Container.end(), result.getArray() );
return result;
}
// handle arrays
template<typename ElementType, std::size_t SrcSize>
inline css::uno::Sequence< ElementType > containerToSequence( ElementType const (&i_Array)[ SrcSize ] )
{
return css::uno::Sequence< ElementType >( i_Array, SrcSize );
}
template <typename T>
inline css::uno::Sequence<T> containerToSequence(
::std::vector<T> const& v )
{
return css::uno::Sequence<T>(
v.data(), static_cast<sal_Int32>(v.size()) );
}
/** Copy from a Sequence into a container
@tpl SrcType
Sequence element type. Must be assignable to SrcType's
elements
@tpl DstType
Container type. This type must have a constructor taking a pair
of iterators defining a range to copy from
@param i_Sequence
Reference to a Sequence of SrcType elements
@return the generated container. C++17 copy elision rules apply
@attention this function always performs a copy. Furthermore,
when copying from e.g. a Sequence<double> to a vector<int>, no
proper rounding will be performed, but the values will be
truncated. There's currently no measure to prevent or detect
precision loss, overflow or truncation.
*/
template < typename DstType, typename SrcType >
inline DstType sequenceToContainer( const css::uno::Sequence< SrcType >& i_Sequence )
{
return DstType(i_Sequence.begin(), i_Sequence.end());
}
// this one does better type deduction, but does not allow us to copy into a different element type
template < typename DstType >
inline DstType sequenceToContainer( const css::uno::Sequence< typename DstType::value_type >& i_Sequence )
{
return DstType(i_Sequence.begin(), i_Sequence.end());
}
/** Copy from a Sequence into an existing container
This potentially saves a needless extra copy operation over
the whole container, as it passes the target object by
reference.
@tpl SrcType
Sequence element type. Must be assignable to SrcType's
elements
@tpl DstType
Container type. This type must fulfill the STL container and
sequence concepts, in particular, the begin(), end() and
resize(int) methods must be available and have the usual
semantics.
@param o_Output
Reference to the target container
@param i_Sequence
Reference to a Sequence of SrcType elements
@return a non-const reference to the given container
@attention this function always performs a copy. Furthermore,
when copying from e.g. a Sequence<double> to a vector<int>, no
proper rounding will be performed, but the values will be
truncated. There's currently no measure to prevent or detect
precision loss, overflow or truncation.
*/
template < typename DstType, typename SrcType >
inline DstType& sequenceToContainer( DstType& o_Output, const css::uno::Sequence< SrcType >& i_Sequence )
{
o_Output.resize( i_Sequence.getLength() );
::std::copy( i_Sequence.begin(), i_Sequence.end(), o_Output.begin() );
return o_Output;
}
/** Copy (keys or values) from an associate container into a Sequence
@tpl M map container type eg. std::map/std::unordered_map
@return the generated Sequence
*/
template < typename M >
inline css::uno::Sequence< typename M::key_type > mapKeysToSequence( M const& map )
{
css::uno::Sequence< typename M::key_type > ret( static_cast<sal_Int32>(map.size()) );
typename M::key_type* pArray = ret.getArray();
for (const auto& i : map)
*pArray++ = i.first;
return ret;
}
template < typename M >
inline css::uno::Sequence< typename M::mapped_type > mapValuesToSequence( M const& map )
{
css::uno::Sequence< typename M::mapped_type > ret( static_cast<sal_Int32>(map.size()) );
typename M::mapped_type* pArray = ret.getArray();
for (const auto& i : map)
*pArray++ = i.second;
return ret;
}
} // namespace comphelper
#endif // INCLUDED_COMPHELPER_SEQUENCE_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */