ofz: Use-of-uninitialized-value
[LibreOffice.git] / sc / inc / mtvfunctions.hxx
blob854ca42c37fc0100d0123c170b64c1e95141a508
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 #pragma once
12 #include <cstdlib>
13 #include <mdds/multi_type_vector_types.hpp>
15 namespace sc {
17 template<typename SizeT, typename Ret = bool>
18 struct FuncElseNoOp
20 Ret operator() (mdds::mtv::element_t, SizeT, SizeT) const
22 return Ret();
26 /**
27 * Generic algorithm to parse blocks of multi_type_vector either partially
28 * or fully.
30 template<typename StoreT, typename Func>
31 typename StoreT::const_iterator
32 ParseBlock(
33 const typename StoreT::const_iterator& itPos, const StoreT& rStore, Func& rFunc,
34 typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
36 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
38 PositionType aPos = rStore.position(itPos, nStart);
39 typename StoreT::const_iterator it = aPos.first;
40 typename StoreT::size_type nOffset = aPos.second;
41 typename StoreT::size_type nDataSize = 0;
42 typename StoreT::size_type nTopRow = nStart;
44 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
46 bool bLastBlock = false;
47 nDataSize = it->size - nOffset;
48 if (nTopRow + nDataSize - 1 > nEnd)
50 // Truncate the block.
51 nDataSize = nEnd - nTopRow + 1;
52 bLastBlock = true;
55 rFunc(*it, nOffset, nDataSize);
57 if (bLastBlock)
58 break;
61 return it;
64 /**
65 * Non-const variant of the above function. TODO: Find a way to merge these
66 * two in an elegant way.
68 template<typename StoreT, typename Func>
69 typename StoreT::iterator
70 ProcessBlock(const typename StoreT::iterator& itPos, StoreT& rStore, Func& rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
72 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
74 PositionType aPos = rStore.position(itPos, nStart);
75 typename StoreT::iterator it = aPos.first;
76 typename StoreT::size_type nOffset = aPos.second;
77 typename StoreT::size_type nDataSize = 0;
78 typename StoreT::size_type nCurRow = nStart;
80 for (; it != rStore.end() && nCurRow <= nEnd; ++it, nOffset = 0, nCurRow += nDataSize)
82 bool bLastBlock = false;
83 nDataSize = it->size - nOffset;
84 if (nCurRow + nDataSize - 1 > nEnd)
86 // Truncate the block.
87 nDataSize = nEnd - nCurRow + 1;
88 bLastBlock = true;
91 rFunc(*it, nOffset, nDataSize);
93 if (bLastBlock)
94 break;
97 return it;
100 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
101 void EachElem(NodeT& rNode, size_t nOffset, size_t nDataSize, FuncElem& rFuncElem)
103 ItrT it = BlkT::begin(*rNode.data);
104 std::advance(it, nOffset);
105 ItrT itEnd = it;
106 std::advance(itEnd, nDataSize);
107 size_t nRow = rNode.position + nOffset;
108 for (; it != itEnd; ++it, ++nRow)
109 rFuncElem(nRow, *it);
112 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
113 void EachElem(NodeT& rNode, FuncElem& rFuncElem)
115 auto it = BlkT::begin(*rNode.data);
116 auto itEnd = BlkT::end(*rNode.data);
117 size_t nRow = rNode.position;
118 for (; it != itEnd; ++it, ++nRow)
119 rFuncElem(nRow, *it);
122 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
123 void EachElemReverse(NodeT& rNode, FuncElem& rFuncElem)
125 auto it = BlkT::rbegin(*rNode.data);
126 auto itEnd = BlkT::rend(*rNode.data);
127 size_t nRow = rNode.position;
128 for (; it != itEnd; ++it, ++nRow)
129 rFuncElem(nRow, *it);
132 template<typename BlkT, typename StoreT, typename FuncElem>
133 std::pair<typename StoreT::const_iterator, size_t>
134 CheckElem(
135 const StoreT& rStore, const typename StoreT::const_iterator& it, size_t nOffset, size_t nDataSize,
136 FuncElem& rFuncElem)
138 typedef std::pair<typename StoreT::const_iterator, size_t> PositionType;
140 typename BlkT::const_iterator itData = BlkT::begin(*it->data);
141 std::advance(itData, nOffset);
142 typename BlkT::const_iterator itDataEnd = itData;
143 std::advance(itDataEnd, nDataSize);
144 size_t nTopRow = it->position + nOffset;
145 size_t nRow = nTopRow;
146 for (; itData != itDataEnd; ++itData, ++nRow)
148 if (rFuncElem(nRow, *itData))
149 return PositionType(it, nRow - it->position);
152 return PositionType(rStore.end(), 0);
155 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
156 void ParseElements1(const StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
158 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
159 typename StoreT::const_iterator it = rStore.begin(), itEnd = rStore.end();
160 for (; it != itEnd; ++it, nTopRow += nDataSize)
162 nDataSize = it->size;
163 if (it->type != BlkT::block_type)
165 rFuncElse(it->type, nTopRow, nDataSize);
166 continue;
169 EachElem<BlkT, typename BlkT::const_iterator>(*it, rFuncElem);
173 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
174 typename StoreT::const_iterator
175 ParseElements1(
176 const typename StoreT::const_iterator& itPos, const StoreT& rStore,
177 typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
178 FuncElem& rFuncElem, FuncElse& rFuncElse)
180 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
182 PositionType aPos = rStore.position(itPos, nStart);
183 typename StoreT::const_iterator it = aPos.first;
184 typename StoreT::size_type nOffset = aPos.second;
185 typename StoreT::size_type nDataSize = 0;
186 typename StoreT::size_type nTopRow = nStart;
188 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
190 bool bLastBlock = false;
191 nDataSize = it->size - nOffset;
192 if (nTopRow + nDataSize - 1 > nEnd)
194 // Truncate the block.
195 nDataSize = nEnd - nTopRow + 1;
196 bLastBlock = true;
199 if (it->type == BlkT::block_type)
200 EachElem<BlkT, typename BlkT::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
201 else
202 rFuncElse(it->type, nTopRow, nDataSize);
204 if (bLastBlock)
205 break;
208 return it;
211 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
212 typename StoreT::const_iterator
213 ParseElements2(
214 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
215 FuncElem& rFuncElem, FuncElse& rFuncElse)
217 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
219 PositionType aPos = rStore.position(itPos, nStart);
220 typename StoreT::const_iterator it = aPos.first;
221 typename StoreT::size_type nOffset = aPos.second;
222 typename StoreT::size_type nDataSize = 0;
223 typename StoreT::size_type nTopRow = nStart;
225 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
227 bool bLastBlock = false;
228 nDataSize = it->size - nOffset;
229 if (nTopRow + nDataSize - 1 > nEnd)
231 // Truncate the block.
232 nDataSize = nEnd - nTopRow + 1;
233 bLastBlock = true;
236 switch (it->type)
238 case Blk1::block_type:
239 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
240 break;
241 case Blk2::block_type:
242 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
243 break;
244 default:
245 rFuncElse(it->type, nTopRow, nDataSize);
248 if (bLastBlock)
249 break;
252 return it;
255 template<typename StoreT, typename Blk1, typename Blk2, typename Blk3, typename Blk4, typename FuncElem, typename FuncElse>
256 typename StoreT::const_iterator
257 ParseElements4(
258 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
259 FuncElem& rFuncElem, FuncElse& rFuncElse)
261 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
263 PositionType aPos = rStore.position(itPos, nStart);
264 typename StoreT::const_iterator it = aPos.first;
265 typename StoreT::size_type nOffset = aPos.second;
266 typename StoreT::size_type nDataSize = 0;
267 typename StoreT::size_type nTopRow = nStart;
269 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
271 bool bLastBlock = false;
272 nDataSize = it->size - nOffset;
273 if (nTopRow + nDataSize - 1 > nEnd)
275 // Truncate the block.
276 nDataSize = nEnd - nTopRow + 1;
277 bLastBlock = true;
280 switch (it->type)
282 case Blk1::block_type:
283 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
284 break;
285 case Blk2::block_type:
286 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
287 break;
288 case Blk3::block_type:
289 EachElem<Blk3, typename Blk3::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
290 break;
291 case Blk4::block_type:
292 EachElem<Blk4, typename Blk4::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
293 break;
294 default:
295 rFuncElse(it->type, nTopRow, nDataSize);
298 if (bLastBlock)
299 break;
302 return it;
305 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
306 void ProcessElements1(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
308 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
309 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
310 for (; it != itEnd; ++it, nTopRow += nDataSize)
312 nDataSize = it->size;
313 if (it->type != BlkT::block_type)
315 rFuncElse(it->type, nTopRow, nDataSize);
316 continue;
319 EachElem<BlkT, typename BlkT::iterator>(*it, rFuncElem);
324 * This variant specifies start and end positions.
326 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
327 typename StoreT::iterator
328 ProcessElements1(
329 const typename StoreT::iterator& itPos, StoreT& rStore,
330 typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
331 FuncElem& rFuncElem, FuncElse& rFuncElse)
333 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
335 PositionType aPos = rStore.position(itPos, nStart);
336 typename StoreT::iterator it = aPos.first;
337 typename StoreT::size_type nOffset = aPos.second;
338 typename StoreT::size_type nDataSize = 0;
339 typename StoreT::size_type nTopRow = nStart;
341 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
343 bool bLastBlock = false;
344 nDataSize = it->size - nOffset;
345 if (nTopRow + nDataSize - 1 > nEnd)
347 // Truncate the block.
348 nDataSize = nEnd - nTopRow + 1;
349 bLastBlock = true;
352 if (it->type == BlkT::block_type)
353 EachElem<BlkT, typename BlkT::iterator>(*it, nOffset, nDataSize, rFuncElem);
354 else
355 rFuncElse(it->type, nTopRow, nDataSize);
357 if (bLastBlock)
358 break;
361 return it;
364 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
365 void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
367 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
368 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
369 for (; it != itEnd; ++it, nTopRow += nDataSize)
371 nDataSize = it->size;
372 switch (it->type)
374 case Blk1::block_type:
375 EachElem<Blk1, typename Blk1::iterator>(*it, rFuncElem);
376 break;
377 case Blk2::block_type:
378 EachElem<Blk2, typename Blk2::iterator>(*it, rFuncElem);
379 break;
380 default:
381 rFuncElse(it->type, nTopRow, nDataSize);
386 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
387 void ProcessElements2Reverse(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
389 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
390 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
391 for (; it != itEnd; ++it, nTopRow += nDataSize)
393 nDataSize = it->size;
394 switch (it->type)
396 case Blk1::block_type:
397 EachElemReverse<Blk1, typename Blk1::iterator>(*it, rFuncElem);
398 break;
399 case Blk2::block_type:
400 EachElemReverse<Blk2, typename Blk2::iterator>(*it, rFuncElem);
401 break;
402 default:
403 rFuncElse(it->type, nTopRow, nDataSize);
408 template<typename StoreT, typename Blk1, typename FuncElem, typename FuncElse>
409 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
410 FindElement1(
411 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
412 FuncElem& rFuncElem, FuncElse& rFuncElse)
414 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
415 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
417 PositionType aPos = rStore.position(nStart);
418 typename StoreT::const_iterator it = aPos.first;
419 typename StoreT::size_type nOffset = aPos.second;
420 typename StoreT::size_type nDataSize = 0;
421 typename StoreT::size_type nTopRow = nStart;
423 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
425 bool bLastBlock = false;
426 nDataSize = it->size - nOffset;
427 if (nTopRow + nDataSize - 1 > nEnd)
429 // Truncate the block.
430 nDataSize = nEnd - nTopRow + 1;
431 bLastBlock = true;
434 switch (it->type)
436 case Blk1::block_type:
438 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
439 if (aRet.first != rStore.end())
440 return aRet;
442 break;
443 default:
445 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
446 if (aRet.second)
447 return PositionType(it, aRet.first);
451 if (bLastBlock)
452 break;
455 return PositionType(rStore.end(), 0);
458 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
459 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
460 FindElement2(
461 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
462 FuncElem& rFuncElem, FuncElse& rFuncElse)
464 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
465 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
467 PositionType aPos = rStore.position(nStart);
468 typename StoreT::const_iterator it = aPos.first;
469 typename StoreT::size_type nOffset = aPos.second;
470 typename StoreT::size_type nDataSize = 0;
471 typename StoreT::size_type nTopRow = nStart;
473 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
475 bool bLastBlock = false;
476 nDataSize = it->size - nOffset;
477 if (nTopRow + nDataSize - 1 > nEnd)
479 // Truncate the block.
480 nDataSize = nEnd - nTopRow + 1;
481 bLastBlock = true;
484 switch (it->type)
486 case Blk1::block_type:
488 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
489 if (aRet.first != rStore.end())
490 return aRet;
492 break;
493 case Blk2::block_type:
495 PositionType aRet = CheckElem<Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
496 if (aRet.first != rStore.end())
497 return aRet;
499 break;
500 default:
502 ElseRetType aRet = rFuncElse(*it, nOffset, nDataSize);
503 if (aRet.second)
504 return PositionType(it, aRet.first);
508 if (bLastBlock)
509 break;
512 return PositionType(rStore.end(), 0);
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */