LibreOffice Module sc (master) 1
mtvfunctions.hxx
Go to the documentation of this file.
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
10#pragma once
11
12#include <cstdlib>
13#include <mdds/multi_type_vector/types.hpp>
14
15namespace sc {
16
17template<typename SizeT, typename Ret = bool>
19{
20 Ret operator() (mdds::mtv::element_t, SizeT, SizeT) const
21 {
22 return Ret();
23 }
24};
25
26template<typename FuncElem, typename Elem>
28{
29 FuncElem& func;
30 FuncNotElem(FuncElem& f) : func(f) {}
31 bool operator() (size_t s, Elem elem) const
32 {
33 return !func(s, elem);
34 }
35};
36
41template<typename StoreT, typename Func>
42typename 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)
46{
47 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
48
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;
54
55 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
56 {
57 bool bLastBlock = false;
58 nDataSize = it->size - nOffset;
59 if (nTopRow + nDataSize - 1 > nEnd)
60 {
61 // Truncate the block.
62 nDataSize = nEnd - nTopRow + 1;
63 bLastBlock = true;
64 }
65
66 rFunc(*it, nOffset, nDataSize);
67
68 if (bLastBlock)
69 break;
70 }
71
72 return it;
73}
74
79template<typename StoreT, typename Func>
80typename StoreT::iterator
81ProcessBlock(const typename StoreT::iterator& itPos, StoreT& rStore, Func& rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
82{
83 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
84
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;
90
91 for (; it != rStore.end() && nCurRow <= nEnd; ++it, nOffset = 0, nCurRow += nDataSize)
92 {
93 bool bLastBlock = false;
94 nDataSize = it->size - nOffset;
95 if (nCurRow + nDataSize - 1 > nEnd)
96 {
97 // Truncate the block.
98 nDataSize = nEnd - nCurRow + 1;
99 bLastBlock = true;
100 }
101
102 rFunc(*it, nOffset, nDataSize);
103
104 if (bLastBlock)
105 break;
106 }
107
108 return it;
109}
110
111template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
112void EachElem(NodeT& rNode, size_t nOffset, size_t nDataSize, FuncElem& rFuncElem)
113{
114 ItrT it = BlkT::begin(*rNode.data);
115 std::advance(it, nOffset);
116 ItrT itEnd = it;
117 std::advance(itEnd, nDataSize);
118 size_t nRow = rNode.position + nOffset;
119 for (; it != itEnd; ++it, ++nRow)
120 rFuncElem(nRow, *it);
121}
122
123template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
124void EachElem(NodeT& rNode, FuncElem& rFuncElem)
125{
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);
131}
132
133template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
134void EachElemReverse(NodeT& rNode, FuncElem& rFuncElem)
135{
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);
141}
142
143template<typename BlkT, typename StoreT, typename FuncElem>
144std::pair<typename StoreT::const_iterator, size_t>
146 const StoreT& rStore, const typename StoreT::const_iterator& it, size_t nOffset, size_t nDataSize,
147 FuncElem& rFuncElem)
148{
149 typedef std::pair<typename StoreT::const_iterator, size_t> PositionType;
150
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)
158 {
159 if (rFuncElem(nRow, *itData))
160 return PositionType(it, nRow - it->position);
161 }
162
163 return PositionType(rStore.end(), 0);
164}
165
166template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
167void ParseElements1(const StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
168{
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)
172 {
173 nDataSize = it->size;
174 if (it->type != BlkT::block_type)
175 {
176 rFuncElse(it->type, nTopRow, nDataSize);
177 continue;
178 }
179
180 EachElem<BlkT, typename BlkT::const_iterator>(*it, rFuncElem);
181 }
182}
183
184template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
185typename 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)
190{
191 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
192
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;
198
199 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
200 {
201 bool bLastBlock = false;
202 nDataSize = it->size - nOffset;
203 if (nTopRow + nDataSize - 1 > nEnd)
204 {
205 // Truncate the block.
206 nDataSize = nEnd - nTopRow + 1;
207 bLastBlock = true;
208 }
209
210 if (it->type == BlkT::block_type)
211 EachElem<BlkT, typename BlkT::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
212 else
213 rFuncElse(it->type, nTopRow, nDataSize);
214
215 if (bLastBlock)
216 break;
217 }
218
219 return it;
220};
221
222template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
223typename 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)
227{
228 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
229
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;
235
236 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
237 {
238 bool bLastBlock = false;
239 nDataSize = it->size - nOffset;
240 if (nTopRow + nDataSize - 1 > nEnd)
241 {
242 // Truncate the block.
243 nDataSize = nEnd - nTopRow + 1;
244 bLastBlock = true;
245 }
246
247 switch (it->type)
248 {
249 case Blk1::block_type:
250 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
251 break;
252 case Blk2::block_type:
253 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
254 break;
255 default:
256 rFuncElse(it->type, nTopRow, nDataSize);
257 }
258
259 if (bLastBlock)
260 break;
261 }
262
263 return it;
264}
265
266template<typename StoreT, typename Blk1, typename Blk2, typename Blk3, typename Blk4, typename FuncElem, typename FuncElse>
267typename 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)
271{
272 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
273
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;
279
280 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
281 {
282 bool bLastBlock = false;
283 nDataSize = it->size - nOffset;
284 if (nTopRow + nDataSize - 1 > nEnd)
285 {
286 // Truncate the block.
287 nDataSize = nEnd - nTopRow + 1;
288 bLastBlock = true;
289 }
290
291 switch (it->type)
292 {
293 case Blk1::block_type:
294 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
295 break;
296 case Blk2::block_type:
297 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
298 break;
299 case Blk3::block_type:
300 EachElem<Blk3, typename Blk3::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
301 break;
302 case Blk4::block_type:
303 EachElem<Blk4, typename Blk4::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
304 break;
305 default:
306 rFuncElse(it->type, nTopRow, nDataSize);
307 }
308
309 if (bLastBlock)
310 break;
311 }
312
313 return it;
314}
315
316template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
317void ProcessElements1(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
318{
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)
322 {
323 nDataSize = it->size;
324 if (it->type != BlkT::block_type)
325 {
326 rFuncElse(it->type, nTopRow, nDataSize);
327 continue;
328 }
329
330 EachElem<BlkT, typename BlkT::iterator>(*it, rFuncElem);
331 }
332}
333
337template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
338typename 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)
343{
344 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
345
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;
351
352 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
353 {
354 bool bLastBlock = false;
355 nDataSize = it->size - nOffset;
356 if (nTopRow + nDataSize - 1 > nEnd)
357 {
358 // Truncate the block.
359 nDataSize = nEnd - nTopRow + 1;
360 bLastBlock = true;
361 }
362
363 if (it->type == BlkT::block_type)
364 EachElem<BlkT, typename BlkT::iterator>(*it, nOffset, nDataSize, rFuncElem);
365 else
366 rFuncElse(it->type, nTopRow, nDataSize);
367
368 if (bLastBlock)
369 break;
370 }
371
372 return it;
373};
374
375template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
376void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
377{
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)
381 {
382 nDataSize = it->size;
383 switch (it->type)
384 {
385 case Blk1::block_type:
386 EachElem<Blk1, typename Blk1::iterator>(*it, rFuncElem);
387 break;
388 case Blk2::block_type:
389 EachElem<Blk2, typename Blk2::iterator>(*it, rFuncElem);
390 break;
391 default:
392 rFuncElse(it->type, nTopRow, nDataSize);
393 }
394 }
395}
396
397template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
398void ProcessElements2Reverse(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
399{
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)
403 {
404 nDataSize = it->size;
405 switch (it->type)
406 {
407 case Blk1::block_type:
408 EachElemReverse<Blk1, typename Blk1::iterator>(*it, rFuncElem);
409 break;
410 case Blk2::block_type:
411 EachElemReverse<Blk2, typename Blk2::iterator>(*it, rFuncElem);
412 break;
413 default:
414 rFuncElse(it->type, nTopRow, nDataSize);
415 }
416 }
417}
418
419template<typename StoreT, typename Blk1, typename FuncElem, typename FuncElse>
420std::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)
424{
425 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
426 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
427
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;
433
434 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
435 {
436 bool bLastBlock = false;
437 nDataSize = it->size - nOffset;
438 if (nTopRow + nDataSize - 1 > nEnd)
439 {
440 // Truncate the block.
441 nDataSize = nEnd - nTopRow + 1;
442 bLastBlock = true;
443 }
444
445 switch (it->type)
446 {
447 case Blk1::block_type:
448 {
449 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
450 if (aRet.first != rStore.end())
451 return aRet;
452 }
453 break;
454 default:
455 {
456 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
457 if (aRet.second)
458 return PositionType(it, aRet.first);
459 }
460 }
461
462 if (bLastBlock)
463 break;
464 }
465
466 return PositionType(rStore.end(), 0);
467}
468
469template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
470std::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)
474{
475 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
476 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
477
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;
483
484 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
485 {
486 bool bLastBlock = false;
487 nDataSize = it->size - nOffset;
488 if (nTopRow + nDataSize - 1 > nEnd)
489 {
490 // Truncate the block.
491 nDataSize = nEnd - nTopRow + 1;
492 bLastBlock = true;
493 }
494
495 switch (it->type)
496 {
497 case Blk1::block_type:
498 {
499 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
500 if (aRet.first != rStore.end())
501 return aRet;
502 }
503 break;
504 case Blk2::block_type:
505 {
506 PositionType aRet = CheckElem<Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
507 if (aRet.first != rStore.end())
508 return aRet;
509 }
510 break;
511 default:
512 {
513 ElseRetType aRet = rFuncElse(*it, nOffset, nDataSize);
514 if (aRet.second)
515 return PositionType(it, aRet.first);
516 }
517 }
518
519 if (bLastBlock)
520 break;
521 }
522
523 return PositionType(rStore.end(), 0);
524}
525
526// Efficiently set all elements for which the predicate returns true as empty.
527template<typename Blk1, typename StoreT, typename FuncElem>
529 StoreT& rStore, FuncElem& rFuncElem)
530{
531 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
532
533 for (typename StoreT::iterator it = rStore.begin(); it != rStore.end(); ++it)
534 {
535 if (it->type == Blk1::block_type)
536 {
537 PositionType firstToEmpty = CheckElem<Blk1>(rStore, it, 0, it->size, rFuncElem);
538 if (firstToEmpty.first != rStore.end())
539 {
540 typename StoreT::size_type nFirstOffset = firstToEmpty.second;
541 typename StoreT::size_type nRemainingDataSize = it->size - nFirstOffset;
543 PositionType lastToEmpty = CheckElem<Blk1>(rStore, it, nFirstOffset, nRemainingDataSize,
544 notFuncElem);
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);
550 }
551 }
552 }
553}
554
555}
556
557/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
CAUTION! The following defines must be in the same namespace as the respective type.
std::pair< typename StoreT::const_iterator, size_t > CheckElem(const StoreT &rStore, const typename StoreT::const_iterator &it, size_t nOffset, size_t nDataSize, FuncElem &rFuncElem)
void ProcessElements2(StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
StoreT::const_iterator ParseBlock(const typename StoreT::const_iterator &itPos, const StoreT &rStore, Func &rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
Generic algorithm to parse blocks of multi_type_vector either partially or fully.
std::pair< typename StoreT::const_iterator, typename StoreT::size_type > FindElement1(const StoreT &rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd, FuncElem &rFuncElem, FuncElse &rFuncElse)
StoreT::iterator ProcessBlock(const typename StoreT::iterator &itPos, StoreT &rStore, Func &rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
Non-const variant of the above function.
void EachElem(NodeT &rNode, size_t nOffset, size_t nDataSize, FuncElem &rFuncElem)
void ParseElements1(const StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
StoreT::const_iterator ParseElements4(const typename StoreT::const_iterator &itPos, const StoreT &rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd, FuncElem &rFuncElem, FuncElse &rFuncElse)
void ProcessElements2Reverse(StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
void ProcessElements1(StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
void EachElemReverse(NodeT &rNode, FuncElem &rFuncElem)
void SetElementsToEmpty1(StoreT &rStore, FuncElem &rFuncElem)
const mdds::mtv::element_t element_type_empty
Definition: mtvelements.hxx:56
StoreT::const_iterator ParseElements2(const typename StoreT::const_iterator &itPos, const StoreT &rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd, FuncElem &rFuncElem, FuncElse &rFuncElse)
std::pair< typename StoreT::const_iterator, typename StoreT::size_type > FindElement2(const StoreT &rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd, FuncElem &rFuncElem, FuncElse &rFuncElse)
Ret operator()(mdds::mtv::element_t, SizeT, SizeT) const
FuncNotElem(FuncElem &f)
FuncElem & func
bool operator()(size_t s, Elem elem) const