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 
15 namespace sc {
16 
17 template<typename SizeT, typename Ret = bool>
19 {
20  Ret operator() (mdds::mtv::element_t, SizeT, SizeT) const
21  {
22  return Ret();
23  }
24 };
25 
30 template<typename StoreT, typename Func>
31 typename StoreT::const_iterator
33  const typename StoreT::const_iterator& itPos, const StoreT& rStore, Func& rFunc,
34  typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
35 {
36  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
37 
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;
43 
44  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
45  {
46  bool bLastBlock = false;
47  nDataSize = it->size - nOffset;
48  if (nTopRow + nDataSize - 1 > nEnd)
49  {
50  // Truncate the block.
51  nDataSize = nEnd - nTopRow + 1;
52  bLastBlock = true;
53  }
54 
55  rFunc(*it, nOffset, nDataSize);
56 
57  if (bLastBlock)
58  break;
59  }
60 
61  return it;
62 }
63 
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)
71 {
72  typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
73 
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;
79 
80  for (; it != rStore.end() && nCurRow <= nEnd; ++it, nOffset = 0, nCurRow += nDataSize)
81  {
82  bool bLastBlock = false;
83  nDataSize = it->size - nOffset;
84  if (nCurRow + nDataSize - 1 > nEnd)
85  {
86  // Truncate the block.
87  nDataSize = nEnd - nCurRow + 1;
88  bLastBlock = true;
89  }
90 
91  rFunc(*it, nOffset, nDataSize);
92 
93  if (bLastBlock)
94  break;
95  }
96 
97  return it;
98 }
99 
100 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
101 void EachElem(NodeT& rNode, size_t nOffset, size_t nDataSize, FuncElem& rFuncElem)
102 {
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);
110 }
111 
112 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
113 void EachElem(NodeT& rNode, FuncElem& rFuncElem)
114 {
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);
120 }
121 
122 template<typename BlkT, typename ItrT, typename NodeT, typename FuncElem>
123 void EachElemReverse(NodeT& rNode, FuncElem& rFuncElem)
124 {
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);
130 }
131 
132 template<typename BlkT, typename StoreT, typename FuncElem>
133 std::pair<typename StoreT::const_iterator, size_t>
135  const StoreT& rStore, const typename StoreT::const_iterator& it, size_t nOffset, size_t nDataSize,
136  FuncElem& rFuncElem)
137 {
138  typedef std::pair<typename StoreT::const_iterator, size_t> PositionType;
139 
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)
147  {
148  if (rFuncElem(nRow, *itData))
149  return PositionType(it, nRow - it->position);
150  }
151 
152  return PositionType(rStore.end(), 0);
153 }
154 
155 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
156 void ParseElements1(const StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
157 {
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)
161  {
162  nDataSize = it->size;
163  if (it->type != BlkT::block_type)
164  {
165  rFuncElse(it->type, nTopRow, nDataSize);
166  continue;
167  }
168 
169  EachElem<BlkT, typename BlkT::const_iterator>(*it, rFuncElem);
170  }
171 }
172 
173 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
174 typename StoreT::const_iterator
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)
179 {
180  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
181 
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;
187 
188  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
189  {
190  bool bLastBlock = false;
191  nDataSize = it->size - nOffset;
192  if (nTopRow + nDataSize - 1 > nEnd)
193  {
194  // Truncate the block.
195  nDataSize = nEnd - nTopRow + 1;
196  bLastBlock = true;
197  }
198 
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);
203 
204  if (bLastBlock)
205  break;
206  }
207 
208  return it;
209 };
210 
211 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
212 typename StoreT::const_iterator
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)
216 {
217  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
218 
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;
224 
225  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
226  {
227  bool bLastBlock = false;
228  nDataSize = it->size - nOffset;
229  if (nTopRow + nDataSize - 1 > nEnd)
230  {
231  // Truncate the block.
232  nDataSize = nEnd - nTopRow + 1;
233  bLastBlock = true;
234  }
235 
236  switch (it->type)
237  {
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);
246  }
247 
248  if (bLastBlock)
249  break;
250  }
251 
252  return it;
253 }
254 
255 template<typename StoreT, typename Blk1, typename Blk2, typename Blk3, typename Blk4, typename FuncElem, typename FuncElse>
256 typename StoreT::const_iterator
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)
260 {
261  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
262 
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;
268 
269  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
270  {
271  bool bLastBlock = false;
272  nDataSize = it->size - nOffset;
273  if (nTopRow + nDataSize - 1 > nEnd)
274  {
275  // Truncate the block.
276  nDataSize = nEnd - nTopRow + 1;
277  bLastBlock = true;
278  }
279 
280  switch (it->type)
281  {
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);
296  }
297 
298  if (bLastBlock)
299  break;
300  }
301 
302  return it;
303 }
304 
305 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
306 void ProcessElements1(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
307 {
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)
311  {
312  nDataSize = it->size;
313  if (it->type != BlkT::block_type)
314  {
315  rFuncElse(it->type, nTopRow, nDataSize);
316  continue;
317  }
318 
319  EachElem<BlkT, typename BlkT::iterator>(*it, rFuncElem);
320  }
321 }
322 
326 template<typename StoreT, typename BlkT, typename FuncElem, typename FuncElse>
327 typename StoreT::iterator
329  const typename StoreT::iterator& itPos, StoreT& rStore,
330  typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
331  FuncElem& rFuncElem, FuncElse& rFuncElse)
332 {
333  typedef std::pair<typename StoreT::iterator, typename StoreT::size_type> PositionType;
334 
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;
340 
341  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
342  {
343  bool bLastBlock = false;
344  nDataSize = it->size - nOffset;
345  if (nTopRow + nDataSize - 1 > nEnd)
346  {
347  // Truncate the block.
348  nDataSize = nEnd - nTopRow + 1;
349  bLastBlock = true;
350  }
351 
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);
356 
357  if (bLastBlock)
358  break;
359  }
360 
361  return it;
362 };
363 
364 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
365 void ProcessElements2(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
366 {
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)
370  {
371  nDataSize = it->size;
372  switch (it->type)
373  {
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);
382  }
383  }
384 }
385 
386 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
387 void ProcessElements2Reverse(StoreT& rStore, FuncElem& rFuncElem, FuncElse& rFuncElse)
388 {
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)
392  {
393  nDataSize = it->size;
394  switch (it->type)
395  {
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);
404  }
405  }
406 }
407 
408 template<typename StoreT, typename Blk1, typename FuncElem, typename FuncElse>
409 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
411  const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
412  FuncElem& rFuncElem, FuncElse& rFuncElse)
413 {
414  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
415  typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
416 
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;
422 
423  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
424  {
425  bool bLastBlock = false;
426  nDataSize = it->size - nOffset;
427  if (nTopRow + nDataSize - 1 > nEnd)
428  {
429  // Truncate the block.
430  nDataSize = nEnd - nTopRow + 1;
431  bLastBlock = true;
432  }
433 
434  switch (it->type)
435  {
436  case Blk1::block_type:
437  {
438  PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
439  if (aRet.first != rStore.end())
440  return aRet;
441  }
442  break;
443  default:
444  {
445  ElseRetType aRet = rFuncElse(it->type, nTopRow, nDataSize);
446  if (aRet.second)
447  return PositionType(it, aRet.first);
448  }
449  }
450 
451  if (bLastBlock)
452  break;
453  }
454 
455  return PositionType(rStore.end(), 0);
456 }
457 
458 template<typename StoreT, typename Blk1, typename Blk2, typename FuncElem, typename FuncElse>
459 std::pair<typename StoreT::const_iterator, typename StoreT::size_type>
461  const StoreT& rStore, typename StoreT::size_type nStart, typename StoreT::size_type nEnd,
462  FuncElem& rFuncElem, FuncElse& rFuncElse)
463 {
464  typedef std::pair<typename StoreT::const_iterator, typename StoreT::size_type> PositionType;
465  typedef std::pair<typename StoreT::size_type, bool> ElseRetType;
466 
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;
472 
473  for (; it != rStore.end() && nTopRow <= nEnd; ++it, nOffset = 0, nTopRow += nDataSize)
474  {
475  bool bLastBlock = false;
476  nDataSize = it->size - nOffset;
477  if (nTopRow + nDataSize - 1 > nEnd)
478  {
479  // Truncate the block.
480  nDataSize = nEnd - nTopRow + 1;
481  bLastBlock = true;
482  }
483 
484  switch (it->type)
485  {
486  case Blk1::block_type:
487  {
488  PositionType aRet = CheckElem<Blk1>(rStore, it, nOffset, nDataSize, rFuncElem);
489  if (aRet.first != rStore.end())
490  return aRet;
491  }
492  break;
493  case Blk2::block_type:
494  {
495  PositionType aRet = CheckElem<Blk2>(rStore, it, nOffset, nDataSize, rFuncElem);
496  if (aRet.first != rStore.end())
497  return aRet;
498  }
499  break;
500  default:
501  {
502  ElseRetType aRet = rFuncElse(*it, nOffset, nDataSize);
503  if (aRet.second)
504  return PositionType(it, aRet.first);
505  }
506  }
507 
508  if (bLastBlock)
509  break;
510  }
511 
512  return PositionType(rStore.end(), 0);
513 }
514 
515 }
516 
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ProcessElements2Reverse(StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
Ret operator()(mdds::mtv::element_t, SizeT, SizeT) const
void EachElem(NodeT &rNode, size_t nOffset, size_t nDataSize, FuncElem &rFuncElem)
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. ...
void ProcessElements2(StoreT &rStore, 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.
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)
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)
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)
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::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)
void ProcessElements1(StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
void ParseElements1(const StoreT &rStore, FuncElem &rFuncElem, FuncElse &rFuncElse)
void EachElemReverse(NodeT &rNode, FuncElem &rFuncElem)