Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sc / inc / mtvfunctions.hxx
blobf9052edfb27c4334dbccd3c042c312f4b2fb977a
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 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);
195 if (bLastBlock)
196 break;
199 return it;
202 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
203 typename StoreT::const_iterator
204 ParseElements2(
205 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
206 FuncElem& rFuncElem, FuncElse& rFuncElse)
208 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
210 PositionType aPos = rStore.position(itPos, nStart);
211 typename StoreT::const_iterator it = aPos.first;
212 typename StoreT::size_type nOffset = aPos.second;
213 typename StoreT::size_type nDataSize = 0;
214 typename StoreT::size_type nTopRow = nStart;
216 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
218 bool bLastBlock = false;
219 nDataSize = it->size - nOffset;
220 if (nTopRow + nDataSize - 1 > nEnd)
222 // Truncate the block.
223 nDataSize = nEnd - nTopRow + 1;
224 bLastBlock = true;
227 switch (it->type)
229 case Blk1::block_type:
230 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
231 break;
232 case Blk2::block_type:
233 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
234 break;
235 default:
236 rFuncElse(it->type, nTopRow, nDataSize);
239 if (bLastBlock)
240 break;
243 return it;
246 template<typename StoreT, typename Blk1, typename Blk2, typename Blk3, typename Blk4, typename FuncElem, typename FuncElse>
247 typename StoreT::const_iterator
248 ParseElements4(
249 const typename StoreT::const_iterator& itPos, const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
250 FuncElem& rFuncElem, FuncElse& rFuncElse)
252 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
254 PositionType aPos = rStore.position(itPos, nStart);
255 typename StoreT::const_iterator it = aPos.first;
256 typename StoreT::size_type nOffset = aPos.second;
257 typename StoreT::size_type nDataSize = 0;
258 typename StoreT::size_type nTopRow = nStart;
260 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
262 bool bLastBlock = false;
263 nDataSize = it->size - nOffset;
264 if (nTopRow + nDataSize - 1 > nEnd)
266 // Truncate the block.
267 nDataSize = nEnd - nTopRow + 1;
268 bLastBlock = true;
271 switch (it->type)
273 case Blk1::block_type:
274 EachElem<Blk1, typename Blk1::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
275 break;
276 case Blk2::block_type:
277 EachElem<Blk2, typename Blk2::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
278 break;
279 case Blk3::block_type:
280 EachElem<Blk3, typename Blk3::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
281 break;
282 case Blk4::block_type:
283 EachElem<Blk4, typename Blk4::const_iterator>(*it, nOffset, nDataSize, rFuncElem);
284 break;
285 default:
286 rFuncElse(it->type, nTopRow, nDataSize);
289 if (bLastBlock)
290 break;
293 return it;
296 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
297 void ProcessElements1(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
299 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
300 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
301 for (; it != itEnd; ++it, nTopRow += nDataSize)
303 nDataSize = it->size;
304 if (it->type != BlkT::block_type)
306 rFuncElse(it->type, nTopRow, nDataSize);
307 continue;
310 EachElem<BlkT, typename BlkT::iterator>(*it, rFuncElem);
315 * This variant specifies start and end positions.
317 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
318 typename StoreT::iterator
319 ProcessElements1(
320 const typename StoreT::iterator& itPos, StoreT& rStore,
321 typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
322 FuncElem& rFuncElem, FuncElse& rFuncElse)
324 typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
326 PositionType aPos = rStore.position(itPos, nStart);
327 typename StoreT::iterator it = aPos.first;
328 typename StoreT::size_type nOffset = aPos.second;
329 typename StoreT::size_type nDataSize = 0;
330 typename StoreT::size_type nTopRow = nStart;
332 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
334 bool bLastBlock = false;
335 nDataSize = it->size - nOffset;
336 if (nTopRow + nDataSize - 1 > nEnd)
338 // Truncate the block.
339 nDataSize = nEnd - nTopRow + 1;
340 bLastBlock = true;
343 if (it->type == BlkT::block_type)
344 EachElem<BlkT, typename BlkT::iterator>(*it, nOffset, nDataSize, rFuncElem);
345 else
346 rFuncElse(it->type, nTopRow, nDataSize);
348 if (bLastBlock)
349 break;
352 return it;
355 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
356 void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
358 typename StoreT::size_type nTopRow = 0, nDataSize = 0;
359 typename StoreT::iterator it = rStore.begin(), itEnd = rStore.end();
360 for (; it != itEnd; ++it, nTopRow += nDataSize)
362 nDataSize = it->size;
363 switch (it->type)
365 case Blk1::block_type:
366 EachElem<Blk1, typename Blk1::iterator>(*it, rFuncElem);
367 break;
368 case Blk2::block_type:
369 EachElem<Blk2, typename Blk2::iterator>(*it, rFuncElem);
370 break;
371 default:
372 rFuncElse(it->type, nTopRow, nDataSize);
377 template<typename StoreT, typename Blk1, typename FuncElem, typename FuncElse>
378 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
379 FindElement1(
380 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
381 FuncElem& rFuncElem, FuncElse& rFuncElse)
383 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
384 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
386 PositionType aPos = rStore.position(nStart);
387 typename StoreT::const_iterator it = aPos.first;
388 typename StoreT::size_type nOffset = aPos.second;
389 typename StoreT::size_type nDataSize = 0;
390 typename StoreT::size_type nTopRow = nStart;
392 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
394 bool bLastBlock = false;
395 nDataSize = it->size - nOffset;
396 if (nTopRow + nDataSize - 1 > nEnd)
398 // Truncate the block.
399 nDataSize = nEnd - nTopRow + 1;
400 bLastBlock = true;
403 switch (it->type)
405 case Blk1::block_type:
407 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
408 if (aRet.first != rStore.end())
409 return aRet;
411 break;
412 default:
414 ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
415 if (aRet.second)
416 return PositionType(it, aRet.first);
420 if (bLastBlock)
421 break;
424 return PositionType(rStore.end(), 0);
427 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
428 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
429 FindElement2(
430 const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
431 FuncElem& rFuncElem, FuncElse& rFuncElse)
433 typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
434 typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
436 PositionType aPos = rStore.position(nStart);
437 typename StoreT::const_iterator it = aPos.first;
438 typename StoreT::size_type nOffset = aPos.second;
439 typename StoreT::size_type nDataSize = 0;
440 typename StoreT::size_type nTopRow = nStart;
442 for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
444 bool bLastBlock = false;
445 nDataSize = it->size - nOffset;
446 if (nTopRow + nDataSize - 1 > nEnd)
448 // Truncate the block.
449 nDataSize = nEnd - nTopRow + 1;
450 bLastBlock = true;
453 switch (it->type)
455 case Blk1::block_type:
457 PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
458 if (aRet.first != rStore.end())
459 return aRet;
461 break;
462 case Blk2::block_type:
464 PositionType aRet = CheckElem<Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
465 if (aRet.first != rStore.end())
466 return aRet;
468 break;
469 default:
471 ElseRetType aRet = rFuncElse(*it, nOffset, nDataSize);
472 if (aRet.second)
473 return PositionType(it, aRet.first);
477 if (bLastBlock)
478 break;
481 return PositionType(rStore.end(), 0);
486 #endif
488 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */