diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2021-06-11 12:07:44 +0200 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-06-14 12:46:07 +0200 |
commit | 49b3b9d3391abb50aefe291d2ee0f8bca7eb6bd0 (patch) | |
tree | e75e5ade8acbf8aa3f040aa28ef08572752935ad /include | |
parent | d376297c643785564e7bda1a74b573c35ade6cb8 (diff) |
Assert on valid order of which ids in ranges on SfxItemSet creation
This allows to make sure we actually use sorted which ranges,
and then it's safe to call SfxItemSet::MergeRange when needed.
Also this change relaxes the previous requirement that ranges
must be separated by at least one; this allows to have adjacent
ranges, like in
RES_FRMATR_BEGIN, RES_FRMATR_END-1,
RES_GRFATR_BEGIN, RES_GRFATR_END-1,
where RES_FRMATR_END is equal to RES_GRFATR_BEGIN. Allowing this
makes possible to (1) self-document the ranges, so it's clear
which ranges are included; and (2) be safe in case when these
constants would change, so that the one merged range would not
unexpectedly contain everything inserted between RES_FRMATR_END
and RES_GRFATR_BEGIN.
Change-Id: Iaad0f099b85059b3aa318a347aa7fbd3f6d455c7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116909
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
(cherry picked from commit 8aaa28ed43978a9a4a20d62368410a57ec05c23f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117114
Diffstat (limited to 'include')
-rw-r--r-- | include/svl/itemset.hxx | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index 41a782d7966f..d4a9304a85dd 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -21,11 +21,13 @@ #include <sal/config.h> +#include <array> #include <cassert> #include <cstddef> #include <initializer_list> #include <type_traits> #include <memory> +#include <utility> #include <svl/svldllapi.h> #include <svl/poolitem.hxx> @@ -41,7 +43,7 @@ constexpr bool validRange(sal_uInt16 wid1, sal_uInt16 wid2) { return wid1 != 0 && wid1 <= wid2; } constexpr bool validGap(sal_uInt16 wid1, sal_uInt16 wid2) -{ return wid2 > wid1 && wid2 - wid1 > 1; } +{ return wid2 > wid1; } template<sal_uInt16 WID1, sal_uInt16 WID2> constexpr bool validRanges() { return validRange(WID1, WID2); } @@ -52,6 +54,19 @@ constexpr bool validRanges() { && validRanges<WID3, WIDs...>(); } +inline constexpr bool validRanges(const sal_uInt16* pRanges) +{ + for (auto p = pRanges; p && *p; p += 2) + { + if (!validRange(p[0], p[1])) + return false; + // ranges must be sorted + if (p[2] != 0 && !validGap(p[1], p[2])) + return false; + } + return true; +} + // The calculations in rangeSize and rangesSize cannot overflow, assuming // std::size_t is no smaller than sal_uInt16: @@ -71,6 +86,24 @@ constexpr std::size_t rangesSize() template<sal_uInt16... WIDs> struct Items {}; +// This allows creating compile-time which id arrays using syntax like +// +// constexpr auto aWids = svl::ItemsArray({ { widFrom1, widTo2 }, { widFrom2, widTo2 }, ... }); +// +// so that e.g. clang-format would not try to rearrange the initializer sequence to break pairs. +// Additionally, the array validity is checked in debug builds. +template <size_t N> constexpr auto ItemsArray(const std::pair<sal_uInt16, sal_uInt16> (&wids)[N]) +{ + std::array<sal_uInt16, N * 2 + 1> aArray{}; + sal_uInt16* p = aArray.data(); + for (const auto& [wid1, wid2] : wids) + { + *p++ = wid1; + *p++ = wid2; + } + assert(svl::detail::validRanges(aArray.data())); + return aArray; +} } class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet @@ -88,7 +121,7 @@ friend class SfxItemPoolCache; friend class SfxAllItemSet; private: - SVL_DLLPRIVATE void InitRanges_Impl(const sal_uInt16 *nWhichPairTable); + SVL_DLLPRIVATE sal_uInt16 InitRanges_Impl(const sal_uInt16 *nWhichPairTable); SfxItemSet( SfxItemPool & pool, std::initializer_list<sal_uInt16> wids, @@ -249,8 +282,6 @@ class SVL_DLLPUBLIC SfxAllItemSet: public SfxItemSet // Handles all Ranges. Ranges are automatically modified by putting items. { - sal_uInt16 nFree; - public: SfxAllItemSet( SfxItemPool &rPool ); SfxAllItemSet( const SfxItemSet & ); |