From 89ab8b79a51b4963da55dce195ea1ab520c73b50 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sun, 13 Jun 2021 04:18:21 +0200 Subject: [PATCH] Codechange: Remove FOR_EACH_SET_BIT --- src/core/bitmath_func.hpp | 63 ++++++++++++++++++++++++++++++--------- src/goal_gui.cpp | 3 +- src/newgrf.cpp | 3 +- src/newgrf_station.cpp | 3 +- src/settings.cpp | 3 +- src/station_cmd.cpp | 3 +- src/station_gui.cpp | 3 +- src/town_gui.cpp | 3 +- src/water_cmd.cpp | 6 ++-- 9 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp index 4af46d3430..917a247daa 100644 --- a/src/core/bitmath_func.hpp +++ b/src/core/bitmath_func.hpp @@ -345,20 +345,55 @@ static inline T ROR(const T x, const uint8 n) ) \ if ((___FESBE_bits & 1) != 0) -/** - * Do an operation for each set set bit in a value. - * - * This macros is used to do an operation for each set - * bit in a variable. The first parameter is a variable - * that is used as the bit position counter. - * The second parameter is an expression of the bits - * we need to iterate over. This expression will be - * evaluated once. - * - * @param bitpos_var The position counter variable. - * @param bitset_value The value which we check for set bits. - */ -#define FOR_EACH_SET_BIT(bitpos_var, bitset_value) FOR_EACH_SET_BIT_EX(uint, bitpos_var, uint, bitset_value) + /** + * Iterable ensemble of each set bit in a value. + * @tparam Tbitpos Type of the position variable. + * @tparam Tbitset Type of the bitset value. +*/ +template +struct SetBitIterator { + struct Iterator { + typedef Tbitpos value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef size_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit Iterator(Tbitset bitset) : bitset(bitset), bitpos(static_cast(0)) + { + this->Validate(); + } + + bool operator==(const Iterator &other) const + { + return this->bitset == other.bitset && (this->bitset == 0 || this->bitpos == other.bitpos); + } + bool operator!=(const Iterator &other) const { return !(*this == other); } + Tbitpos operator*() const { return this->bitpos; } + Iterator & operator++() { this->Next(); this->Validate(); return *this; } + + private: + Tbitset bitset; + Tbitpos bitpos; + void Validate() + { + while (this->bitset != 0 && (this->bitset & 1) == 0) this->Next(); + } + void Next() + { + this->bitset = static_cast(this->bitset >> 1); + this->bitpos++; + } + }; + + SetBitIterator(Tbitset bitset) : bitset(bitset) {} + Iterator begin() { return Iterator(this->bitset); } + Iterator end() { return Iterator(static_cast(0)); } + bool empty() { return this->begin() == this->end(); } + +private: + Tbitset bitset; +}; #if defined(__APPLE__) /* Make endian swapping use Apple's macros to increase speed diff --git a/src/goal_gui.cpp b/src/goal_gui.cpp index 922f5f5d5b..65ed9003b0 100644 --- a/src/goal_gui.cpp +++ b/src/goal_gui.cpp @@ -336,9 +336,8 @@ struct GoalQuestionWindow : public Window { this->question = stredup(question); /* Figure out which buttons we have to enable. */ - uint bit; int n = 0; - FOR_EACH_SET_BIT(bit, button_mask) { + for (uint bit : SetBitIterator(button_mask)) { if (bit >= GOAL_QUESTION_BUTTON_COUNT) break; this->button[n++] = bit; if (n == 3) break; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 77b4d52a91..15e95e4d2d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -961,8 +961,7 @@ static bool ReadSpriteLayout(ByteReader *buf, uint num_building_sprites, bool us static CargoTypes TranslateRefitMask(uint32 refit_mask) { CargoTypes result = 0; - uint8 bit; - FOR_EACH_SET_BIT(bit, refit_mask) { + for (uint8 bit : SetBitIterator(refit_mask)) { CargoID cargo = GetCargoTranslation(bit, _cur.grffile, true); if (cargo != CT_INVALID) SetBit(result, cargo); } diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index a7932ce231..5fd5d6ad3c 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -812,8 +812,7 @@ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID /* Sprite layout which needs preprocessing */ bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND); uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground); - uint8 var10; - FOR_EACH_SET_BIT(var10, var10_values) { + for (uint8 var10 : SetBitIterator(var10_values)) { uint32 var10_relocation = GetCustomStationRelocation(statspec, nullptr, INVALID_TILE, var10); layout->ProcessRegisters(var10, var10_relocation, separate_ground); } diff --git a/src/settings.cpp b/src/settings.cpp index 09223c585e..97a73dd13b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -354,9 +354,8 @@ void OneOfManySettingDesc::FormatValue(char *buf, const char *last, const void * void ManyOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const { uint bitmask = (uint)this->Read(object); - uint id = 0; bool first = true; - FOR_EACH_SET_BIT(id, bitmask) { + for (uint id : SetBitIterator(bitmask)) { if (!first) buf = strecpy(buf, "|", last); buf = this->FormatSingleValue(buf, last, id); first = false; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 8f26ecf4c0..a58c7b1f26 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2993,8 +2993,7 @@ draw_default_foundation: /* Sprite layout which needs preprocessing */ bool separate_ground = HasBit(statspec->flags, SSF_SEPARATE_GROUND); uint32 var10_values = layout->PrepareLayout(total_offset, rti->fallback_railtype, 0, 0, separate_ground); - uint8 var10; - FOR_EACH_SET_BIT(var10, var10_values) { + for (uint8 var10 : SetBitIterator(var10_values)) { uint32 var10_relocation = GetCustomStationRelocation(statspec, st, ti->tile, var10); layout->ProcessRegisters(var10, var10_relocation, separate_ground); } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 1b64d8aee9..e36978c37c 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -560,8 +560,7 @@ public: ToggleBit(this->facilities, widget - WID_STL_TRAIN); this->ToggleWidgetLoweredState(widget); } else { - uint i; - FOR_EACH_SET_BIT(i, this->facilities) { + for (uint i : SetBitIterator(this->facilities)) { this->RaiseWidget(i + WID_STL_TRAIN); } this->facilities = 1 << (widget - WID_STL_TRAIN); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 2d7aa8f20f..ec44b246b1 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -84,8 +84,7 @@ private: static int GetNthSetBit(uint32 bits, int n) { if (n >= 0) { - uint i; - FOR_EACH_SET_BIT(i, bits) { + for (uint i : SetBitIterator(bits)) { n--; if (n < 0) return i; } diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index dbb4999a7c..a2bedac845 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -1246,8 +1246,7 @@ void TileLoop_Water(TileIndex tile) case FLOOD_DRYUP: { Slope slope_here = GetFoundationSlope(tile) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP; - uint dir; - FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope_here]) { + for (uint dir : SetBitIterator(_flood_from_dirs[slope_here])) { TileIndex dest = tile + TileOffsByDir((Direction)dir); if (!IsValidTile(dest)) continue; @@ -1285,8 +1284,7 @@ void ConvertGroundTilesIntoWaterTiles() break; default: - uint dir; - FOR_EACH_SET_BIT(dir, _flood_from_dirs[slope & ~SLOPE_STEEP]) { + for (uint dir : SetBitIterator(_flood_from_dirs[slope & ~SLOPE_STEEP])) { TileIndex dest = TileAddByDir(tile, (Direction)dir); Slope slope_dest = GetTileSlope(dest) & ~SLOPE_STEEP; if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest)) {