Use std::string_view keys for UpperMap

This avoids constructing temporary `std::string` objects on lookup
This commit is contained in:
Rangi
2026-05-27 21:11:39 -04:00
committed by Rangi
parent 007672f080
commit 673c62414f
3 changed files with 24 additions and 12 deletions
+4
View File
@@ -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 <inttype.h> macros)
#define PRI_SV ".*s"
#define PRI_SV_ARG(sv) static_cast<int>((sv).length()), (sv).data()
// MSVC does not inline `strlen()` or `.length()` of a constant string
template<int SizeOfString>
requires(SizeOfString > 0)
+7 -5
View File
@@ -8,7 +8,7 @@
#include <optional>
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <string_view>
#include <unordered_map>
#include "helpers.hpp"
@@ -76,23 +76,25 @@ std::optional<uint64_t> 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<typename ItemT>
using UpperMap = std::unordered_map<std::string, ItemT, Uppercase, Uppercase>;
using UpperMap = std::unordered_map<std::string_view, ItemT, Uppercase, Uppercase>;
#endif // RGBDS_UTIL_HPP
+13 -7
View File
@@ -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;
}
}