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 .
21 #include "segmenttree.hxx"
23 #include <mdds/flat_segment_tree.hpp>
27 using ::std::numeric_limits
;
29 // ============================================================================
31 template<typename _ValueType
, typename _ExtValueType
= _ValueType
>
32 class ScFlatSegmentsImpl
35 typedef _ValueType ValueType
;
36 typedef _ExtValueType ExtValueType
;
45 ScFlatSegmentsImpl(SCCOLROW nMax
, ValueType nDefault
);
46 ScFlatSegmentsImpl(const ScFlatSegmentsImpl
& r
);
47 ~ScFlatSegmentsImpl();
49 bool setValue(SCCOLROW nPos1
, SCCOLROW nPos2
, ValueType nValue
);
50 ValueType
getValue(SCCOLROW nPos
);
51 ExtValueType
getSumValue(SCCOLROW nPos1
, SCCOLROW nPos2
);
52 bool getRangeData(SCCOLROW nPos
, RangeData
& rData
);
53 bool getRangeDataLeaf(SCCOLROW nPos
, RangeData
& rData
);
54 void removeSegment(SCCOLROW nPos1
, SCCOLROW nPos2
);
55 void insertSegment(SCCOLROW nPos
, SCCOLROW nSize
, bool bSkipStartBoundary
);
57 SCROW
findLastNotOf(ValueType nValue
) const;
60 bool getFirst(RangeData
& rData
);
61 bool getNext(RangeData
& rData
);
63 void enableTreeSearch(bool b
)
65 mbTreeSearchEnabled
= b
;
69 typedef ::mdds::flat_segment_tree
<SCCOLROW
, ValueType
> fst_type
;
71 typename
fst_type::const_iterator maItr
;
73 bool mbTreeSearchEnabled
:1;
76 template<typename _ValueType
, typename _ExtValueType
>
77 ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::ScFlatSegmentsImpl(SCCOLROW nMax
, ValueType nDefault
) :
78 maSegments(0, nMax
+1, nDefault
),
79 mbTreeSearchEnabled(true)
83 template<typename _ValueType
, typename _ExtValueType
>
84 ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::ScFlatSegmentsImpl(const ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>& r
) :
85 maSegments(r
.maSegments
),
86 mbTreeSearchEnabled(r
.mbTreeSearchEnabled
)
90 template<typename _ValueType
, typename _ExtValueType
>
91 ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::~ScFlatSegmentsImpl()
95 template<typename _ValueType
, typename _ExtValueType
>
96 bool ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::setValue(SCCOLROW nPos1
, SCCOLROW nPos2
, ValueType nValue
)
98 ::std::pair
<typename
fst_type::const_iterator
, bool> ret
;
99 ret
= maSegments
.insert(maItr
, nPos1
, nPos2
+1, nValue
);
104 template<typename _ValueType
, typename _ExtValueType
>
105 typename ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::ValueType ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getValue(SCCOLROW nPos
)
107 ValueType nValue
= 0;
108 if (!mbTreeSearchEnabled
)
110 maSegments
.search(nPos
, nValue
);
114 if (!maSegments
.is_tree_valid())
115 maSegments
.build_tree();
117 maSegments
.search_tree(nPos
, nValue
);
121 template<typename _ValueType
, typename _ExtValueType
>
122 typename ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::ExtValueType
123 ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getSumValue(SCCOLROW nPos1
, SCCOLROW nPos2
)
126 if (!getRangeData(nPos1
, aData
))
129 sal_uInt32 nValue
= 0;
131 SCROW nCurPos
= nPos1
;
132 SCROW nEndPos
= aData
.mnPos2
;
133 while (nEndPos
<= nPos2
)
135 nValue
+= aData
.mnValue
* (nEndPos
- nCurPos
+ 1);
136 nCurPos
= nEndPos
+ 1;
137 if (!getRangeData(nCurPos
, aData
))
140 nEndPos
= aData
.mnPos2
;
142 if (nCurPos
<= nPos2
)
144 nEndPos
= ::std::min(nEndPos
, nPos2
);
145 nValue
+= aData
.mnValue
* (nEndPos
- nCurPos
+ 1);
150 template<typename _ValueType
, typename _ExtValueType
>
151 bool ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getRangeData(SCCOLROW nPos
, RangeData
& rData
)
153 if (!mbTreeSearchEnabled
)
154 return getRangeDataLeaf(nPos
, rData
);
156 if (!maSegments
.is_tree_valid())
157 maSegments
.build_tree();
159 if (!maSegments
.search_tree(nPos
, rData
.mnValue
, &rData
.mnPos1
, &rData
.mnPos2
).second
)
162 rData
.mnPos2
= rData
.mnPos2
-1; // end point is not inclusive.
166 template<typename _ValueType
, typename _ExtValueType
>
167 bool ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getRangeDataLeaf(SCCOLROW nPos
, RangeData
& rData
)
169 // Conduct leaf-node only search. Faster when searching between range insertion.
170 const ::std::pair
<typename
fst_type::const_iterator
, bool> &ret
=
171 maSegments
.search(maItr
, nPos
, rData
.mnValue
, &rData
.mnPos1
, &rData
.mnPos2
);
178 rData
.mnPos2
= rData
.mnPos2
-1; // end point is not inclusive.
182 template<typename _ValueType
, typename _ExtValueType
>
183 void ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::removeSegment(SCCOLROW nPos1
, SCCOLROW nPos2
)
185 maSegments
.shift_left(nPos1
, nPos2
);
186 maItr
= maSegments
.begin();
189 template<typename _ValueType
, typename _ExtValueType
>
190 void ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::insertSegment(SCCOLROW nPos
, SCCOLROW nSize
, bool bSkipStartBoundary
)
192 maSegments
.shift_right(nPos
, nSize
, bSkipStartBoundary
);
193 maItr
= maSegments
.begin();
196 template<typename _ValueType
, typename _ExtValueType
>
197 SCCOLROW ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::findLastNotOf(ValueType nValue
) const
199 SCCOLROW nPos
= numeric_limits
<SCCOLROW
>::max(); // position not found.
200 typename
fst_type::const_reverse_iterator itr
= maSegments
.rbegin(), itrEnd
= maSegments
.rend();
201 // Note that when searching in reverse direction, we need to skip the first
202 // node, since the right-most leaf node does not store a valid value.
203 for (++itr
; itr
!= itrEnd
; ++itr
)
205 if (itr
->second
!= nValue
)
207 nPos
= (--itr
)->first
- 1;
214 template<typename _ValueType
, typename _ExtValueType
>
215 bool ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getFirst(RangeData
& rData
)
217 maItr
= maSegments
.begin();
218 return getNext(rData
);
221 template<typename _ValueType
, typename _ExtValueType
>
222 bool ScFlatSegmentsImpl
<_ValueType
, _ExtValueType
>::getNext(RangeData
& rData
)
224 typename
fst_type::const_iterator itrEnd
= maSegments
.end();
228 rData
.mnPos1
= maItr
->first
;
229 rData
.mnValue
= maItr
->second
;
235 rData
.mnPos2
= maItr
->first
- 1;
239 // ============================================================================
241 class ScFlatUInt16SegmentsImpl
: public ScFlatSegmentsImpl
<sal_uInt16
, sal_uInt32
>
244 explicit ScFlatUInt16SegmentsImpl(SCCOLROW nMax
, sal_uInt16 nDefault
) :
245 ScFlatSegmentsImpl
<sal_uInt16
, sal_uInt32
>(nMax
, nDefault
)
250 // ----------------------------------------------------------------------------
252 class ScFlatBoolSegmentsImpl
: public ScFlatSegmentsImpl
<bool>
255 explicit ScFlatBoolSegmentsImpl(SCCOLROW nMax
) :
256 ScFlatSegmentsImpl
<bool>(nMax
, false)
260 bool setTrue(SCCOLROW nPos1
, SCCOLROW nPos2
);
261 bool setFalse(SCCOLROW nPos1
, SCCOLROW nPos2
);
264 bool ScFlatBoolSegmentsImpl::setTrue(SCCOLROW nPos1
, SCCOLROW nPos2
)
266 return setValue(nPos1
, nPos2
, true);
269 bool ScFlatBoolSegmentsImpl::setFalse(SCCOLROW nPos1
, SCCOLROW nPos2
)
271 return setValue(nPos1
, nPos2
, false);
274 // ============================================================================
276 ScFlatBoolRowSegments::ForwardIterator::ForwardIterator(ScFlatBoolRowSegments
& rSegs
) :
277 mrSegs(rSegs
), mnCurPos(0), mnLastPos(-1), mbCurValue(false)
281 bool ScFlatBoolRowSegments::ForwardIterator::getValue(SCROW nPos
, bool& rVal
)
283 if (nPos
>= mnCurPos
)
284 // It can only go in a forward direction.
287 if (mnCurPos
> mnLastPos
)
289 // position not in the current segment. Update the current value.
290 ScFlatBoolRowSegments::RangeData aData
;
291 if (!mrSegs
.getRangeData(mnCurPos
, aData
))
294 mbCurValue
= aData
.mbValue
;
295 mnLastPos
= aData
.mnRow2
;
302 SCROW
ScFlatBoolRowSegments::ForwardIterator::getLastPos() const
307 // ----------------------------------------------------------------------------
309 ScFlatBoolRowSegments::RangeIterator::RangeIterator(ScFlatBoolRowSegments
& rSegs
) :
314 bool ScFlatBoolRowSegments::RangeIterator::getFirst(RangeData
& rRange
)
316 ScFlatBoolSegmentsImpl::RangeData aData
;
317 if (!mrSegs
.mpImpl
->getFirst(aData
))
320 rRange
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
321 rRange
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
322 rRange
.mbValue
= static_cast<bool>(aData
.mnValue
);
326 bool ScFlatBoolRowSegments::RangeIterator::getNext(RangeData
& rRange
)
328 ScFlatBoolSegmentsImpl::RangeData aData
;
329 if (!mrSegs
.mpImpl
->getNext(aData
))
332 rRange
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
333 rRange
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
334 rRange
.mbValue
= static_cast<bool>(aData
.mnValue
);
338 // ----------------------------------------------------------------------------
340 ScFlatBoolRowSegments::ScFlatBoolRowSegments() :
341 mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW
>(MAXROW
)))
345 ScFlatBoolRowSegments::ScFlatBoolRowSegments(const ScFlatBoolRowSegments
& r
) :
346 mpImpl(new ScFlatBoolSegmentsImpl(*r
.mpImpl
))
350 ScFlatBoolRowSegments::~ScFlatBoolRowSegments()
354 bool ScFlatBoolRowSegments::setTrue(SCROW nRow1
, SCROW nRow2
)
356 return mpImpl
->setTrue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
359 bool ScFlatBoolRowSegments::setFalse(SCROW nRow1
, SCROW nRow2
)
361 return mpImpl
->setFalse(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
364 bool ScFlatBoolRowSegments::getValue(SCROW nRow
)
366 return mpImpl
->getValue(static_cast<SCCOLROW
>(nRow
));
369 bool ScFlatBoolRowSegments::getRangeData(SCROW nRow
, RangeData
& rData
)
371 ScFlatBoolSegmentsImpl::RangeData aData
;
372 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nRow
), aData
))
375 rData
.mbValue
= aData
.mnValue
;
376 rData
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
377 rData
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
381 bool ScFlatBoolRowSegments::getRangeDataLeaf(SCROW nRow
, RangeData
& rData
)
383 ScFlatBoolSegmentsImpl::RangeData aData
;
384 if (!mpImpl
->getRangeDataLeaf(static_cast<SCCOLROW
>(nRow
), aData
))
387 rData
.mbValue
= aData
.mnValue
;
388 rData
.mnRow1
= static_cast<SCROW
>(aData
.mnPos1
);
389 rData
.mnRow2
= static_cast<SCROW
>(aData
.mnPos2
);
393 void ScFlatBoolRowSegments::removeSegment(SCROW nRow1
, SCROW nRow2
)
395 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
398 void ScFlatBoolRowSegments::insertSegment(SCROW nRow
, SCROW nSize
, bool bSkipStartBoundary
)
400 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nRow
), static_cast<SCCOLROW
>(nSize
), bSkipStartBoundary
);
403 SCROW
ScFlatBoolRowSegments::findLastNotOf(bool bValue
) const
405 return static_cast<SCROW
>(mpImpl
->findLastNotOf(bValue
));
408 // ============================================================================
410 ScFlatBoolColSegments::ScFlatBoolColSegments() :
411 mpImpl(new ScFlatBoolSegmentsImpl(static_cast<SCCOLROW
>(MAXCOL
)))
415 ScFlatBoolColSegments::ScFlatBoolColSegments(const ScFlatBoolColSegments
& r
) :
416 mpImpl(new ScFlatBoolSegmentsImpl(*r
.mpImpl
))
420 ScFlatBoolColSegments::~ScFlatBoolColSegments()
424 bool ScFlatBoolColSegments::setTrue(SCCOL nCol1
, SCCOL nCol2
)
426 return mpImpl
->setTrue(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
429 bool ScFlatBoolColSegments::setFalse(SCCOL nCol1
, SCCOL nCol2
)
431 return mpImpl
->setFalse(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
434 bool ScFlatBoolColSegments::getRangeData(SCCOL nCol
, RangeData
& rData
)
436 ScFlatBoolSegmentsImpl::RangeData aData
;
437 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nCol
), aData
))
440 rData
.mbValue
= aData
.mnValue
;
441 rData
.mnCol1
= static_cast<SCCOL
>(aData
.mnPos1
);
442 rData
.mnCol2
= static_cast<SCCOL
>(aData
.mnPos2
);
446 void ScFlatBoolColSegments::removeSegment(SCCOL nCol1
, SCCOL nCol2
)
448 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nCol1
), static_cast<SCCOLROW
>(nCol2
));
451 void ScFlatBoolColSegments::insertSegment(SCCOL nCol
, SCCOL nSize
, bool bSkipStartBoundary
)
453 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nCol
), static_cast<SCCOLROW
>(nSize
), bSkipStartBoundary
);
456 // ============================================================================
458 ScFlatUInt16RowSegments::ForwardIterator::ForwardIterator(ScFlatUInt16RowSegments
& rSegs
) :
459 mrSegs(rSegs
), mnCurPos(0), mnLastPos(-1), mnCurValue(0)
463 bool ScFlatUInt16RowSegments::ForwardIterator::getValue(SCROW nPos
, sal_uInt16
& rVal
)
465 if (nPos
>= mnCurPos
)
466 // It can only go in a forward direction.
469 if (mnCurPos
> mnLastPos
)
471 // position not in the current segment. Update the current value.
472 ScFlatUInt16RowSegments::RangeData aData
;
473 if (!mrSegs
.getRangeData(mnCurPos
, aData
))
476 mnCurValue
= aData
.mnValue
;
477 mnLastPos
= aData
.mnRow2
;
484 SCROW
ScFlatUInt16RowSegments::ForwardIterator::getLastPos() const
489 // ----------------------------------------------------------------------------
491 ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(sal_uInt16 nDefault
) :
492 mpImpl(new ScFlatUInt16SegmentsImpl(static_cast<SCCOLROW
>(MAXROW
), nDefault
))
496 ScFlatUInt16RowSegments::ScFlatUInt16RowSegments(const ScFlatUInt16RowSegments
& r
) :
497 mpImpl(new ScFlatUInt16SegmentsImpl(*r
.mpImpl
))
501 ScFlatUInt16RowSegments::~ScFlatUInt16RowSegments()
505 void ScFlatUInt16RowSegments::setValue(SCROW nRow1
, SCROW nRow2
, sal_uInt16 nValue
)
507 mpImpl
->setValue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
), nValue
);
510 sal_uInt16
ScFlatUInt16RowSegments::getValue(SCROW nRow
)
512 return mpImpl
->getValue(static_cast<SCCOLROW
>(nRow
));
515 sal_uInt32
ScFlatUInt16RowSegments::getSumValue(SCROW nRow1
, SCROW nRow2
)
517 return mpImpl
->getSumValue(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
520 bool ScFlatUInt16RowSegments::getRangeData(SCROW nRow
, RangeData
& rData
)
522 ScFlatUInt16SegmentsImpl::RangeData aData
;
523 if (!mpImpl
->getRangeData(static_cast<SCCOLROW
>(nRow
), aData
))
526 rData
.mnRow1
= aData
.mnPos1
;
527 rData
.mnRow2
= aData
.mnPos2
;
528 rData
.mnValue
= aData
.mnValue
;
532 void ScFlatUInt16RowSegments::removeSegment(SCROW nRow1
, SCROW nRow2
)
534 mpImpl
->removeSegment(static_cast<SCCOLROW
>(nRow1
), static_cast<SCCOLROW
>(nRow2
));
537 void ScFlatUInt16RowSegments::insertSegment(SCROW nRow
, SCROW nSize
, bool bSkipStartBoundary
)
539 mpImpl
->insertSegment(static_cast<SCCOLROW
>(nRow
), static_cast<SCCOLROW
>(nSize
), bSkipStartBoundary
);
542 SCROW
ScFlatUInt16RowSegments::findLastNotOf(sal_uInt16 nValue
) const
544 return static_cast<SCROW
>(mpImpl
->findLastNotOf(nValue
));
547 void ScFlatUInt16RowSegments::enableTreeSearch(bool bEnable
)
549 mpImpl
->enableTreeSearch(bEnable
);
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */