1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 #ifndef INCLUDED_COMPHELPER_SEQUENCE_HXX 21 #define INCLUDED_COMPHELPER_SEQUENCE_HXX 22 23 #include <com/sun/star/uno/Sequence.hxx> 24 #include <osl/diagnose.h> 25 26 #include <algorithm> 27 #include <vector> 28 29 namespace comphelper 30 { 31 /** Search the given value within the given sequence, return the position of the first occurrence. 32 Returns -1 if nothing found. 33 */ 34 template <class T1, class T2> findValue(const css::uno::Sequence<T1> & _rList,const T2 & _rValue)35 inline sal_Int32 findValue(const css::uno::Sequence<T1>& _rList, const T2& _rValue) 36 { 37 // at which position do I find the value? 38 for (sal_Int32 i = 0; i < _rList.getLength(); ++i) 39 { 40 if (_rList[i] == _rValue) 41 return i; 42 } 43 44 return -1; 45 } 46 47 /// concat several sequences 48 template <class T, class... Ss> concatSequences(const css::uno::Sequence<T> & rS1,const Ss &...rSn)49 inline css::uno::Sequence<T> concatSequences(const css::uno::Sequence<T>& rS1, const Ss&... rSn) 50 { 51 // unary fold to disallow empty parameter pack: at least have one sequence in rSn 52 css::uno::Sequence<T> aReturn(std::size(rS1) + (... + std::size(rSn))); 53 T* pReturn = std::copy(std::begin(rS1), std::end(rS1), aReturn.begin()); 54 (..., (pReturn = std::copy(std::begin(rSn), std::end(rSn), pReturn))); 55 return aReturn; 56 } 57 58 /// concat additional elements from right sequence to left sequence 59 /// 60 /// be aware that this takes time O(|left| * |right|) combineSequences(css::uno::Sequence<T> const & left,css::uno::Sequence<T> const & right)61 template<typename T> inline css::uno::Sequence<T> combineSequences( 62 css::uno::Sequence<T> const & left, css::uno::Sequence<T> const & right) 63 { 64 sal_Int32 n1 = left.getLength(); 65 css::uno::Sequence<T> ret(n1 + right.getLength()); 66 //TODO: check for overflow 67 std::copy_n(left.getConstArray(), n1, ret.getArray()); 68 sal_Int32 n2 = n1; 69 for (sal_Int32 i = 0; i != right.getLength(); ++i) { 70 bool found = false; 71 for (sal_Int32 j = 0; j != n1; ++j) { 72 if (right[i] == left[j]) { 73 found = true; 74 break; 75 } 76 } 77 if (!found) { 78 ret[n2++] = right[i]; 79 } 80 } 81 ret.realloc(n2); 82 return ret; 83 } 84 85 /// remove a specified element from a sequences 86 template<class T> removeElementAt(css::uno::Sequence<T> & _rSeq,sal_Int32 _nPos)87 inline void removeElementAt(css::uno::Sequence<T>& _rSeq, sal_Int32 _nPos) 88 { 89 sal_Int32 nLength = _rSeq.getLength(); 90 91 OSL_ENSURE(0 <= _nPos && _nPos < nLength, "invalid index"); 92 93 T* pPos = _rSeq.getArray() + _nPos; 94 std::move(pPos + 1, pPos + nLength - _nPos, pPos); 95 96 _rSeq.realloc(nLength-1); 97 } 98 99 /** Copy from a plain C/C++ array into a Sequence. 100 101 @tpl SrcType 102 Array element type. Must be assignable to DstType 103 104 @tpl DstType 105 Sequence element type. Must be assignable from SrcType 106 107 @param i_pArray 108 Valid pointer to at least num elements of type SrcType 109 110 @param nNum 111 Number of array elements to copy 112 113 @return the resulting Sequence 114 115 @attention when copying from e.g. a double array to a 116 Sequence<int>, no proper rounding will be performed, but the 117 values will be truncated. There's currently no measure to 118 prevent or detect precision loss, overflow or truncation. 119 */ 120 template < typename DstType, typename SrcType > arrayToSequence(const SrcType * i_pArray,sal_Int32 nNum)121 inline css::uno::Sequence< DstType > arrayToSequence( const SrcType* i_pArray, sal_Int32 nNum ) 122 { 123 css::uno::Sequence< DstType > result( nNum ); 124 ::std::copy( i_pArray, i_pArray+nNum, result.getArray() ); 125 return result; 126 } 127 128 129 /** Copy from a Sequence into a plain C/C++ array 130 131 @tpl SrcType 132 Sequence element type. Must be assignable to DstType 133 134 @tpl DstType 135 Array element type. Must be assignable from SrcType 136 137 @param io_pArray 138 Valid pointer to at least i_Sequence.getLength() elements of 139 type DstType 140 141 @param i_Sequence 142 Reference to a Sequence of SrcType elements 143 144 @return a pointer to the array 145 146 @attention when copying from e.g. a Sequence<double> to an int 147 array, no proper rounding will be performed, but the values 148 will be truncated. There's currently no measure to prevent or 149 detect precision loss, overflow or truncation. 150 */ 151 template < typename DstType, typename SrcType > sequenceToArray(DstType * io_pArray,const css::uno::Sequence<SrcType> & i_Sequence)152 inline DstType* sequenceToArray( DstType* io_pArray, const css::uno::Sequence< SrcType >& i_Sequence ) 153 { 154 ::std::copy( i_Sequence.begin(), i_Sequence.end(), io_pArray ); 155 return io_pArray; 156 } 157 158 159 /** Copy from a container into a Sequence 160 161 @tpl SrcType 162 Container type. This type must fulfill the STL container 163 concept, in particular, the size(), begin() and end() methods 164 must be available and have the usual semantics. 165 166 @tpl DstType 167 Sequence element type. Must be assignable from SrcType's 168 elements 169 170 @param i_Container 171 Reference to the input contain with elements of type SrcType 172 173 @return the generated Sequence 174 175 @attention this function always performs a copy. Furthermore, 176 when copying from e.g. a vector<double> to a Sequence<int>, no 177 proper rounding will be performed, but the values will be 178 truncated. There's currently no measure to prevent or detect 179 precision loss, overflow or truncation. 180 */ 181 template < typename DstElementType, typename SrcType > containerToSequence(const SrcType & i_Container)182 inline css::uno::Sequence< DstElementType > containerToSequence( const SrcType& i_Container ) 183 { 184 css::uno::Sequence< DstElementType > result( i_Container.size() ); 185 ::std::copy( i_Container.begin(), i_Container.end(), result.getArray() ); 186 return result; 187 } 188 189 // this one does better type deduction, but does not allow us to copy into a different element type 190 template < typename SrcType > containerToSequence(const SrcType & i_Container)191 inline css::uno::Sequence< typename SrcType::value_type > containerToSequence( const SrcType& i_Container ) 192 { 193 css::uno::Sequence< typename SrcType::value_type > result( i_Container.size() ); 194 ::std::copy( i_Container.begin(), i_Container.end(), result.getArray() ); 195 return result; 196 } 197 198 // handle arrays 199 template<typename ElementType, std::size_t SrcSize> containerToSequence(ElementType const (& i_Array)[SrcSize])200 inline css::uno::Sequence< ElementType > containerToSequence( ElementType const (&i_Array)[ SrcSize ] ) 201 { 202 return css::uno::Sequence< ElementType >( i_Array, SrcSize ); 203 } 204 205 template <typename T> containerToSequence(::std::vector<T> const & v)206 inline css::uno::Sequence<T> containerToSequence( 207 ::std::vector<T> const& v ) 208 { 209 return css::uno::Sequence<T>( 210 v.data(), static_cast<sal_Int32>(v.size()) ); 211 } 212 213 214 /** Copy from a Sequence into a container 215 216 @tpl SrcType 217 Sequence element type. Must be assignable to SrcType's 218 elements 219 220 @tpl DstType 221 Container type. This type must have a constructor taking a pair 222 of iterators defining a range to copy from 223 224 @param i_Sequence 225 Reference to a Sequence of SrcType elements 226 227 @return the generated container. C++17 copy elision rules apply 228 229 @attention this function always performs a copy. Furthermore, 230 when copying from e.g. a Sequence<double> to a vector<int>, no 231 proper rounding will be performed, but the values will be 232 truncated. There's currently no measure to prevent or detect 233 precision loss, overflow or truncation. 234 */ 235 template < typename DstType, typename SrcType > sequenceToContainer(const css::uno::Sequence<SrcType> & i_Sequence)236 inline DstType sequenceToContainer( const css::uno::Sequence< SrcType >& i_Sequence ) 237 { 238 return DstType(i_Sequence.begin(), i_Sequence.end()); 239 } 240 241 // this one does better type deduction, but does not allow us to copy into a different element type 242 template < typename DstType > sequenceToContainer(const css::uno::Sequence<typename DstType::value_type> & i_Sequence)243 inline DstType sequenceToContainer( const css::uno::Sequence< typename DstType::value_type >& i_Sequence ) 244 { 245 return DstType(i_Sequence.begin(), i_Sequence.end()); 246 } 247 248 /** Copy from a Sequence into an existing container 249 250 This potentially saves a needless extra copy operation over 251 the whole container, as it passes the target object by 252 reference. 253 254 @tpl SrcType 255 Sequence element type. Must be assignable to SrcType's 256 elements 257 258 @tpl DstType 259 Container type. This type must fulfill the STL container and 260 sequence concepts, in particular, the begin(), end() and 261 resize(int) methods must be available and have the usual 262 semantics. 263 264 @param o_Output 265 Reference to the target container 266 267 @param i_Sequence 268 Reference to a Sequence of SrcType elements 269 270 @return a non-const reference to the given container 271 272 @attention this function always performs a copy. Furthermore, 273 when copying from e.g. a Sequence<double> to a vector<int>, no 274 proper rounding will be performed, but the values will be 275 truncated. There's currently no measure to prevent or detect 276 precision loss, overflow or truncation. 277 */ 278 template < typename DstType, typename SrcType > sequenceToContainer(DstType & o_Output,const css::uno::Sequence<SrcType> & i_Sequence)279 inline DstType& sequenceToContainer( DstType& o_Output, const css::uno::Sequence< SrcType >& i_Sequence ) 280 { 281 o_Output.resize( i_Sequence.getLength() ); 282 ::std::copy( i_Sequence.begin(), i_Sequence.end(), o_Output.begin() ); 283 return o_Output; 284 } 285 286 /** Copy (keys or values) from an associate container into a Sequence 287 288 @tpl M map container type eg. std::map/std::unordered_map 289 290 @return the generated Sequence 291 */ 292 template < typename M > mapKeysToSequence(M const & map)293 inline css::uno::Sequence< typename M::key_type > mapKeysToSequence( M const& map ) 294 { 295 css::uno::Sequence< typename M::key_type > ret( static_cast<sal_Int32>(map.size()) ); 296 typename M::key_type* pArray = ret.getArray(); 297 for (const auto& i : map) 298 *pArray++ = i.first; 299 return ret; 300 } 301 302 template < typename M > mapValuesToSequence(M const & map)303 inline css::uno::Sequence< typename M::mapped_type > mapValuesToSequence( M const& map ) 304 { 305 css::uno::Sequence< typename M::mapped_type > ret( static_cast<sal_Int32>(map.size()) ); 306 typename M::mapped_type* pArray = ret.getArray(); 307 for (const auto& i : map) 308 *pArray++ = i.second; 309 return ret; 310 } 311 312 } // namespace comphelper 313 314 315 #endif // INCLUDED_COMPHELPER_SEQUENCE_HXX 316 317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 318