diff options
author | Jochen Nitschke <j.nitschke+logerrit@ok.de> | 2016-10-30 12:31:26 +0100 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2016-10-30 18:59:13 +0000 |
commit | e75561bd19faa332c077ec249a397d056fae63f2 (patch) | |
tree | 4ec9622274abac1fde1d8781cd495041ae591125 /svl/source/items/itemset.cxx | |
parent | 3d531da5ac08d5da5d7177306dba0f8a38696002 (diff) |
bin SfxUShortRanges, inline and rewrite only usage
only use was to merge 2 range tables in SfxItemSet::MergeRange
of which one table always contained a single range.
rewrite the merge algorithm (SfxUShortRanges += operator).
sort new range into the table of ranges and merge overlapping
ranges afterwards. Not as optimal as the original code but it's
short, maintainable and works without 'goto'
inline the DBG_CHECK_RANGES macro
Change-Id: I991c050f069d44fe72b3ea374863f5f26e7099e9
Reviewed-on: https://gerrit.libreoffice.org/30299
Tested-by: Jochen Nitschke <j.nitschke+logerrit@ok.de>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'svl/source/items/itemset.cxx')
-rw-r--r-- | svl/source/items/itemset.cxx | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index c10430514061..745d96a86c67 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -593,10 +593,58 @@ void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo ) if ( nFrom == nTo && ( eItemState == SfxItemState::DEFAULT || eItemState == SfxItemState::SET ) ) return; - // merge new range - SfxUShortRanges aRanges( m_pWhichRanges ); - aRanges += SfxUShortRanges( nFrom, nTo ); - SetRanges( aRanges ); +#ifdef DBG_UTIL + assert(nFrom <= nTo); + for (const sal_uInt16 *pRange = m_pWhichRanges; *pRange; pRange += 2) + { + assert(pRange[0] <= pRange[1]); + // ranges must be sorted and discrete + assert(!pRange[2] || (pRange[2] - pRange[1]) > 1); + } +#endif + + // create vector of ranges (sal_uInt16 pairs of lower and upper bound) + const size_t nOldCount = Count_Impl(m_pWhichRanges); + std::vector<std::pair<sal_uInt16, sal_uInt16>> aRangesTable; + aRangesTable.reserve(nOldCount/2 + 1); + bool bAdded = false; + for (size_t i = 0; i < nOldCount; i += 2) + { + if (!bAdded && m_pWhichRanges[i] >= nFrom) + { // insert new range, keep ranges sorted + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(nFrom, nTo)); + bAdded = true; + } + // insert current range + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(m_pWhichRanges[i], m_pWhichRanges[i+1])); + } + if (!bAdded) + aRangesTable.emplace_back(std::pair<sal_uInt16, sal_uInt16>(nFrom, nTo)); + + // true if ranges overlap or adjoin, false if ranges are separate + auto needMerge = [](std::pair<sal_uInt16, sal_uInt16> lhs, std::pair<sal_uInt16, sal_uInt16> rhs) + {return (lhs.first-1) <= rhs.second && (rhs.first-1) <= lhs.second;}; + + std::vector<std::pair<sal_uInt16, sal_uInt16> >::iterator it = aRangesTable.begin(); + // check neighbouring ranges, find first range which overlaps or adjoins a previous range + while ((it = std::is_sorted_until(it, aRangesTable.end(), needMerge)) != aRangesTable.end()) + { + --it; // merge with previous range + // lower bounds are sorted, implies: it->first = min(it[0].first, it[1].first) + it->second = std::max(it[0].second, it[1].second); + aRangesTable.erase(std::next(it)); + } + + // construct range array + const size_t nNewSize = 2 * aRangesTable.size() + 1; + std::vector<sal_uInt16> aRanges(nNewSize); + for (size_t i = 0; i < (nNewSize - 1); i +=2) + std::tie(aRanges[i], aRanges[i+1]) = aRangesTable[i/2]; + + // null terminate to be compatible with sal_uInt16* array pointers + aRanges.back() = 0; + + SetRanges( aRanges.data() ); } /** |