Bump version to 6.4-15
[LibreOffice.git] / sc / inc / mtvfunctions.hxx
blob5e48bb2942d7c62739b4d9aa3ccb5c604d18b0d4
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 INCLUDED_SC_INC_MTVFUNCTIONS_HXX
11 #define INCLUDED_SC_INC_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 auto it = BlkT::begin(*rNode.data);
117 auto 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 ItrT, typename NodeT, typename FuncElem>
124 void EachElemReverse(NodeT& rNode, FuncElem& rFuncElem)
126 auto it = BlkT::rbegin(*rNode.data);
127 auto itEnd = BlkT::rend(*rNode.data);
128 size_t nRow = rNode.position;
129 for (; it != itEnd; ++it, ++nRow)
130 rFuncElem(nRow, *it);
133 template<typename BlkT, typename StoreT, typename FuncElem>
134 std::pair<typename StoreT::const_iterator, size_t>
135 CheckElem(
136 const StoreT& rStore, const typename StoreT::const_iterator& it, size_t nOffset, size_t nDataSize,
137 FuncElem& rFuncElem)
139 typedef std::pair<typename StoreT::const_iterator, size_t> PositionType;
141 typename BlkT::const_iterator itData = BlkT::begin(*it->data);
142 std::advance(itData, nOffset);
143 typename BlkT::const_iterator itDataEnd = itData;
144 std::advance(itDataEnd, nDataSize);
145 size_t nTopRow = it->position + nOffset;
146 size_t nRow = nTopRow;
147 for (; itData != itDataEnd; ++itData, ++nRow)
149 if (rFuncElem(nRow, *itData))
150 return PositionType(it, nRow - it->position);
153 return PositionType(rStore.end(), 0);
156 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
157 void ParseElements1(const StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
159 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
160 typename StoreT::const_iterator it = rStore.begin(), itEnd = rStore.end();
161 for (; it != itEnd; ++it, nTopRow += nDataSize)
163 nDataSize = it->size;
164 if (it->type != BlkT::block_type)
166 rFuncElse(it->type, nTopRow, nDataSize);
167 continue;
170 EachElem<BlkT, typename BlkT::const_iterator>(*it, rFuncElem);
174 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
175 typename StoreT::const_iterator
176 ParseElements1(
177 const typename StoreT::const_iterator& itPos, const StoreT& rStore,
178 typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
179 FuncElem& rFuncElem, FuncElse& rFuncElse)
181 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
183 PositionType aPos = rStore.position(itPos, nStart);
184 typename StoreT::const_iterator it = aPos.first;
185 typename StoreT::size_type nOffset = aPos.second;
186 typename StoreT::size_type nDataSize = 0;
187 typename StoreT::size_type nTopRow = nStart;
189 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
191 bool bLastBlock = false;
192 nDataSize = it->size - nOffset;
193 if (nTopRow + nDataSize - 1 > nEnd)
195 // Truncate the block.
196 nDataSize = nEnd - nTopRow + 1;
197 bLastBlock = true;
200 if (it->type == BlkT::block_type)
201 EachElem<BlkT, typename BlkT::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
202 else
203 rFuncElse(it->type, nTopRow, nDataSize);
205 if (bLastBlock)
206 break;
209 return it;
212 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
213 typename StoreT::const_iterator
214 ParseElements2(
215 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
216 FuncElem& rFuncElem, FuncElse& rFuncElse)
218 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
220 PositionType aPos = rStore.position(itPos, nStart);
221 typename StoreT::const_iterator it = aPos.first;
222 typename StoreT::size_type nOffset = aPos.second;
223 typename StoreT::size_type nDataSize = 0;
224 typename StoreT::size_type nTopRow = nStart;
226 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
228 bool bLastBlock = false;
229 nDataSize = it->size - nOffset;
230 if (nTopRow + nDataSize - 1 > nEnd)
232 // Truncate the block.
233 nDataSize = nEnd - nTopRow + 1;
234 bLastBlock = true;
237 switch (it->type)
239 case Blk1::block_type:
240 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
241 break;
242 case Blk2::block_type:
243 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
244 break;
245 default:
246 rFuncElse(it->type, nTopRow, nDataSize);
249 if (bLastBlock)
250 break;
253 return it;
256 template<typename StoreT, typename Blk1, typename Blk2, typename Blk3, typename Blk4, typename FuncElem, typename FuncElse>
257 typename StoreT::const_iterator
258 ParseElements4(
259 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
260 FuncElem& rFuncElem, FuncElse& rFuncElse)
262 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
264 PositionType aPos = rStore.position(itPos, nStart);
265 typename StoreT::const_iterator it = aPos.first;
266 typename StoreT::size_type nOffset = aPos.second;
267 typename StoreT::size_type nDataSize = 0;
268 typename StoreT::size_type nTopRow = nStart;
270 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
272 bool bLastBlock = false;
273 nDataSize = it->size - nOffset;
274 if (nTopRow + nDataSize - 1 > nEnd)
276 // Truncate the block.
277 nDataSize = nEnd - nTopRow + 1;
278 bLastBlock = true;
281 switch (it->type)
283 case Blk1::block_type:
284 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
285 break;
286 case Blk2::block_type:
287 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
288 break;
289 case Blk3::block_type:
290 EachElem<Blk3, typename Blk3::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
291 break;
292 case Blk4::block_type:
293 EachElem<Blk4, typename Blk4::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
294 break;
295 default:
296 rFuncElse(it->type, nTopRow, nDataSize);
299 if (bLastBlock)
300 break;
303 return it;
306 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
307 void ProcessElements1(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
309 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
310 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
311 for (; it != itEnd; ++it, nTopRow += nDataSize)
313 nDataSize = it->size;
314 if (it->type != BlkT::block_type)
316 rFuncElse(it->type, nTopRow, nDataSize);
317 continue;
320 EachElem<BlkT, typename BlkT::iterator>(*it, rFuncElem);
325 * This variant specifies start and end positions.
327 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
328 typename StoreT::iterator
329 ProcessElements1(
330 const typename StoreT::iterator& itPos, StoreT& rStore,
331 typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
332 FuncElem& rFuncElem, FuncElse& rFuncElse)
334 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
336 PositionType aPos = rStore.position(itPos, nStart);
337 typename StoreT::iterator it = aPos.first;
338 typename StoreT::size_type nOffset = aPos.second;
339 typename StoreT::size_type nDataSize = 0;
340 typename StoreT::size_type nTopRow = nStart;
342 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
344 bool bLastBlock = false;
345 nDataSize = it->size - nOffset;
346 if (nTopRow + nDataSize - 1 > nEnd)
348 // Truncate the block.
349 nDataSize = nEnd - nTopRow + 1;
350 bLastBlock = true;
353 if (it->type == BlkT::block_type)
354 EachElem<BlkT, typename BlkT::iterator>(*it, nOffset, nDataSize, rFuncElem);
355 else
356 rFuncElse(it->type, nTopRow, nDataSize);
358 if (bLastBlock)
359 break;
362 return it;
365 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
366 void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
368 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
369 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
370 for (; it != itEnd; ++it, nTopRow += nDataSize)
372 nDataSize = it->size;
373 switch (it->type)
375 case Blk1::block_type:
376 EachElem<Blk1, typename Blk1::iterator>(*it, rFuncElem);
377 break;
378 case Blk2::block_type:
379 EachElem<Blk2, typename Blk2::iterator>(*it, rFuncElem);
380 break;
381 default:
382 rFuncElse(it->type, nTopRow, nDataSize);
387 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
388 void ProcessElements2Reverse(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
390 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
391 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
392 for (; it != itEnd; ++it, nTopRow += nDataSize)
394 nDataSize = it->size;
395 switch (it->type)
397 case Blk1::block_type:
398 EachElemReverse<Blk1, typename Blk1::iterator>(*it, rFuncElem);
399 break;
400 case Blk2::block_type:
401 EachElemReverse<Blk2, typename Blk2::iterator>(*it, rFuncElem);
402 break;
403 default:
404 rFuncElse(it->type, nTopRow, nDataSize);
409 template<typename StoreT, typename Blk1, typename FuncElem, typename FuncElse>
410 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
411 FindElement1(
412 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
413 FuncElem& rFuncElem, FuncElse& rFuncElse)
415 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
416 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
418 PositionType aPos = rStore.position(nStart);
419 typename StoreT::const_iterator it = aPos.first;
420 typename StoreT::size_type nOffset = aPos.second;
421 typename StoreT::size_type nDataSize = 0;
422 typename StoreT::size_type nTopRow = nStart;
424 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
426 bool bLastBlock = false;
427 nDataSize = it->size - nOffset;
428 if (nTopRow + nDataSize - 1 > nEnd)
430 // Truncate the block.
431 nDataSize = nEnd - nTopRow + 1;
432 bLastBlock = true;
435 switch (it->type)
437 case Blk1::block_type:
439 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
440 if (aRet.first != rStore.end())
441 return aRet;
443 break;
444 default:
446 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
447 if (aRet.second)
448 return PositionType(it, aRet.first);
452 if (bLastBlock)
453 break;
456 return PositionType(rStore.end(), 0);
459 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
460 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
461 FindElement2(
462 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
463 FuncElem& rFuncElem, FuncElse& rFuncElse)
465 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
466 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
468 PositionType aPos = rStore.position(nStart);
469 typename StoreT::const_iterator it = aPos.first;
470 typename StoreT::size_type nOffset = aPos.second;
471 typename StoreT::size_type nDataSize = 0;
472 typename StoreT::size_type nTopRow = nStart;
474 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
476 bool bLastBlock = false;
477 nDataSize = it->size - nOffset;
478 if (nTopRow + nDataSize - 1 > nEnd)
480 // Truncate the block.
481 nDataSize = nEnd - nTopRow + 1;
482 bLastBlock = true;
485 switch (it->type)
487 case Blk1::block_type:
489 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
490 if (aRet.first != rStore.end())
491 return aRet;
493 break;
494 case Blk2::block_type:
496 PositionType aRet = CheckElem<Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
497 if (aRet.first != rStore.end())
498 return aRet;
500 break;
501 default:
503 ElseRetType aRet = rFuncElse(*it, nOffset, nDataSize);
504 if (aRet.second)
505 return PositionType(it, aRet.first);
509 if (bLastBlock)
510 break;
513 return PositionType(rStore.end(), 0);
518 #endif
520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */