1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <segmenttree.hxx>
21 #include <o3tl/safeint.hxx>
22 #include <mdds/flat_segment_tree.hpp>
23 #include <sal/log.hxx>
26 #include <string_view>
28 #include <rtl/strbuf.hxx>
30 using ::std::numeric_limits
;
34 template<typename ValueType_
, typename ExtValueType_
= ValueType_
>
35 class ScFlatSegmentsImpl
38 typedef ValueType_ ValueType
;
39 typedef ExtValueType_ ExtValueType
;
48 ScFlatSegmentsImpl(SCCOLROW nMax
, ValueType nDefault
);
49 ScFlatSegmentsImpl(const ScFlatSegmentsImpl
& r
);
51 bool setValue(SCCOLROW nPos1
, SCCOLROW nPos2
, ValueType nValue
);
52 void setValueIf(SCCOLROW nPos1
, SCCOLROW nPos2
, ValueType nValue
, const std::function
<bool(ValueType
)>& rPredicate
);
53 ValueType
getValue(SCCOLROW nPos
);
54 sal_uInt64
getSumValue(SCCOLROW nPos1
, SCCOLROW nPos2
);
55 bool getRangeData(SCCOLROW nPos
, RangeData
& rData
);
56 bool getRangeDataLeaf(SCCOLROW nPos
, RangeData
& rData
);
57 void removeSegment(SCCOLROW nPos1
, SCCOLROW nPos2
);
58 void insertSegment(SCCOLROW nPos
, SCCOLROW nSize
, bool bSkipStartBoundary
);
60 SCCOLROW
findLastTrue(ValueType nValue
) const;
63 bool getFirst(RangeData
& rData
);
64 bool getNext(RangeData
& rData
);
66 void enableTreeSearch(bool b
)
68 mbTreeSearchEnabled
= b
;
74 typedef ::mdds::flat_segment_tree
<SCCOLROW
, ValueType
> fst_type
;
76 typename
fst_type::const_iterator maItr
;
78 bool mbTreeSearchEnabled
:1;
83 template<typename ValueType_
, typename ExtValueType_
>
84 ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::ScFlatSegmentsImpl(SCCOLROW nMax
, ValueType nDefault
) :
85 maSegments(0, nMax
+1, nDefault
),
86 mbTreeSearchEnabled(true)
90 template<typename ValueType_
, typename ExtValueType_
>
91 ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::ScFlatSegmentsImpl(const ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>& r
) :
92 maSegments(r
.maSegments
),
93 mbTreeSearchEnabled(r
.mbTreeSearchEnabled
)
97 template<typename ValueType_
, typename ExtValueType_
>
98 bool ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::setValue(SCCOLROW nPos1
, SCCOLROW nPos2
, ValueType nValue
)
100 ::std::pair
<typename
fst_type::const_iterator
, bool> ret
;
101 ret
= maSegments
.insert(maItr
, nPos1
, nPos2
+1, nValue
);
106 template<typename ValueType_
, typename ExtValueType_
>
107 void ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::setValueIf(SCCOLROW nPos1
, SCCOLROW nPos2
,
108 ValueType nValue
, const std::function
<bool(ValueType
)>& rPredicate
)
110 SCCOLROW nCurrentStartRow
= nPos1
;
111 while (nCurrentStartRow
<= nPos2
)
113 RangeData aRangeData
;
114 getRangeData(nCurrentStartRow
, aRangeData
);
115 if (rPredicate(aRangeData
.mnValue
))
117 // set value from current iteration point on, til end of range.
118 // Note that aRangeData may well contain much lower values for nPos1
119 setValue(nCurrentStartRow
, std::min
<SCCOLROW
>(nPos2
, aRangeData
.mnPos2
), nValue
);
122 // even if nPos2 is bigger than nPos2 this should terminate the loop
123 nCurrentStartRow
= aRangeData
.mnPos2
+ 1;
127 template<typename ValueType_
, typename ExtValueType_
>
128 typename ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::ValueType ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getValue(SCCOLROW nPos
)
130 ValueType nValue
= 0;
131 if (!mbTreeSearchEnabled
)
133 maSegments
.search(nPos
, nValue
);
137 if (!maSegments
.is_tree_valid())
139 assert(!ScGlobal::bThreadedGroupCalcInProgress
);
140 maSegments
.build_tree();
143 maSegments
.search_tree(nPos
, nValue
);
147 template<typename ValueType_
, typename ExtValueType_
>
148 sal_uInt64 ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getSumValue(SCCOLROW nPos1
, SCCOLROW nPos2
)
150 if (mbTreeSearchEnabled
)
153 if (!maSegments
.is_tree_valid())
155 assert(!ScGlobal::bThreadedGroupCalcInProgress
);
156 maSegments
.build_tree();
160 auto [it
, found
] = maSegments
.search_tree(nPos1
, aData
.mnValue
, &aData
.mnPos1
, &aData
.mnPos2
);
163 aData
.mnPos2
= aData
.mnPos2
-1; // end point is not inclusive.
165 sal_uInt64 nValue
= 0;
167 SCROW nCurPos
= nPos1
;
168 SCROW nEndPos
= aData
.mnPos2
;
169 while (nEndPos
<= nPos2
)
172 if (o3tl::checked_multiply
<sal_uInt64
>(aData
.mnValue
, nEndPos
- nCurPos
+ 1, nRes
))
174 SAL_WARN("sc.core", "row height overflow");
175 nRes
= SAL_MAX_INT64
;
177 nValue
= o3tl::saturating_add(nValue
, nRes
);
178 nCurPos
= nEndPos
+ 1;
179 auto itPair
= maSegments
.search(it
, nCurPos
, aData
.mnValue
, &aData
.mnPos1
, &aData
.mnPos2
);
183 aData
.mnPos2
= aData
.mnPos2
-1; // end point is not inclusive.
184 nEndPos
= aData
.mnPos2
;
186 if (nCurPos
<= nPos2
)
188 nEndPos
= ::std::min(nEndPos
, nPos2
);
190 if (o3tl::checked_multiply
<sal_uInt64
>(aData
.mnValue
, nEndPos
- nCurPos
+ 1, nRes
))
192 SAL_WARN("sc.core", "row height overflow");
193 nRes
= SAL_MAX_INT64
;
195 nValue
= o3tl::saturating_add(nValue
, nRes
);
202 if (!getRangeDataLeaf(nPos1
, aData
))
205 sal_uInt64 nValue
= 0;
207 SCROW nCurPos
= nPos1
;
208 SCROW nEndPos
= aData
.mnPos2
;
209 while (nEndPos
<= nPos2
)
212 if (o3tl::checked_multiply
<sal_uInt64
>(aData
.mnValue
, nEndPos
- nCurPos
+ 1, nRes
))
214 SAL_WARN("sc.core", "row height overflow");
215 nRes
= SAL_MAX_INT64
;
217 nValue
= o3tl::saturating_add(nValue
, nRes
);
218 nCurPos
= nEndPos
+ 1;
219 if (!getRangeDataLeaf(nCurPos
, aData
))
222 nEndPos
= aData
.mnPos2
;
224 if (nCurPos
<= nPos2
)
226 nEndPos
= ::std::min(nEndPos
, nPos2
);
228 if (o3tl::checked_multiply
<sal_uInt64
>(aData
.mnValue
, nEndPos
- nCurPos
+ 1, nRes
))
230 SAL_WARN("sc.core", "row height overflow");
231 nRes
= SAL_MAX_INT64
;
233 nValue
= o3tl::saturating_add(nValue
, nRes
);
239 template<typename ValueType_
, typename ExtValueType_
>
240 bool ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getRangeData(SCCOLROW nPos
, RangeData
& rData
)
242 if (!mbTreeSearchEnabled
)
243 return getRangeDataLeaf(nPos
, rData
);
245 if (!maSegments
.is_tree_valid())
247 assert(!ScGlobal::bThreadedGroupCalcInProgress
);
248 maSegments
.build_tree();
251 auto [it
,found
] = maSegments
.search_tree(nPos
, rData
.mnValue
, &rData
.mnPos1
, &rData
.mnPos2
);
254 maItr
= std::move(it
); // cache the iterator to speed up ForwardIterator.
255 rData
.mnPos2
= rData
.mnPos2
-1; // end point is not inclusive.
259 template<typename ValueType_
, typename ExtValueType_
>
260 bool ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getRangeDataLeaf(SCCOLROW nPos
, RangeData
& rData
)
262 // Conduct leaf-node only search. Faster when searching between range insertion.
263 const ::std::pair
<typename
fst_type::const_iterator
, bool> &ret
=
264 maSegments
.search(maItr
, nPos
, rData
.mnValue
, &rData
.mnPos1
, &rData
.mnPos2
);
271 rData
.mnPos2
= rData
.mnPos2
-1; // end point is not inclusive.
275 template<typename ValueType_
, typename ExtValueType_
>
276 void ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::removeSegment(SCCOLROW nPos1
, SCCOLROW nPos2
)
278 maSegments
.shift_left(nPos1
, nPos2
);
279 maItr
= maSegments
.begin();
282 template<typename ValueType_
, typename ExtValueType_
>
283 void ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::insertSegment(SCCOLROW nPos
, SCCOLROW nSize
, bool bSkipStartBoundary
)
285 maSegments
.shift_right(nPos
, nSize
, bSkipStartBoundary
);
286 maItr
= maSegments
.begin();
289 template<typename ValueType_
, typename ExtValueType_
>
290 SCCOLROW ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::findLastTrue(ValueType nValue
) const
292 SCCOLROW nPos
= numeric_limits
<SCCOLROW
>::max(); // position not found.
293 typename
fst_type::const_reverse_iterator itr
= maSegments
.rbegin(), itrEnd
= maSegments
.rend();
294 // Note that when searching in reverse direction, we need to skip the first
295 // node, since the right-most leaf node does not store a valid value.
296 for (++itr
; itr
!= itrEnd
; ++itr
)
298 if (itr
->second
!= nValue
)
300 nPos
= (--itr
)->first
- 1;
307 template<typename ValueType_
, typename ExtValueType_
>
308 bool ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getFirst(RangeData
& rData
)
310 maItr
= maSegments
.begin();
311 return getNext(rData
);
314 template<typename ValueType_
, typename ExtValueType_
>
315 bool ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::getNext(RangeData
& rData
)
317 typename
fst_type::const_iterator itrEnd
= maSegments
.end();
321 rData
.mnPos1
= maItr
->first
;
322 rData
.mnValue
= maItr
->second
;
328 rData
.mnPos2
= maItr
->first
- 1;
332 template<typename ValueType_
, typename ExtValueType_
>
333 void ScFlatSegmentsImpl
<ValueType_
, ExtValueType_
>::makeReady()
335 assert(!ScGlobal::bThreadedGroupCalcInProgress
);
336 if (!maSegments
.is_tree_valid())
337 maSegments
.build_tree();
340 class ScFlatUInt16SegmentsImpl
: public ScFlatSegmentsImpl
<sal_uInt16
, sal_uInt32
>
343 explicit ScFlatUInt16SegmentsImpl(SCCOLROW nMax
, sal_uInt16 nDefault
) :
344 ScFlatSegmentsImpl
<sal_uInt16
, sal_uInt32
>(nMax
, nDefault
)
349 class ScFlatBoolSegmentsImpl
: public ScFlatSegmentsImpl
<bool>
352 explicit ScFlatBoolSegmentsImpl(SCCOLROW nMax
) :
353 ScFlatSegmentsImpl
<bool>(nMax
, false)
357 bool setTrue(SCCOLROW nPos1
, SCCOLROW nPos2
);
358 bool setFalse(SCCOLROW nPos1
, SCCOLROW nPos2
);
361 bool ScFlatBoolSegmentsImpl::setTrue(SCCOLROW nPos1
, SCCOLROW nPos2
)
363 return setValue(nPos1
, nPos2
, true);
366 bool ScFlatBoolSegmentsImpl::setFalse(SCCOLROW nPos1
, SCCOLROW nPos2
)
368 return setValue(nPos1
, nPos2
, false);
371 ScFlatBoolRowSegments::ForwardIterator::ForwardIterator(ScFlatBoolRowSegments
& rSegs
) :
372 mrSegs(rSegs
), mnCurPos(0), mnLastPos(-1), mbCurValue(false)
376 bool ScFlatBoolRowSegments::ForwardIterator::getValue(SCROW nPos
, bool& rVal
)
378 if (nPos
>= mnCurPos
)
379 // It can only go in a forward direction.
382 if (mnCurPos
> mnLastPos
)
384 // position not in the current segment. Update the current value.
385 ScFlatBoolRowSegments::RangeData aData
;
386 if (!mrSegs
.getRangeData(mnCurPos
, aData
))
389 mbCurValue
= aData
.mbValue
;
390 mnLastPos
= aData
.mnRow2
;
397 ScFlatBoolRowSegments::RangeIterator::RangeIterator(ScFlatBoolRowSegments
const & rSegs
) :
402 bool ScFlatBoolRowSegments::RangeIterator::getFirst(RangeData
& rRange
)
404 ScFlatBoolSegmentsImpl::RangeData aData
;
405 if (!mrSegs
.mpImpl
->getFirst(aData
))
408 rRange
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
409 rRange
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
410 rRange
.mbValue
= static_cast<bool>(aData
.mnValue
);
414 bool ScFlatBoolRowSegments::RangeIterator::getNext(RangeData
& rRange
)
416 ScFlatBoolSegmentsImpl::RangeData aData
;
417 if (!mrSegs
.mpImpl
->getNext(aData
))
420 rRange
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
421 rRange
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
422 rRange
.mbValue
= static_cast<bool>(aData
.mnValue
);
426 ScFlatBoolRowSegments::ScFlatBoolRowSegments(SCROW nMaxRow
) :
427 mpImpl(new ScFlatBoolSegmentsImpl(nMaxRow
))
431 ScFlatBoolRowSegments::ScFlatBoolRowSegments(const ScFlatBoolRowSegments
& r
) :
432 mpImpl(new ScFlatBoolSegmentsImpl(*r
.mpImpl
))
436 ScFlatBoolRowSegments::~ScFlatBoolRowSegments()
440 bool ScFlatBoolRowSegments::setTrue(SCROW nRow1
, SCROW nRow2
)
442 return mpImpl
->setTrue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
445 bool ScFlatBoolRowSegments::setFalse(SCROW nRow1
, SCROW nRow2
)
447 return mpImpl
->setFalse(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
450 bool ScFlatBoolRowSegments::getRangeData(SCROW nRow
, RangeData
& rData
) const
452 ScFlatBoolSegmentsImpl::RangeData aData
;
453 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nRow
), aData
))
456 rData
.mbValue
= aData
.mnValue
;
457 rData
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
458 rData
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
462 bool ScFlatBoolRowSegments::getRangeDataLeaf(SCROW nRow
, RangeData
& rData
)
464 ScFlatBoolSegmentsImpl::RangeData aData
;
465 if (!mpImpl
->getRangeDataLeaf(static_cast<SCCOLROW
>(nRow
), aData
))
468 rData
.mbValue
= aData
.mnValue
;
469 rData
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
470 rData
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
474 void ScFlatBoolRowSegments::removeSegment(SCROW nRow1
, SCROW nRow2
)
476 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
479 void ScFlatBoolRowSegments::insertSegment(SCROW nRow
, SCROW nSize
)
481 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nRow
), static_cast<SCCOLROW
>(nSize
), true/*bSkipStartBoundary*/);
484 SCROW
ScFlatBoolRowSegments::findLastTrue() const
486 return mpImpl
->findLastTrue(false);
489 void ScFlatBoolRowSegments::makeReady()
494 OString
ScFlatBoolRowSegments::dumpAsString()
496 OStringBuffer
aOutput(4096);
499 while (getRangeData(nRow
, aRange
))
502 aOutput
.append(aRange
.mbValue
? '1' : '0').append(':');
504 aOutput
.append(OString::number(aRange
.mnRow2
) + " ");
505 nRow
= aRange
.mnRow2
+ 1;
508 return aOutput
.makeStringAndClear();
511 ScFlatBoolColSegments::ScFlatBoolColSegments(SCCOL nMaxCol
) :
512 mpImpl(new ScFlatBoolSegmentsImpl(nMaxCol
))
516 ScFlatBoolColSegments::ScFlatBoolColSegments(const ScFlatBoolColSegments
& r
) :
517 mpImpl(new ScFlatBoolSegmentsImpl(*r
.mpImpl
))
521 ScFlatBoolColSegments::~ScFlatBoolColSegments()
525 bool ScFlatBoolColSegments::setTrue(SCCOL nCol1
, SCCOL nCol2
)
527 return mpImpl
->setTrue(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
530 bool ScFlatBoolColSegments::setFalse(SCCOL nCol1
, SCCOL nCol2
)
532 return mpImpl
->setFalse(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
535 bool ScFlatBoolColSegments::getRangeData(SCCOL nCol
, RangeData
& rData
)
537 ScFlatBoolSegmentsImpl::RangeData aData
;
538 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nCol
), aData
))
541 rData
.mbValue
= aData
.mnValue
;
542 rData
.mnCol1
= static_cast<SCCOL
>(aData
.mnPos1
);
543 rData
.mnCol2
= static_cast<SCCOL
>(aData
.mnPos2
);
547 void ScFlatBoolColSegments::removeSegment(SCCOL nCol1
, SCCOL nCol2
)
549 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
552 void ScFlatBoolColSegments::insertSegment(SCCOL nCol
, SCCOL nSize
)
554 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nCol
), static_cast<SCCOLROW
>(nSize
), true/*bSkipStartBoundary*/);
557 void ScFlatBoolColSegments::makeReady()
562 OString
ScFlatBoolColSegments::dumpAsString()
564 OStringBuffer
aOutput(4096);
567 while (getRangeData(nCol
, aRange
))
570 aOutput
.append(aRange
.mbValue
? '1' : '0').append(':');
572 aOutput
.append(OString::number(aRange
.mnCol2
) + " ");
573 nCol
= aRange
.mnCol2
+ 1;
576 return aOutput
.makeStringAndClear();
579 ScFlatUInt16RowSegments::ForwardIterator::ForwardIterator(ScFlatUInt16RowSegments
& rSegs
) :
580 mrSegs(rSegs
), mnCurPos(0), mnLastPos(-1), mnCurValue(0)
584 bool ScFlatUInt16RowSegments::ForwardIterator::getValue(SCROW nPos
, sal_uInt16
& rVal
)
586 if (nPos
>= mnCurPos
)
587 // It can only go in a forward direction.
590 if (mnCurPos
> mnLastPos
)
592 // position not in the current segment. Update the current value.
593 ScFlatUInt16SegmentsImpl::RangeData aData
;
596 // first time in this method, use the tree search based method
597 if (!mrSegs
.mpImpl
->getRangeData(mnCurPos
, aData
))
602 // but on subsequent calls, use the leaf method, which is faster
603 // because we have a cached iterator.
604 if (!mrSegs
.mpImpl
->getRangeDataLeaf(mnCurPos
, aData
))
608 mnCurValue
= aData
.mnValue
;
609 mnLastPos
= aData
.mnPos2
;
616 ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(SCROW nMaxRow
, sal_uInt16 nDefault
) :
617 mpImpl(new ScFlatUInt16SegmentsImpl(nMaxRow
, nDefault
))
621 ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(const ScFlatUInt16RowSegments
& r
) :
622 mpImpl(new ScFlatUInt16SegmentsImpl(*r
.mpImpl
))
626 ScFlatUInt16RowSegments::~ScFlatUInt16RowSegments()
630 void ScFlatUInt16RowSegments::setValue(SCROW nRow1
, SCROW nRow2
, sal_uInt16 nValue
)
632 mpImpl
->setValue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
), nValue
);
635 sal_uInt16
ScFlatUInt16RowSegments::getValue(SCROW nRow
)
637 return mpImpl
->getValue(static_cast<SCCOLROW
>(nRow
));
640 sal_uInt64
ScFlatUInt16RowSegments::getSumValue(SCROW nRow1
, SCROW nRow2
)
642 return mpImpl
->getSumValue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
645 bool ScFlatUInt16RowSegments::getRangeData(SCROW nRow
, RangeData
& rData
)
647 ScFlatUInt16SegmentsImpl::RangeData aData
;
648 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nRow
), aData
))
651 rData
.mnRow1
= aData
.mnPos1
;
652 rData
.mnRow2
= aData
.mnPos2
;
653 rData
.mnValue
= aData
.mnValue
;
657 void ScFlatUInt16RowSegments::removeSegment(SCROW nRow1
, SCROW nRow2
)
659 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
662 void ScFlatUInt16RowSegments::insertSegment(SCROW nRow
, SCROW nSize
)
664 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nRow
), static_cast<SCCOLROW
>(nSize
), false/*bSkipStartBoundary*/);
667 SCROW
ScFlatUInt16RowSegments::findLastTrue(sal_uInt16 nValue
) const
669 return mpImpl
->findLastTrue(nValue
);
672 void ScFlatUInt16RowSegments::enableTreeSearch(bool bEnable
)
674 mpImpl
->enableTreeSearch(bEnable
);
677 void ScFlatUInt16RowSegments::setValueIf(SCROW nRow1
, SCROW nRow2
, sal_uInt16 nValue
, const std::function
<bool(sal_uInt16
)>& rPredicate
)
679 mpImpl
->setValueIf(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
), nValue
, rPredicate
);
682 void ScFlatUInt16RowSegments::makeReady()
687 OString
ScFlatUInt16RowSegments::dumpAsString()
689 OStringBuffer
aOutput(4096);
692 while (getRangeData(nRow
, aRange
))
694 aOutput
.append(OString::number(aRange
.mnValue
) + ":" + OString::number(aRange
.mnRow2
) + " ");
695 nRow
= aRange
.mnRow2
+ 1;
698 return aOutput
.makeStringAndClear();
701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */