summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/bitmath_func.hpp63
-rw-r--r--src/goal_gui.cpp3
-rw-r--r--src/newgrf.cpp3
-rw-r--r--src/newgrf_station.cpp3
-rw-r--r--src/settings.cpp3
-rw-r--r--src/station_cmd.cpp3
-rw-r--r--src/station_gui.cpp3
-rw-r--r--src/town_gui.cpp3
-rw-r--r--src/water_cmd.cpp6
9 files changed, 58 insertions, 32 deletions
diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp
index 4af46d343..917a247da 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 <typename Tbitpos = uint, typename Tbitset = uint>
+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<Tbitpos>(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<Tbitset>(this->bitset >> 1);
+ this->bitpos++;
+ }
+ };
+
+ SetBitIterator(Tbitset bitset) : bitset(bitset) {}
+ Iterator begin() { return Iterator(this->bitset); }
+ Iterator end() { return Iterator(static_cast<Tbitset>(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 922f5f5d5..65ed9003b 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 77b4d52a9..15e95e4d2 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 a7932ce23..5fd5d6ad3 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 09223c585..97a73dd13 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 8f26ecf4c..a58c7b1f2 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 1b64d8aee..e36978c37 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 2d7aa8f20..ec44b246b 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 dbb4999a7..a2bedac84 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)) {