From 73b3ce068d86b1c9e72a92d3d8a95c17b499116d Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 22 Jan 2026 16:43:14 +0200 Subject: [PATCH] map: add case-insensitive look up --- src/irc.cpp | 22 ++++------------------ src/map.cpp | 25 ++++++++++++++++++++++--- src/map.hpp | 10 ++++++++-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/irc.cpp b/src/irc.cpp index 97dd0a0..29b111f 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -1785,23 +1785,9 @@ void channel_topic(Client *src, Channel *chan, const char *topic, const char *wh chanlog_time(chan->topic_when); sendbuf_chan(chan); } -Client *findClient(const char *nickname) -{ - char key[MAX_NICKLEN]; - size_t len = strlen(nickname); - if (len >= MAX_NICKLEN) - return NULL; - memcpy(key, nickname, len+1); - stringlower(key); - return client_map.get(key); +Client *findClient(const char *nickname) { + return client_map.iget(nickname); } -Channel *findChannel(const char *channel) -{ - size_t chanlen = strlen(channel); - if (chanlen >= MAX_CHANLEN) - return NULL; - char key[MAX_CHANLEN]; - memcpy(key, channel, chanlen+1); - stringlower(key); - return channel_map.get(key); +Channel *findChannel(const char *channel) { + return channel_map.iget(channel); } diff --git a/src/map.cpp b/src/map.cpp index 2463ccc..721eccf 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,13 +1,26 @@ -// Copyright (c) 2023, 2025 Egor +// Copyright (c) 2023, 2025-2026 Egor // SPDX-License-Identifier: GPL-2.0-or-later #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) { auto it = std::partition_point(root->ptr, root->ptr + root->len, - [key](const auto &p){ return strcmp(p.key, key) < 0; }); - *found = it != root->ptr + root->len && !strcmp(it->key, key); + [key](const auto &p){ return cmp(p.key, key) < 0; }); + *found = it != root->ptr + root->len && !cmp(it->key, key); return it - root->ptr; } void *map_base::_get(const char *key) @@ -16,6 +29,12 @@ void *map_base::_get(const char *key) size_t i = ent_find(this, 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); + return found ? ptr[i].value : 0; +} void map_base::_set(const char *key, const void *value, void **oldvalue) { int found; diff --git a/src/map.hpp b/src/map.hpp index 86e7bc7..3f26a96 100644 --- a/src/map.hpp +++ b/src/map.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023, 2025 Egor +// Copyright (c) 2023, 2025-2026 Egor // SPDX-License-Identifier: GPL-2.0-or-later #ifndef MAP_H_ #define MAP_H_ @@ -24,6 +24,8 @@ struct map_base { /* Return the associated value for a given key. * Dynarr complexity: O(log n) */ void *_get(const char *key); + /* _get() but lowercase the key */ + void *_iget(const char *key); /* Associate a new value with a given key. * If oldvalue is not NULL, it receives the old value of key. * No allocation failures on value = NULL. @@ -103,7 +105,10 @@ public: } V get(const char *k) { - return (V)_get(k); + return static_cast(_get(k)); + } + V iget(const char *k) { + return static_cast(_iget(k)); } }; @@ -128,6 +133,7 @@ protected: } public: const char *get(const char *k) = delete; + const char *iget(const char *k) = delete; }; #endif -- 2.56.0