From: Egor Date: Sun, 1 Feb 2026 12:36:25 +0000 (+0200) Subject: map: use <=> for case insensitive comparisons X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=1b6e9c06e6070515570747399473acbf69d5dfdf;p=patchyircd.git map: use <=> for case insensitive comparisons --- diff --git a/src/common.hpp b/src/common.hpp index bb04b8f..2a88544 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -29,6 +29,7 @@ /* C++ standard */ #include #include +#include #include #include #include diff --git a/src/map.cpp b/src/map.cpp index 0134dac..18cfb9c 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3,42 +3,71 @@ #include "common.hpp" #include "map.hpp" #include "ircdata.hpp" -static int istrcmp(const char *a, const char *b) { - unsigned char cha, chb; - int diff; - do { - cha = *a++; - chb = *b++; - if (chb >= 'A' && chb <= 'Z') - chb |= 0x20; - diff = cha - chb; - } while (!diff && cha && chb); - return diff; -} -template -static size_t ent_find(map_base *root, const char *key, int *found) + +template +class Comparisons { + friend constexpr bool operator==(const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs == 0; } + friend constexpr bool operator!=(const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs != 0; } + friend constexpr bool operator< (const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs < 0; } + friend constexpr bool operator<=(const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs <= 0; } + friend constexpr bool operator> (const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs > 0; } + friend constexpr bool operator>=(const A& lhs, const B& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs >= 0; } + + friend constexpr bool operator==(const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs == 0; } + friend constexpr bool operator!=(const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs != 0; } + friend constexpr bool operator< (const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs < 0; } + friend constexpr bool operator<=(const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs <= 0; } + friend constexpr bool operator> (const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs > 0; } + friend constexpr bool operator>=(const B& lhs, const A& rhs) noexcept(noexcept(lhs <=> rhs)) { return lhs <=> rhs >= 0; } +}; + +class LowercasingView : Comparisons { + std::string_view sv; +public: + explicit constexpr LowercasingView(std::string_view sv) :sv(sv) {} + friend constexpr std::strong_ordering operator<=>(std::string_view lhs, LowercasingView rhs) noexcept { + size_t len = std::min(lhs.size(), rhs.sv.size()); + const char *a = lhs.data(); + const char *b = rhs.sv.data(); + unsigned char cha, chb; + while (len--) { + cha = *a++; + chb = *b++; + if (chb >= 'A' && chb <= 'Z') + chb |= 0x20; + if (auto diff = cha <=> chb; diff != 0) + return diff; + } + return lhs.size() <=> rhs.sv.size(); + } + friend constexpr std::strong_ordering operator<=>(LowercasingView lhs, std::string_view rhs) noexcept { + return rhs <=> lhs; + } +}; + +static size_t ent_find(map_base *root, auto key, int *found) { auto it = std::partition_point(root->ptr, root->ptr + root->len, - [key](const auto &p){ return cmp(p.key, key) < 0; }); - *found = it != root->ptr + root->len && !cmp(it->key, key); + [key](const auto &p){ return std::string_view(p.key) < key; }); + *found = it != root->ptr + root->len && std::string_view(it->key) == key; return it - root->ptr; } void *map_base::_get(const char *key) { int found; - size_t i = ent_find(this, key, &found); + size_t i = ent_find(this, std::string_view(key), &found); return found ? ptr[i].value : 0; } void *map_base::_iget(const char *key) { int found; - size_t i = ent_find(this, key, &found); + size_t i = ent_find(this, LowercasingView(key), &found); return found ? ptr[i].value : 0; } void map_base::_set(const char *key, const void *value, void **oldvalue) { int found; - size_t i = ent_find(this, key, &found); + size_t i = ent_find(this, std::string_view(key), &found); if (found) { if (oldvalue) *oldvalue = ptr[i].value;