Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / inc / mtvfunctions.hxx
blob3c2a94010589cfca73ae382c82a547a1854ede45
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #ifndef SC_MTVFUNCTIONS_HXX
11 #define SC_MTVFUNCTIONS_HXX
13 #include <cstdlib>
14 #include <mdds/multi_type_vector_types.hpp>
16 namespace sc {
18 template<typename _SizeT, typename _Ret = bool>
19 struct FuncElseNoOp
21 _Ret operator() (mdds::mtv::element_t, _SizeT, _SizeT) const
23 return _Ret();
27 /**
28 * Generic algorithm to parse blocks of multi_type_vector either partially
29 * or fully.
31 template<typename _StoreT, typename _Func>
32 typename _StoreT::const_iterator
33 ParseBlock(
34 const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, _Func& rFunc,
35 typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd)
37 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
39 PositionType aPos = rStore.position(itPos, nStart);
40 typename _StoreT::const_iterator it = aPos.first;
41 typename _StoreT::size_type nOffset = aPos.second;
42 typename _StoreT::size_type nDataSize = 0;
43 typename _StoreT::size_type nTopRow = nStart;
45 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
47 bool bLastBlock = false;
48 nDataSize = it->size - nOffset;
49 if (nTopRow + nDataSize - 1 > nEnd)
51 // Truncate the block.
52 nDataSize = nEnd - nTopRow + 1;
53 bLastBlock = true;
56 rFunc(*it, nOffset, nDataSize);
58 if (bLastBlock)
59 break;
62 return it;
65 /**
66 * Non-const variant of the above function. TODO: Find a way to merge these
67 * two in an elegant way.
69 template<typename _StoreT, typename _Func>
70 typename _StoreT::iterator
71 ProcessBlock(const typename _StoreT::iterator& itPos, _StoreT& rStore, _Func& rFunc, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd)
73 typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
75 PositionType aPos = rStore.position(itPos, nStart);
76 typename _StoreT::iterator it = aPos.first;
77 typename _StoreT::size_type nOffset = aPos.second;
78 typename _StoreT::size_type nDataSize = 0;
79 typename _StoreT::size_type nCurRow = nStart;
81 for (; it != rStore.end() && nCurRow <= nEnd; ++it, nOffset = 0, nCurRow += nDataSize)
83 bool bLastBlock = false;
84 nDataSize = it->size - nOffset;
85 if (nCurRow + nDataSize - 1 > nEnd)
87 // Truncate the block.
88 nDataSize = nEnd - nCurRow + 1;
89 bLastBlock = true;
92 rFunc(*it, nOffset, nDataSize);
94 if (bLastBlock)
95 break;
98 return it;
101 template<typename _BlkT, typename _ItrT, typename _NodeT, typename _FuncElem>
102 void EachElem(_NodeT& rNode, size_t nOffset, size_t nDataSize, _FuncElem& rFuncElem)
104 _ItrT it = _BlkT::begin(*rNode.data);
105 std::advance(it, nOffset);
106 _ItrT itEnd = it;
107 std::advance(itEnd, nDataSize);
108 size_t nRow = rNode.position + nOffset;
109 for (; it != itEnd; ++it, ++nRow)
110 rFuncElem(nRow, *it);
113 template<typename _BlkT, typename _ItrT, typename _NodeT, typename _FuncElem>
114 void EachElem(_NodeT& rNode, _FuncElem& rFuncElem)
116 _ItrT it = _BlkT::begin(*rNode.data);
117 _ItrT itEnd = _BlkT::end(*rNode.data);
118 size_t nRow = rNode.position;
119 for (; it != itEnd; ++it, ++nRow)
120 rFuncElem(nRow, *it);
123 template<typename _BlkT, typename _StoreT, typename _FuncElem>
124 std::pair<typename _StoreT::const_iterator, size_t>
125 CheckElem(
126 const _StoreT& rStore, const typename _StoreT::const_iterator& it, size_t nOffset, size_t nDataSize,
127 _FuncElem& rFuncElem)
129 typedef std::pair<typename _StoreT::const_iterator, size_t> PositionType;
131 typename _BlkT::const_iterator itData = _BlkT::begin(*it->data);
132 std::advance(itData, nOffset);
133 typename _BlkT::const_iterator itDataEnd = itData;
134 std::advance(itDataEnd, nDataSize);
135 size_t nTopRow = it->position + nOffset;
136 size_t nRow = nTopRow;
137 for (; itData != itDataEnd; ++itData, ++nRow)
139 if (rFuncElem(nRow, *itData))
140 return PositionType(it, nRow - it->position);
143 return PositionType(rStore.end(), 0);
146 template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
147 void ParseElements1(const _StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
149 typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
150 typename _StoreT::const_iterator it = rStore.begin(), itEnd = rStore.end();
151 for (; it != itEnd; ++it, nTopRow += nDataSize)
153 nDataSize = it->size;
154 if (it->type != _BlkT::block_type)
156 rFuncElse(it->type, nTopRow, nDataSize);
157 continue;
160 EachElem<_BlkT, typename _BlkT::const_iterator>(*it, rFuncElem);
164 template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
165 typename _StoreT::const_iterator
166 ParseElements1(
167 const typename _StoreT::const_iterator& itPos, const _StoreT& rStore,
168 typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
169 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
171 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
173 PositionType aPos = rStore.position(itPos, nStart);
174 typename _StoreT::const_iterator it = aPos.first;
175 typename _StoreT::size_type nOffset = aPos.second;
176 typename _StoreT::size_type nDataSize = 0;
177 typename _StoreT::size_type nTopRow = nStart;
179 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
181 bool bLastBlock = false;
182 nDataSize = it->size - nOffset;
183 if (nTopRow + nDataSize - 1 > nEnd)
185 // Truncate the block.
186 nDataSize = nEnd - nTopRow + 1;
187 bLastBlock = true;
190 if (it->type == _BlkT::block_type)
191 EachElem<_BlkT, typename _BlkT::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
192 else
193 rFuncElse(it->type, nTopRow, nDataSize);
196 if (bLastBlock)
197 break;
200 return it;
203 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
204 typename _StoreT::const_iterator
205 ParseElements2(
206 const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
207 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
209 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
211 PositionType aPos = rStore.position(itPos, nStart);
212 typename _StoreT::const_iterator it = aPos.first;
213 typename _StoreT::size_type nOffset = aPos.second;
214 typename _StoreT::size_type nDataSize = 0;
215 typename _StoreT::size_type nTopRow = nStart;
217 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
219 bool bLastBlock = false;
220 nDataSize = it->size - nOffset;
221 if (nTopRow + nDataSize - 1 > nEnd)
223 // Truncate the block.
224 nDataSize = nEnd - nTopRow + 1;
225 bLastBlock = true;
228 switch (it->type)
230 case _Blk1::block_type:
231 EachElem<_Blk1, typename _Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
232 break;
233 case _Blk2::block_type:
234 EachElem<_Blk2, typename _Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
235 break;
236 default:
237 rFuncElse(it->type, nTopRow, nDataSize);
240 if (bLastBlock)
241 break;
244 return it;
247 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
248 typename _StoreT::const_iterator
249 ParseElements4(
250 const typename _StoreT::const_iterator& itPos, const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
251 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
253 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
255 PositionType aPos = rStore.position(itPos, nStart);
256 typename _StoreT::const_iterator it = aPos.first;
257 typename _StoreT::size_type nOffset = aPos.second;
258 typename _StoreT::size_type nDataSize = 0;
259 typename _StoreT::size_type nTopRow = nStart;
261 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
263 bool bLastBlock = false;
264 nDataSize = it->size - nOffset;
265 if (nTopRow + nDataSize - 1 > nEnd)
267 // Truncate the block.
268 nDataSize = nEnd - nTopRow + 1;
269 bLastBlock = true;
272 switch (it->type)
274 case _Blk1::block_type:
275 EachElem<_Blk1, typename _Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
276 break;
277 case _Blk2::block_type:
278 EachElem<_Blk2, typename _Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
279 break;
280 case _Blk3::block_type:
281 EachElem<_Blk3, typename _Blk3::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
282 break;
283 case _Blk4::block_type:
284 EachElem<_Blk4, typename _Blk4::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
285 break;
286 default:
287 rFuncElse(it->type, nTopRow, nDataSize);
290 if (bLastBlock)
291 break;
294 return it;
297 template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
298 void ProcessElements1(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
300 typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
301 typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
302 for (; it != itEnd; ++it, nTopRow += nDataSize)
304 nDataSize = it->size;
305 if (it->type != _BlkT::block_type)
307 rFuncElse(it->type, nTopRow, nDataSize);
308 continue;
311 EachElem<_BlkT, typename _BlkT::iterator>(*it, rFuncElem);
316 * This variant specifies start and end positions.
318 template<typename _StoreT, typename _BlkT, typename _FuncElem, typename _FuncElse>
319 typename _StoreT::iterator
320 ProcessElements1(
321 const typename _StoreT::iterator& itPos, _StoreT& rStore,
322 typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
323 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
325 typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
327 PositionType aPos = rStore.position(itPos, nStart);
328 typename _StoreT::iterator it = aPos.first;
329 typename _StoreT::size_type nOffset = aPos.second;
330 typename _StoreT::size_type nDataSize = 0;
331 typename _StoreT::size_type nTopRow = nStart;
333 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
335 bool bLastBlock = false;
336 nDataSize = it->size - nOffset;
337 if (nTopRow + nDataSize - 1 > nEnd)
339 // Truncate the block.
340 nDataSize = nEnd - nTopRow + 1;
341 bLastBlock = true;
344 if (it->type == _BlkT::block_type)
345 EachElem<_BlkT, typename _BlkT::iterator>(*it, nOffset, nDataSize, rFuncElem);
346 else
347 rFuncElse(it->type, nTopRow, nDataSize);
349 if (bLastBlock)
350 break;
353 return it;
356 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
357 void ProcessElements2(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
359 typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
360 typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
361 for (; it != itEnd; ++it, nTopRow += nDataSize)
363 nDataSize = it->size;
364 switch (it->type)
366 case _Blk1::block_type:
367 EachElem<_Blk1, typename _Blk1::iterator>(*it, rFuncElem);
368 break;
369 case _Blk2::block_type:
370 EachElem<_Blk2, typename _Blk2::iterator>(*it, rFuncElem);
371 break;
372 default:
373 rFuncElse(it->type, nTopRow, nDataSize);
378 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
379 typename _StoreT::iterator
380 ProcessElements2(
381 const typename _StoreT::iterator& itPos, _StoreT& rStore,
382 typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
383 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
385 typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
387 PositionType aPos = rStore.position(itPos, nStart);
388 typename _StoreT::iterator it = aPos.first;
389 typename _StoreT::size_type nOffset = aPos.second;
390 typename _StoreT::size_type nDataSize = 0;
391 typename _StoreT::size_type nTopRow = nStart;
393 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
395 bool bLastBlock = false;
396 nDataSize = it->size - nOffset;
397 if (nTopRow + nDataSize - 1 > nEnd)
399 // Truncate the block.
400 nDataSize = nEnd - nTopRow + 1;
401 bLastBlock = true;
404 switch (it->type)
406 case _Blk1::block_type:
407 EachElem<_Blk1, typename _Blk1::iterator>(*it, nOffset, nDataSize, rFuncElem);
408 break;
409 case _Blk2::block_type:
410 EachElem<_Blk2, typename _Blk2::iterator>(*it, nOffset, nDataSize, rFuncElem);
411 break;
412 default:
413 rFuncElse(it->type, nTopRow, nDataSize);
416 if (bLastBlock)
417 break;
420 return it;
423 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _FuncElem, typename _FuncElse>
424 void ProcessElements3(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
426 typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
427 typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
428 for (; it != itEnd; ++it, nTopRow += nDataSize)
430 nDataSize = it->size;
431 switch (it->type)
433 case _Blk1::block_type:
434 EachElem<_Blk1, typename _Blk1::iterator>(*it, rFuncElem);
435 break;
436 case _Blk2::block_type:
437 EachElem<_Blk2, typename _Blk2::iterator>(*it, rFuncElem);
438 break;
439 case _Blk3::block_type:
440 EachElem<_Blk3, typename _Blk3::iterator>(*it, rFuncElem);
441 break;
442 default:
443 rFuncElse(it->type, nTopRow, nDataSize);
448 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
449 void ProcessElements4(_StoreT& rStore, _FuncElem& rFuncElem, _FuncElse& rFuncElse)
451 typename _StoreT::size_type nTopRow = 0, nDataSize = 0;
452 typename _StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
453 for (; it != itEnd; ++it, nTopRow += nDataSize)
455 nDataSize = it->size;
456 switch (it->type)
458 case _Blk1::block_type:
459 EachElem<_Blk1, typename _Blk1::iterator>(*it, rFuncElem);
460 break;
461 case _Blk2::block_type:
462 EachElem<_Blk2, typename _Blk2::iterator>(*it, rFuncElem);
463 break;
464 case _Blk3::block_type:
465 EachElem<_Blk3, typename _Blk3::iterator>(*it, rFuncElem);
466 break;
467 case _Blk4::block_type:
468 EachElem<_Blk4, typename _Blk4::iterator>(*it, rFuncElem);
469 break;
470 default:
471 rFuncElse(it->type, nTopRow, nDataSize);
476 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _Blk3, typename _Blk4, typename _FuncElem, typename _FuncElse>
477 typename _StoreT::iterator
478 ProcessElements4(
479 const typename _StoreT::iterator& itPos, _StoreT& rStore,
480 typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
481 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
483 typedef std::pair<typename _StoreT::iterator, typename _StoreT::size_type> PositionType;
485 PositionType aPos = rStore.position(itPos, nStart);
486 typename _StoreT::iterator it = aPos.first;
487 typename _StoreT::size_type nOffset = aPos.second;
488 typename _StoreT::size_type nDataSize = 0;
489 typename _StoreT::size_type nTopRow = nStart;
491 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
493 bool bLastBlock = false;
494 nDataSize = it->size - nOffset;
495 if (nTopRow + nDataSize - 1 > nEnd)
497 // Truncate the block.
498 nDataSize = nEnd - nTopRow + 1;
499 bLastBlock = true;
502 switch (it->type)
504 case _Blk1::block_type:
505 EachElem<_Blk1, typename _Blk1::iterator>(*it, nOffset, nDataSize, rFuncElem);
506 break;
507 case _Blk2::block_type:
508 EachElem<_Blk2, typename _Blk2::iterator>(*it, nOffset, nDataSize, rFuncElem);
509 break;
510 case _Blk3::block_type:
511 EachElem<_Blk3, typename _Blk3::iterator>(*it, nOffset, nDataSize, rFuncElem);
512 break;
513 case _Blk4::block_type:
514 EachElem<_Blk4, typename _Blk4::iterator>(*it, nOffset, nDataSize, rFuncElem);
515 break;
516 default:
517 rFuncElse(it->type, nTopRow, nDataSize);
520 if (bLastBlock)
521 break;
524 return it;
527 template<typename _StoreT, typename _Blk1, typename _FuncElem, typename _FuncElse>
528 std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type>
529 FindElement1(
530 const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
531 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
533 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
534 typedef std::pair<typename _StoreT::size_type, bool> ElseRetType;
536 PositionType aPos = rStore.position(nStart);
537 typename _StoreT::const_iterator it = aPos.first;
538 typename _StoreT::size_type nOffset = aPos.second;
539 typename _StoreT::size_type nDataSize = 0;
540 typename _StoreT::size_type nTopRow = nStart;
542 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
544 bool bLastBlock = false;
545 nDataSize = it->size - nOffset;
546 if (nTopRow + nDataSize - 1 > nEnd)
548 // Truncate the block.
549 nDataSize = nEnd - nTopRow + 1;
550 bLastBlock = true;
553 switch (it->type)
555 case _Blk1::block_type:
557 PositionType aRet = CheckElem<_Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
558 if (aRet.first != rStore.end())
559 return aRet;
561 break;
562 default:
564 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
565 if (aRet.second)
566 return PositionType(it, aRet.first);
570 if (bLastBlock)
571 break;
574 return PositionType(rStore.end(), 0);
577 template<typename _StoreT, typename _Blk1, typename _Blk2, typename _FuncElem, typename _FuncElse>
578 std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type>
579 FindElement2(
580 const _StoreT& rStore, typename _StoreT::size_type nStart, typename _StoreT::size_type nEnd,
581 _FuncElem& rFuncElem, _FuncElse& rFuncElse)
583 typedef std::pair<typename _StoreT::const_iterator, typename _StoreT::size_type> PositionType;
584 typedef std::pair<typename _StoreT::size_type, bool> ElseRetType;
586 PositionType aPos = rStore.position(nStart);
587 typename _StoreT::const_iterator it = aPos.first;
588 typename _StoreT::size_type nOffset = aPos.second;
589 typename _StoreT::size_type nDataSize = 0;
590 typename _StoreT::size_type nTopRow = nStart;
592 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
594 bool bLastBlock = false;
595 nDataSize = it->size - nOffset;
596 if (nTopRow + nDataSize - 1 > nEnd)
598 // Truncate the block.
599 nDataSize = nEnd - nTopRow + 1;
600 bLastBlock = true;
603 switch (it->type)
605 case _Blk1::block_type:
607 PositionType aRet = CheckElem<_Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
608 if (aRet.first != rStore.end())
609 return aRet;
611 break;
612 case _Blk2::block_type:
614 PositionType aRet = CheckElem<_Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
615 if (aRet.first != rStore.end())
616 return aRet;
618 break;
619 default:
621 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
622 if (aRet.second)
623 return PositionType(it, aRet.first);
627 if (bLastBlock)
628 break;
631 return PositionType(rStore.end(), 0);
636 #endif
638 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */