]> PatchyGit - patchyircd.git/commitdiff
map: add case-insensitive look up
authorEgor <egor@patchysicp.xyz>
Thu, 22 Jan 2026 14:43:14 +0000 (16:43 +0200)
committerEgor <egor@patchysicp.xyz>
Thu, 22 Jan 2026 14:43:14 +0000 (16:43 +0200)
src/irc.cpp
src/map.cpp
src/map.hpp

index 97dd0a0..29b111f 100644 (file)
@@ -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);
 }
index 2463ccc..721eccf 100644 (file)
@@ -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<auto cmp=strcmp>
 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<istrcmp>(this, key, &found);
+       return found ? ptr[i].value : 0;
+}
 void map_base::_set(const char *key, const void *value, void **oldvalue)
 {
        int found;
index 86e7bc7..3f26a96 100644 (file)
@@ -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<V>(_get(k));
+       }
+       V iget(const char *k) {
+               return static_cast<V>(_iget(k));
        }
 };
 
@@ -128,6 +133,7 @@ protected:
        }
 public:
        const char *get(const char *k) = delete;
+       const char *iget(const char *k) = delete;
 };
 
 #endif