diff --git a/include/helpers.hpp b/include/helpers.hpp index b9a2a97f..7026b416 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -82,4 +82,7 @@ // (Having two instances of `arr` is OK because the contents of `sizeof` are not evaluated.) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof *(arr)) +// For lack of , this adds some more brevity +#define RANGE(s) std::begin(s), std::end(s) + #endif // HELPERS_H diff --git a/src/gfx/pal_packing.cpp b/src/gfx/pal_packing.cpp index 8c876f2b..41771254 100644 --- a/src/gfx/pal_packing.cpp +++ b/src/gfx/pal_packing.cpp @@ -16,6 +16,7 @@ #include #include "defaultinitalloc.hpp" +#include "helpers.hpp" #include "gfx/main.hpp" #include "gfx/proto_palette.hpp" @@ -140,7 +141,7 @@ public: template void assign(Ts &&...args) { auto freeSlot = std::find_if_not( - _assigned.begin(), _assigned.end(), + RANGE(_assigned), [](std::optional const &slot) { return slot.has_value(); }); if (freeSlot == _assigned.end()) { // We are full, use a new slot @@ -156,11 +157,11 @@ public: bool empty() const { return std::find_if( - _assigned.begin(), _assigned.end(), + RANGE(_assigned), [](std::optional const &slot) { return slot.has_value(); }) == _assigned.end(); } - size_t nbProtoPals() const { return std::distance(begin(), end()); } + size_t nbProtoPals() const { return std::distance(RANGE(*this)); } private: template @@ -168,7 +169,7 @@ private: std::vector const &protoPals) { for (; iter != end; ++iter) { ProtoPalette const &protoPal = protoPals[iter->protoPalIndex]; - colors.insert(protoPal.begin(), protoPal.end()); + colors.insert(RANGE(protoPal)); } } // This function should stay private because it returns a reference to a unique object @@ -188,7 +189,7 @@ private: static std::unordered_set colors; colors.clear(); - addUniqueColors(colors, begin(), end(), *_protoPals); + addUniqueColors(colors, RANGE(*this), *_protoPals); return colors; } public: @@ -198,7 +199,7 @@ public: size_t volume() const { return uniqueColors().size(); } bool canFit(ProtoPalette const &protoPal) const { auto &colors = uniqueColors(); - colors.insert(protoPal.begin(), protoPal.end()); + colors.insert(RANGE(protoPal)); return colors.size() <= options.maxOpaqueColors(); } @@ -209,9 +210,9 @@ public: // NOTE: this function must not call `uniqueColors`, or one of its callers will break! double relSize = 0.; for (uint16_t color : protoPal) { - auto n = std::count_if(begin(), end(), [this, &color](ProtoPalAttrs const &attrs) { + auto n = std::count_if(RANGE(*this), [this, &color](ProtoPalAttrs const &attrs) { ProtoPalette const &pal = (*_protoPals)[attrs.protoPalIndex]; - return std::find(pal.begin(), pal.end(), color) != pal.end(); + return std::find(RANGE(pal), color) != pal.end(); }); // NOTE: The paper and the associated code disagree on this: the code has // this `1 +`, whereas the paper does not; its lack causes a division by 0 @@ -273,8 +274,7 @@ static void decant(std::vector &assignments, // Decant on palettes decantOn([&protoPalettes](AssignedProtos &to, AssignedProtos &from) { // If the entire palettes can be merged, move all of `from`'s proto-palettes - if (to.combinedVolume(from.begin(), from.end(), protoPalettes) - <= options.maxOpaqueColors()) { + if (to.combinedVolume(RANGE(from), protoPalettes) <= options.maxOpaqueColors()) { for (ProtoPalAttrs &attrs : from) { to.assign(attrs.protoPalIndex); } @@ -294,7 +294,7 @@ static void decant(std::vector &assignments, std::unordered_set colors; std::vector members; while (true) { - auto iter = std::find(processed.begin(), processed.end(), true); + auto iter = std::find(RANGE(processed), true); if (iter == processed.end()) { // Processed everything! break; } @@ -309,10 +309,8 @@ static void decant(std::vector &assignments, ProtoPalette const &protoPal = protoPalettes[attrs->protoPalIndex]; // If this is the first proto-pal, or if at least one color matches, add it if (members.empty() - || std::find_first_of(colors.begin(), colors.end(), protoPal.begin(), - protoPal.end()) - != colors.end()) { - colors.insert(protoPal.begin(), protoPal.end()); + || std::find_first_of(RANGE(colors), RANGE(protoPal)) != colors.end()) { + colors.insert(RANGE(protoPal)); members.push_back(iter - processed.begin()); *iter = true; // Mark that proto-pal as processed } @@ -320,7 +318,7 @@ static void decant(std::vector &assignments, ++attrs; } while (iter != processed.end()); - if (to.combinedVolume(colors.begin(), colors.end()) <= options.maxOpaqueColors()) { + if (to.combinedVolume(RANGE(colors)) <= options.maxOpaqueColors()) { // Iterate through the component's proto-palettes, and transfer them auto member = from.begin(); size_t curIndex = 0; @@ -358,12 +356,10 @@ std::tuple, size_t> DefaultInitVec sortedProtoPalIDs(protoPalettes.size()); sortedProtoPalIDs.clear(); for (size_t i = 0; i < protoPalettes.size(); ++i) { - sortedProtoPalIDs.insert( - std::lower_bound(sortedProtoPalIDs.begin(), sortedProtoPalIDs.end(), i), i); + sortedProtoPalIDs.insert(std::lower_bound(RANGE(sortedProtoPalIDs), i), i); } // Begin with all proto-palettes queued up for insertion - std::queue queue( - std::deque(sortedProtoPalIDs.begin(), sortedProtoPalIDs.end())); + std::queue queue(std::deque(RANGE(sortedProtoPalIDs))); // Begin with no pages std::vector assignments{}; @@ -410,7 +406,7 @@ std::tuple, size_t> return pal.size() / bestPal.relSizeOf(pal); }; auto [minEfficiencyIter, maxEfficiencyIter] = - std::minmax_element(bestPal.begin(), bestPal.end(), + std::minmax_element(RANGE(bestPal), [&efficiency, &protoPalettes](ProtoPalAttrs const &lhs, ProtoPalAttrs const &rhs) { return efficiency(protoPalettes[lhs.protoPalIndex]) @@ -448,7 +444,7 @@ std::tuple, size_t> ProtoPalAttrs const &attrs = queue.front(); ProtoPalette const &protoPal = protoPalettes[attrs.protoPalIndex]; auto iter = - std::find_if(assignments.begin(), assignments.end(), + std::find_if(RANGE(assignments), [&protoPal](AssignedProtos const &pal) { return pal.canFit(protoPal); }); if (iter == assignments.end()) { // No such page, create a new one options.verbosePrint(Options::VERB_DEBUG, diff --git a/src/gfx/pal_sorting.cpp b/src/gfx/pal_sorting.cpp index 1f1dc1aa..f5df6fbc 100644 --- a/src/gfx/pal_sorting.cpp +++ b/src/gfx/pal_sorting.cpp @@ -23,7 +23,7 @@ void indexed(std::vector &palettes, int palSize, png_color const *palRG }; for (Palette &pal : palettes) { - std::sort(pal.begin(), pal.end(), [&](uint16_t lhs, uint16_t rhs) { + std::sort(RANGE(pal), [&](uint16_t lhs, uint16_t rhs) { // Iterate through the PNG's palette, looking for either of the two for (int i = 0; i < palSize; ++i) { uint16_t color = pngToRgb(i).cgbColor(); @@ -52,7 +52,7 @@ void grayscale(std::vector &palettes, assert(palettes.size() == 1); Palette &palette = palettes[0]; - std::fill(palette.colors.begin(), palette.colors.end(), Rgba::transparent); + std::fill(RANGE(palette.colors), Rgba::transparent); for (auto const &slot : colors) { if (!slot.has_value() || slot->isTransparent()) { continue; @@ -72,7 +72,7 @@ void rgb(std::vector &palettes) { options.verbosePrint(Options::VERB_LOG_ACT, "Sorting palettes by \"\"\"luminance\"\"\"...\n"); for (Palette &pal : palettes) { - std::sort(pal.begin(), pal.end(), [](uint16_t lhs, uint16_t rhs) { + std::sort(RANGE(pal), [](uint16_t lhs, uint16_t rhs) { return legacyLuminance(lhs) > legacyLuminance(rhs); }); } diff --git a/src/gfx/pal_spec.cpp b/src/gfx/pal_spec.cpp index d9497b9d..b97c3771 100644 --- a/src/gfx/pal_spec.cpp +++ b/src/gfx/pal_spec.cpp @@ -572,7 +572,7 @@ void parseExternalPalSpec(char const *arg) { std::tuple{"GBC", &parseGBCFile, std::ios::binary}, }; - auto iter = std::find_if(parsers.begin(), parsers.end(), + auto iter = std::find_if(RANGE(parsers), [&arg, &ptr](decltype(parsers)::value_type const &parser) { return strncasecmp(arg, std::get<0>(parser), ptr - arg) == 0; }); diff --git a/src/gfx/process.cpp b/src/gfx/process.cpp index e6aac621..775a43c0 100644 --- a/src/gfx/process.cpp +++ b/src/gfx/process.cpp @@ -60,7 +60,7 @@ public: } size_t size() const { - return std::count_if(_colors.begin(), _colors.end(), + return std::count_if(RANGE(_colors), [](decltype(_colors)::value_type const &slot) { return slot.has_value() && !slot->isTransparent(); }); @@ -333,7 +333,7 @@ public: Rgba &&color) { if (!color.isTransparent() && !color.isOpaque()) { uint32_t css = color.toCSS(); - if (std::find(indeterminates.begin(), indeterminates.end(), css) + if (std::find(RANGE(indeterminates), css) == indeterminates.end()) { error("Color #%08x is neither transparent (alpha < %u) nor opaque (alpha >= " "%u) [first seen at x: %" PRIu32 ", y: %" PRIu32 "]", @@ -343,7 +343,7 @@ public: } else if (Rgba const *other = colors.registerColor(color); other) { std::tuple conflicting{color.toCSS(), other->toCSS()}; // Do not report combinations twice - if (std::find(conflicts.begin(), conflicts.end(), conflicting) == conflicts.end()) { + if (std::find(RANGE(conflicts), conflicting) == conflicts.end()) { warning("Fusing colors #%08x and #%08x into Game Boy color $%04x [first seen " "at x: %" PRIu32 ", y: %" PRIu32 "]", std::get<0>(conflicting), std::get<1>(conflicting), color.cgbColor(), x, @@ -597,10 +597,10 @@ static std::tuple, std::vector> for (size_t i = 0; i < protoPalettes.size(); ++i) { ProtoPalette const &protoPal = protoPalettes[i]; // Find the palette... - auto iter = std::find_if(palettes.begin(), palettes.end(), [&protoPal](Palette const &pal) { + auto iter = std::find_if(RANGE(palettes), [&protoPal](Palette const &pal) { // ...which contains all colors in this proto-pal - return std::all_of(protoPal.begin(), protoPal.end(), [&pal](uint16_t color) { - return std::find(pal.begin(), pal.end(), color) != pal.end(); + return std::all_of(RANGE(protoPal), [&pal](uint16_t color) { + return std::find(RANGE(pal), color) != pal.end(); }); }); @@ -731,7 +731,7 @@ public: } // Check if we have horizontal mirroring, which scans the array forward again - if (std::equal(_data.begin(), _data.end(), other._data.begin(), + if (std::equal(RANGE(_data), other._data.begin(), [](uint8_t lhs, uint8_t rhs) { return lhs == flipTable[rhs]; })) { return MatchType::HFLIP; } diff --git a/src/gfx/proto_palette.cpp b/src/gfx/proto_palette.cpp index 5069ad8b..2a2f97f7 100644 --- a/src/gfx/proto_palette.cpp +++ b/src/gfx/proto_palette.cpp @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: MIT */ +#include "helpers.hpp" + #include "gfx/proto_palette.hpp" #include @@ -42,8 +44,8 @@ bool ProtoPalette::add(uint16_t color) { ProtoPalette::ComparisonResult ProtoPalette::compare(ProtoPalette const &other) const { // This works because the sets are sorted numerically - assert(std::is_sorted(_colorIndices.begin(), _colorIndices.end())); - assert(std::is_sorted(other._colorIndices.begin(), other._colorIndices.end())); + assert(std::is_sorted(RANGE(_colorIndices))); + assert(std::is_sorted(RANGE(other._colorIndices))); auto ours = _colorIndices.begin(), theirs = other._colorIndices.begin(); bool weBigger = true, theyBigger = true; @@ -67,7 +69,7 @@ ProtoPalette::ComparisonResult ProtoPalette::compare(ProtoPalette const &other) } size_t ProtoPalette::size() const { - return std::distance(begin(), end()); + return std::distance(RANGE(*this)); } bool ProtoPalette::empty() const { @@ -78,5 +80,5 @@ auto ProtoPalette::begin() const -> decltype(_colorIndices)::const_iterator { return _colorIndices.begin(); } auto ProtoPalette::end() const -> decltype(_colorIndices)::const_iterator { - return std::find(_colorIndices.begin(), _colorIndices.end(), UINT16_MAX); + return std::find(RANGE(_colorIndices), UINT16_MAX); } diff --git a/src/link/script.y b/src/link/script.y index fc5adeca..5a8f719b 100644 --- a/src/link/script.y +++ b/src/link/script.y @@ -281,17 +281,13 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t } for (SectionType type : EnumSeq(SECTTYPE_INVALID)) { - if (std::equal(ident.begin(), ident.end(), - sectionTypeInfo[type].name.begin(), sectionTypeInfo[type].name.end(), - strUpperCmp)) { + if (std::equal(RANGE(ident), RANGE(sectionTypeInfo[type].name), strUpperCmp)) { return yy::parser::make_section_type(type); } } for (Keyword const &keyword : keywords) { - if (std::equal(ident.begin(), ident.end(), - keyword.name.begin(), keyword.name.end(), - strUpperCmp)) { + if (std::equal(RANGE(ident), RANGE(keyword.name), strUpperCmp)) { return keyword.tokenGen(); } }