1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 .
22 #include <sal/config.h>
24 #include <sal/types.h>
25 #include <svl/itemset.hxx>
34 * Determines the number of sal_uInt16s in a 0-terminated array of pairs of
35 * sal_uInt16s, each representing a range of sal_uInt16s, and total capacity of the ranges.
36 * The terminating 0 is included in the count.
38 inline std::pair
<sal_uInt16
, sal_uInt16
> CountRanges(const sal_uInt16
* pRanges
)
40 sal_uInt16 nCount
= 0;
41 sal_uInt16 nCapacity
= 0;
48 nCapacity
+= rangeSize(pRanges
[0], pRanges
[1]);
52 return { nCount
, nCapacity
};
55 // Adds a range to which ranges, keeping the ranges in valid state (sorted, non-overlapping)
56 inline std::unique_ptr
<sal_uInt16
[]> MergeRange(const sal_uInt16
* pWhichRanges
, sal_uInt16 nFrom
,
59 assert(validRange(nFrom
, nTo
));
63 auto pNewRanges
= std::make_unique
<sal_uInt16
[]>(3);
64 pNewRanges
[0] = nFrom
;
70 assert(validRanges(pWhichRanges
));
72 // create vector of ranges (sal_uInt16 pairs of lower and upper bound)
73 const size_t nOldCount
= CountRanges(pWhichRanges
).first
;
74 std::vector
<std::pair
<sal_uInt16
, sal_uInt16
>> aRangesTable
;
75 aRangesTable
.reserve(nOldCount
/ 2 + 1);
77 for (size_t i
= 0; i
+ 1 < nOldCount
; i
+= 2)
79 if (!bAdded
&& pWhichRanges
[i
] >= nFrom
)
80 { // insert new range, keep ranges sorted
81 aRangesTable
.emplace_back(std::pair
<sal_uInt16
, sal_uInt16
>(nFrom
, nTo
));
84 // insert current range
85 aRangesTable
.emplace_back(
86 std::pair
<sal_uInt16
, sal_uInt16
>(pWhichRanges
[i
], pWhichRanges
[i
+ 1]));
89 aRangesTable
.emplace_back(std::pair
<sal_uInt16
, sal_uInt16
>(nFrom
, nTo
));
91 // true if ranges overlap or adjoin, false if ranges are separate
93 = [](std::pair
<sal_uInt16
, sal_uInt16
> lhs
, std::pair
<sal_uInt16
, sal_uInt16
> rhs
) {
94 return (lhs
.first
- 1) <= rhs
.second
&& (rhs
.first
- 1) <= lhs
.second
;
97 auto it
= aRangesTable
.begin();
98 // we got at least one range
101 auto itNext
= std::next(it
);
102 if (itNext
== aRangesTable
.end())
104 // check neighbouring ranges, find first range which overlaps or adjoins a previous range
105 if (needMerge(*it
, *itNext
))
107 // lower bounds are sorted, implies: it->first = min(it[0].first, it[1].first)
108 it
->second
= std::max(it
->second
, itNext
->second
);
109 aRangesTable
.erase(itNext
);
115 // construct range array
116 const size_t nNewSize
= 2 * aRangesTable
.size() + 1;
117 auto pNewRanges
= std::make_unique
<sal_uInt16
[]>(nNewSize
);
118 for (size_t i
= 0; i
< (nNewSize
- 1); i
+= 2)
119 std::tie(pNewRanges
[i
], pNewRanges
[i
+ 1]) = aRangesTable
[i
/ 2];
121 pNewRanges
[nNewSize
- 1] = 0;
126 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */