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/.
13 #include <mdds/multi_type_vector/types.hpp>
17 template<typename SizeT
, typename Ret
= bool>
20 Ret
operator() (mdds::mtv::element_t
, SizeT
, SizeT
) const
26 template<typename FuncElem
, typename Elem
>
30 FuncNotElem(FuncElem
& f
) : func(f
) {}
31 bool operator() (size_t s
, Elem elem
) const
33 return !func(s
, elem
);
38 * Generic algorithm to parse blocks of multi_type_vector either partially
41 template<typename StoreT
, typename Func
>
42 typename
StoreT::const_iterator
44 const typename
StoreT::const_iterator
& itPos
, const StoreT
& rStore
, Func
& rFunc
,
45 typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
)
47 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
49 PositionType aPos
= rStore
.position(itPos
, nStart
);
50 typename
StoreT::const_iterator it
= aPos
.first
;
51 typename
StoreT::size_type nOffset
= aPos
.second
;
52 typename
StoreT::size_type nDataSize
= 0;
53 typename
StoreT::size_type nTopRow
= nStart
;
55 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
57 bool bLastBlock
= false;
58 nDataSize
= it
->size
- nOffset
;
59 if (nTopRow
+ nDataSize
- 1 > nEnd
)
61 // Truncate the block.
62 nDataSize
= nEnd
- nTopRow
+ 1;
66 rFunc(*it
, nOffset
, nDataSize
);
76 * Non-const variant of the above function. TODO: Find a way to merge these
77 * two in an elegant way.
79 template<typename StoreT
, typename Func
>
80 typename
StoreT::iterator
81 ProcessBlock(const typename
StoreT::iterator
& itPos
, StoreT
& rStore
, Func
& rFunc
, typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
)
83 typedef std::pair
<typename
StoreT::iterator
, typename
StoreT::size_type
> PositionType
;
85 PositionType aPos
= rStore
.position(itPos
, nStart
);
86 typename
StoreT::iterator it
= aPos
.first
;
87 typename
StoreT::size_type nOffset
= aPos
.second
;
88 typename
StoreT::size_type nDataSize
= 0;
89 typename
StoreT::size_type nCurRow
= nStart
;
91 for (; it
!= rStore
.end() && nCurRow
<= nEnd
; ++it
, nOffset
= 0, nCurRow
+= nDataSize
)
93 bool bLastBlock
= false;
94 nDataSize
= it
->size
- nOffset
;
95 if (nCurRow
+ nDataSize
- 1 > nEnd
)
97 // Truncate the block.
98 nDataSize
= nEnd
- nCurRow
+ 1;
102 rFunc(*it
, nOffset
, nDataSize
);
111 template<typename BlkT
, typename ItrT
, typename NodeT
, typename FuncElem
>
112 void EachElem(NodeT
& rNode
, size_t nOffset
, size_t nDataSize
, FuncElem
& rFuncElem
)
114 ItrT it
= BlkT::begin(*rNode
.data
);
115 std::advance(it
, nOffset
);
117 std::advance(itEnd
, nDataSize
);
118 size_t nRow
= rNode
.position
+ nOffset
;
119 for (; it
!= itEnd
; ++it
, ++nRow
)
120 rFuncElem(nRow
, *it
);
123 template<typename BlkT
, typename ItrT
, typename NodeT
, typename FuncElem
>
124 void EachElem(NodeT
& rNode
, FuncElem
& rFuncElem
)
126 auto it
= BlkT::begin(*rNode
.data
);
127 auto itEnd
= BlkT::end(*rNode
.data
);
128 size_t nRow
= rNode
.position
;
129 for (; it
!= itEnd
; ++it
, ++nRow
)
130 rFuncElem(nRow
, *it
);
133 template<typename BlkT
, typename ItrT
, typename NodeT
, typename FuncElem
>
134 void EachElemReverse(NodeT
& rNode
, FuncElem
& rFuncElem
)
136 auto it
= BlkT::rbegin(*rNode
.data
);
137 auto itEnd
= BlkT::rend(*rNode
.data
);
138 size_t nRow
= rNode
.position
;
139 for (; it
!= itEnd
; ++it
, ++nRow
)
140 rFuncElem(nRow
, *it
);
143 template<typename BlkT
, typename StoreT
, typename FuncElem
>
144 std::pair
<typename
StoreT::const_iterator
, size_t>
146 const StoreT
& rStore
, const typename
StoreT::const_iterator
& it
, size_t nOffset
, size_t nDataSize
,
149 typedef std::pair
<typename
StoreT::const_iterator
, size_t> PositionType
;
151 typename
BlkT::const_iterator itData
= BlkT::begin(*it
->data
);
152 std::advance(itData
, nOffset
);
153 typename
BlkT::const_iterator itDataEnd
= itData
;
154 std::advance(itDataEnd
, nDataSize
);
155 size_t nTopRow
= it
->position
+ nOffset
;
156 size_t nRow
= nTopRow
;
157 for (; itData
!= itDataEnd
; ++itData
, ++nRow
)
159 if (rFuncElem(nRow
, *itData
))
160 return PositionType(it
, nRow
- it
->position
);
163 return PositionType(rStore
.end(), 0);
166 template<typename StoreT
, typename BlkT
, typename FuncElem
, typename FuncElse
>
167 void ParseElements1(const StoreT
& rStore
, FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
169 typename
StoreT::size_type nTopRow
= 0, nDataSize
= 0;
170 typename
StoreT::const_iterator it
= rStore
.begin(), itEnd
= rStore
.end();
171 for (; it
!= itEnd
; ++it
, nTopRow
+= nDataSize
)
173 nDataSize
= it
->size
;
174 if (it
->type
!= BlkT::block_type
)
176 rFuncElse(it
->type
, nTopRow
, nDataSize
);
180 EachElem
<BlkT
, typename
BlkT::const_iterator
>(*it
, rFuncElem
);
184 template<typename StoreT
, typename BlkT
, typename FuncElem
, typename FuncElse
>
185 typename
StoreT::const_iterator
187 const typename
StoreT::const_iterator
& itPos
, const StoreT
& rStore
,
188 typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
189 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
191 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
193 PositionType aPos
= rStore
.position(itPos
, nStart
);
194 typename
StoreT::const_iterator it
= aPos
.first
;
195 typename
StoreT::size_type nOffset
= aPos
.second
;
196 typename
StoreT::size_type nDataSize
= 0;
197 typename
StoreT::size_type nTopRow
= nStart
;
199 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
201 bool bLastBlock
= false;
202 nDataSize
= it
->size
- nOffset
;
203 if (nTopRow
+ nDataSize
- 1 > nEnd
)
205 // Truncate the block.
206 nDataSize
= nEnd
- nTopRow
+ 1;
210 if (it
->type
== BlkT::block_type
)
211 EachElem
<BlkT
, typename
BlkT::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
213 rFuncElse(it
->type
, nTopRow
, nDataSize
);
222 template<typename StoreT
, typename Blk1
, typename Blk2
, typename FuncElem
, typename FuncElse
>
223 typename
StoreT::const_iterator
225 const typename
StoreT::const_iterator
& itPos
, const StoreT
& rStore
, typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
226 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
228 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
230 PositionType aPos
= rStore
.position(itPos
, nStart
);
231 typename
StoreT::const_iterator it
= aPos
.first
;
232 typename
StoreT::size_type nOffset
= aPos
.second
;
233 typename
StoreT::size_type nDataSize
= 0;
234 typename
StoreT::size_type nTopRow
= nStart
;
236 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
238 bool bLastBlock
= false;
239 nDataSize
= it
->size
- nOffset
;
240 if (nTopRow
+ nDataSize
- 1 > nEnd
)
242 // Truncate the block.
243 nDataSize
= nEnd
- nTopRow
+ 1;
249 case Blk1::block_type
:
250 EachElem
<Blk1
, typename
Blk1::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
252 case Blk2::block_type
:
253 EachElem
<Blk2
, typename
Blk2::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
256 rFuncElse(it
->type
, nTopRow
, nDataSize
);
266 template<typename StoreT
, typename Blk1
, typename Blk2
, typename Blk3
, typename Blk4
, typename FuncElem
, typename FuncElse
>
267 typename
StoreT::const_iterator
269 const typename
StoreT::const_iterator
& itPos
, const StoreT
& rStore
, typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
270 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
272 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
274 PositionType aPos
= rStore
.position(itPos
, nStart
);
275 typename
StoreT::const_iterator it
= aPos
.first
;
276 typename
StoreT::size_type nOffset
= aPos
.second
;
277 typename
StoreT::size_type nDataSize
= 0;
278 typename
StoreT::size_type nTopRow
= nStart
;
280 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
282 bool bLastBlock
= false;
283 nDataSize
= it
->size
- nOffset
;
284 if (nTopRow
+ nDataSize
- 1 > nEnd
)
286 // Truncate the block.
287 nDataSize
= nEnd
- nTopRow
+ 1;
293 case Blk1::block_type
:
294 EachElem
<Blk1
, typename
Blk1::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
296 case Blk2::block_type
:
297 EachElem
<Blk2
, typename
Blk2::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
299 case Blk3::block_type
:
300 EachElem
<Blk3
, typename
Blk3::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
302 case Blk4::block_type
:
303 EachElem
<Blk4
, typename
Blk4::const_iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
306 rFuncElse(it
->type
, nTopRow
, nDataSize
);
316 template<typename StoreT
, typename BlkT
, typename FuncElem
, typename FuncElse
>
317 void ProcessElements1(StoreT
& rStore
, FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
319 typename
StoreT::size_type nTopRow
= 0, nDataSize
= 0;
320 typename
StoreT::iterator it
= rStore
.begin(), itEnd
= rStore
.end();
321 for (; it
!= itEnd
; ++it
, nTopRow
+= nDataSize
)
323 nDataSize
= it
->size
;
324 if (it
->type
!= BlkT::block_type
)
326 rFuncElse(it
->type
, nTopRow
, nDataSize
);
330 EachElem
<BlkT
, typename
BlkT::iterator
>(*it
, rFuncElem
);
335 * This variant specifies start and end positions.
337 template<typename StoreT
, typename BlkT
, typename FuncElem
, typename FuncElse
>
338 typename
StoreT::iterator
340 const typename
StoreT::iterator
& itPos
, StoreT
& rStore
,
341 typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
342 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
344 typedef std::pair
<typename
StoreT::iterator
, typename
StoreT::size_type
> PositionType
;
346 PositionType aPos
= rStore
.position(itPos
, nStart
);
347 typename
StoreT::iterator it
= aPos
.first
;
348 typename
StoreT::size_type nOffset
= aPos
.second
;
349 typename
StoreT::size_type nDataSize
= 0;
350 typename
StoreT::size_type nTopRow
= nStart
;
352 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
354 bool bLastBlock
= false;
355 nDataSize
= it
->size
- nOffset
;
356 if (nTopRow
+ nDataSize
- 1 > nEnd
)
358 // Truncate the block.
359 nDataSize
= nEnd
- nTopRow
+ 1;
363 if (it
->type
== BlkT::block_type
)
364 EachElem
<BlkT
, typename
BlkT::iterator
>(*it
, nOffset
, nDataSize
, rFuncElem
);
366 rFuncElse(it
->type
, nTopRow
, nDataSize
);
375 template<typename StoreT
, typename Blk1
, typename Blk2
, typename FuncElem
, typename FuncElse
>
376 void ProcessElements2(StoreT
& rStore
, FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
378 typename
StoreT::size_type nTopRow
= 0, nDataSize
= 0;
379 typename
StoreT::iterator it
= rStore
.begin(), itEnd
= rStore
.end();
380 for (; it
!= itEnd
; ++it
, nTopRow
+= nDataSize
)
382 nDataSize
= it
->size
;
385 case Blk1::block_type
:
386 EachElem
<Blk1
, typename
Blk1::iterator
>(*it
, rFuncElem
);
388 case Blk2::block_type
:
389 EachElem
<Blk2
, typename
Blk2::iterator
>(*it
, rFuncElem
);
392 rFuncElse(it
->type
, nTopRow
, nDataSize
);
397 template<typename StoreT
, typename Blk1
, typename Blk2
, typename FuncElem
, typename FuncElse
>
398 void ProcessElements2Reverse(StoreT
& rStore
, FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
400 typename
StoreT::size_type nTopRow
= 0, nDataSize
= 0;
401 typename
StoreT::iterator it
= rStore
.begin(), itEnd
= rStore
.end();
402 for (; it
!= itEnd
; ++it
, nTopRow
+= nDataSize
)
404 nDataSize
= it
->size
;
407 case Blk1::block_type
:
408 EachElemReverse
<Blk1
, typename
Blk1::iterator
>(*it
, rFuncElem
);
410 case Blk2::block_type
:
411 EachElemReverse
<Blk2
, typename
Blk2::iterator
>(*it
, rFuncElem
);
414 rFuncElse(it
->type
, nTopRow
, nDataSize
);
419 template<typename StoreT
, typename Blk1
, typename FuncElem
, typename FuncElse
>
420 std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
>
422 const StoreT
& rStore
, typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
423 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
425 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
426 typedef std::pair
<typename
StoreT::size_type
, bool> ElseRetType
;
428 PositionType aPos
= rStore
.position(nStart
);
429 typename
StoreT::const_iterator it
= aPos
.first
;
430 typename
StoreT::size_type nOffset
= aPos
.second
;
431 typename
StoreT::size_type nDataSize
= 0;
432 typename
StoreT::size_type nTopRow
= nStart
;
434 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
436 bool bLastBlock
= false;
437 nDataSize
= it
->size
- nOffset
;
438 if (nTopRow
+ nDataSize
- 1 > nEnd
)
440 // Truncate the block.
441 nDataSize
= nEnd
- nTopRow
+ 1;
447 case Blk1::block_type
:
449 PositionType aRet
= CheckElem
<Blk1
>(rStore
, it
, nOffset
, nDataSize
, rFuncElem
);
450 if (aRet
.first
!= rStore
.end())
456 ElseRetType aRet
= rFuncElse(it
->type
, nTopRow
, nDataSize
);
458 return PositionType(it
, aRet
.first
);
466 return PositionType(rStore
.end(), 0);
469 template<typename StoreT
, typename Blk1
, typename Blk2
, typename FuncElem
, typename FuncElse
>
470 std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
>
472 const StoreT
& rStore
, typename
StoreT::size_type nStart
, typename
StoreT::size_type nEnd
,
473 FuncElem
& rFuncElem
, FuncElse
& rFuncElse
)
475 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
476 typedef std::pair
<typename
StoreT::size_type
, bool> ElseRetType
;
478 PositionType aPos
= rStore
.position(nStart
);
479 typename
StoreT::const_iterator it
= aPos
.first
;
480 typename
StoreT::size_type nOffset
= aPos
.second
;
481 typename
StoreT::size_type nDataSize
= 0;
482 typename
StoreT::size_type nTopRow
= nStart
;
484 for (; it
!= rStore
.end() && nTopRow
<= nEnd
; ++it
, nOffset
= 0, nTopRow
+= nDataSize
)
486 bool bLastBlock
= false;
487 nDataSize
= it
->size
- nOffset
;
488 if (nTopRow
+ nDataSize
- 1 > nEnd
)
490 // Truncate the block.
491 nDataSize
= nEnd
- nTopRow
+ 1;
497 case Blk1::block_type
:
499 PositionType aRet
= CheckElem
<Blk1
>(rStore
, it
, nOffset
, nDataSize
, rFuncElem
);
500 if (aRet
.first
!= rStore
.end())
504 case Blk2::block_type
:
506 PositionType aRet
= CheckElem
<Blk2
>(rStore
, it
, nOffset
, nDataSize
, rFuncElem
);
507 if (aRet
.first
!= rStore
.end())
513 ElseRetType aRet
= rFuncElse(*it
, nOffset
, nDataSize
);
515 return PositionType(it
, aRet
.first
);
523 return PositionType(rStore
.end(), 0);
526 // Efficiently set all elements for which the predicate returns true as empty.
527 template<typename Blk1
, typename StoreT
, typename FuncElem
>
528 void SetElementsToEmpty1(
529 StoreT
& rStore
, FuncElem
& rFuncElem
)
531 typedef std::pair
<typename
StoreT::const_iterator
, typename
StoreT::size_type
> PositionType
;
533 for (typename
StoreT::iterator it
= rStore
.begin(); it
!= rStore
.end(); ++it
)
535 if (it
->type
== Blk1::block_type
)
537 PositionType firstToEmpty
= CheckElem
<Blk1
>(rStore
, it
, 0, it
->size
, rFuncElem
);
538 if (firstToEmpty
.first
!= rStore
.end())
540 typename
StoreT::size_type nFirstOffset
= firstToEmpty
.second
;
541 typename
StoreT::size_type nRemainingDataSize
= it
->size
- nFirstOffset
;
542 FuncNotElem
<FuncElem
, typename
Blk1::value_type
> notFuncElem(rFuncElem
);
543 PositionType lastToEmpty
= CheckElem
<Blk1
>(rStore
, it
, nFirstOffset
, nRemainingDataSize
,
545 typename
StoreT::size_type nLastOffset
= lastToEmpty
.first
!= rStore
.end()
546 ? lastToEmpty
.second
- 1 : it
->size
- 1;
547 it
= rStore
.set_empty(it
, it
->position
+ nFirstOffset
, it
->position
+ nLastOffset
);
548 // The returned iterator points to the empty elements block.
549 assert(it
->type
== sc::element_type_empty
);
557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */