From 673c62414f4b4a5260507de954b8fc2853c6e4ee Mon Sep 17 00:00:00 2001 From: Rangi Date: Wed, 27 May 2026 21:11:39 -0400 Subject: [PATCH] Use `std::string_view` keys for `UpperMap` This avoids constructing temporary `std::string` objects on lookup --- include/helpers.hpp | 4 ++++ include/util.hpp | 12 +++++++----- src/link/main.cpp | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/helpers.hpp b/include/helpers.hpp index c6180a00..8e7ff439 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -101,6 +101,10 @@ static inline int clz(unsigned int x) { #define RANGE(s) std::begin(s), std::end(s) #define RRANGE(s) std::rbegin(s), std::rend(s) +// Macros to print-format a `std::string_view` (like macros) +#define PRI_SV ".*s" +#define PRI_SV_ARG(sv) static_cast((sv).length()), (sv).data() + // MSVC does not inline `strlen()` or `.length()` of a constant string template requires(SizeOfString > 0) diff --git a/include/util.hpp b/include/util.hpp index 4b06531f..f03bcbe5 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "helpers.hpp" @@ -76,23 +76,25 @@ std::optional parseWholeNumber(char const *str, NumberBase base = BASE char const *printChar(int c); struct Uppercase { + using is_transparent = void; + // FNV-1a hash of an uppercased string - constexpr size_t operator()(std::string const &str) const { + constexpr size_t operator()(std::string_view str) const { return std::accumulate(RANGE(str), size_t(0x811C9DC5), [](size_t hash, char c) { return (hash ^ toUpper(c)) * 16777619; }); } // Compare two strings without case-sensitivity (by converting to uppercase) - constexpr bool operator()(std::string const &str1, std::string const &str2) const { + constexpr bool operator()(std::string_view str1, std::string_view str2) const { return std::equal(RANGE(str1), RANGE(str2), [](char c1, char c2) { return toUpper(c1) == toUpper(c2); }); } }; -// An unordered map from case-insensitive `std::string` keys to `ItemT` items +// An unordered map from case-insensitive `std::string_view` keys to `ItemT` items template -using UpperMap = std::unordered_map; +using UpperMap = std::unordered_map; #endif // RGBDS_UTIL_HPP diff --git a/src/link/main.cpp b/src/link/main.cpp index 3c19279f..f03232c5 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -176,6 +176,7 @@ static void parseScrambleSpec(char *spec) { fatal("Unknown region name \"%s\" in spec for option '-S'", regionName); } + uint16_t *scrambleLimit = search->second.first; uint16_t limit = search->second.second; if (regionSize) { char const *ptr = regionSize + skipBlankSpace(regionSize); @@ -183,24 +184,29 @@ static void parseScrambleSpec(char *spec) { fatal("Invalid region size limit \"%s\" for option '-S'", regionSize); } else if (*value > limit) { fatal( - "%s region size for option '-S' must be between 0 and %" PRIu16, - search->first.c_str(), + "%" PRI_SV " region size for option '-S' must be between 0 and %" PRIu16, + PRI_SV_ARG(search->first), limit ); } else { limit = *value; } - } else if (search->second.first != &options.scrambleWRAMX) { + } else if (scrambleLimit != &options.scrambleWRAMX) { // Only WRAMX limit can be implied, since ROMX and SRAM size may vary. - fatal("Missing %s region size limit for option '-S'", search->first.c_str()); + fatal( + "Missing %" PRI_SV " region size limit for option '-S'", PRI_SV_ARG(search->first) + ); } - if (*search->second.first != limit && *search->second.first != 0) { - warnx("Overriding %s region size limit for option '-S'", search->first.c_str()); + if (*scrambleLimit != limit && *search->second.first != 0) { + warnx( + "Overriding %" PRI_SV " region size limit for option '-S'", + PRI_SV_ARG(search->first) + ); } // Update the scrambling region size limit. - *search->second.first = limit; + *scrambleLimit = limit; } }