#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<auto cmp=strcmp>
-static size_t ent_find(map_base *root, const char *key, int *found)
+
+template<typename A, typename B>
+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, LowercasingView> {
+ 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<istrcmp>(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;