summaryrefslogtreecommitdiffstats
path: root/include/comphelper/sequence.hxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/comphelper/sequence.hxx322
1 files changed, 322 insertions, 0 deletions
diff --git a/include/comphelper/sequence.hxx b/include/comphelper/sequence.hxx
new file mode 100644
index 000000000..bc67559df
--- /dev/null
+++ b/include/comphelper/sequence.hxx
@@ -0,0 +1,322 @@
+/* -*- 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.getArray());
+ (..., (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
+ auto pRet = ret.getArray();
+ std::copy_n(left.getConstArray(), n1, pRet);
+ 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) {
+ pRet[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 )
+ {
+ if constexpr (std::is_same_v< DstType, SrcType >)
+ {
+ return css::uno::Sequence< DstType >( i_pArray, nNum );
+ }
+ else
+ {
+ 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 )
+ {
+ using ::std::size, ::std::begin, ::std::end;
+ css::uno::Sequence< DstElementType > result( size(i_Container) );
+ ::std::copy( begin(i_Container), end(i_Container), 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 )
+ {
+ return containerToSequence<typename SrcType::value_type, SrcType>(i_Container);
+ }
+
+ // 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()) );
+ std::transform(map.begin(), map.end(), ret.getArray(),
+ [](const auto& i) { return 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()) );
+ std::transform(map.begin(), map.end(), ret.getArray(),
+ [](const auto& i) { return i.second; });
+ return ret;
+ }
+
+} // namespace comphelper
+
+
+#endif // INCLUDED_COMPHELPER_SEQUENCE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */