]> PatchyGit - patchyircd.git/commitdiff
map: more c++ification
authorEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 16:26:33 +0000 (18:26 +0200)
committerEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 16:26:33 +0000 (18:26 +0200)
src/admin.cpp
src/common.h
src/irc.cpp
src/main.cpp
src/map.cpp
src/map.h
src/net.cpp

index b059b1a..8257d6d 100644 (file)
@@ -279,11 +279,10 @@ static int fn_channel_new(lua_State *L)
        char key[33];
        memcpy(key, channel, chanlen+1);
        stringlower(key);
-       struct channel *chan = (struct channel *)map_get(&channel_map, key);
+       struct channel *chan = channel_map.get(key);
        if (!chan) {
                chan = channel_new(channel, key, creation ? creation : get_time());
-               if (map_set(&channel_map, key, chan, NULL) == -1)
-                       abort();
+               channel_map.add(chan);
        }
        return 0;
 }
index 3827de8..5d7e02b 100644 (file)
@@ -33,12 +33,12 @@ struct tls;
 #define CAP_SETNAME 128
 #define CAP_ACCOUNTNOTIFY 256
 struct client_data {
+       char   *key; // case-mapped nick
        SOCKET FD;
        struct tls *cctx;
        char   type;
        struct client_data *next;
        char   *nick;
-       char   *key; // case-mapped nick
        char   *username;
        char   *realname;
        char   *hostname;
@@ -106,8 +106,8 @@ struct channel {
 #define DMODE_NOEXTERNAL 8
 #define DMODE_SECRET 16
 #define DMODE_TOPICPROT 32
-#define is_chanop(chan, client) (!!map_get(&(chan)->o, (client)->key))
-#define is_chanvoice(chan, client) (!!map_get(&(chan)->v, (client)->key))
+#define is_chanop(chan, client) (!!(chan)->o.has((client)))
+#define is_chanvoice(chan, client) (!!(chan)->v.has((client)))
 extern clientmap client_map;
 extern channelmap channel_map;
 extern stringset autojoin;
index 0b2373b..290c8e5 100644 (file)
@@ -594,10 +594,9 @@ saslcleanup:
                struct channel *chan = findChannel(args[0]);
                if (!chan)
                        return err_nosuchchannel(client, args[0]), sendbuf(client), 0;
-               if (!map_get(&chan->members, client->key))
+               if (!chan->members.has(client))
                        return err_notonchannel(client, chan), sendbuf(client), 0;
-               if (map_set(&chan->o, client->key, client, NULL) == -1)
-                       abort();
+               chan->o.add(client);
                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick);
                sendbuf_chan(chan);
        } else if(strcmp(command, "JOIN") == 0) {
@@ -606,7 +605,7 @@ saslcleanup:
                if (!args[0])
                        return err_needmoreparams(client, command), sendbuf(client), 0;
                if (!strcmp(args[0], "0")) {
-                       for (struct channel *chan; (chan = (struct channel *)map_pop(&client->channels)); )
+                       for (auto chan : client->channels.pop_view())
                                channel_part(client, chan, "I fell for a classic prank", NULL);
                        return 0;
                }
@@ -649,7 +648,7 @@ saslcleanup:
                        channel_sendtopic(client, chan, 0);
                } else {
                        // TODO: membership check, maybe?
-                       if (chan->dmode & DMODE_TOPICPROT && !map_get(&chan->o, client->key))
+                       if (chan->dmode & DMODE_TOPICPROT && !chan->o.has(client))
                                return 0; // FIXME: error 482
                        channel_topic(client, chan, args[1], client->nick, get_time());
                }
@@ -668,21 +667,19 @@ saslcleanup:
                if (!chan)
                        return err_nosuchchannel(client, args[1]), sendbuf(client), 0;
                if (chan->dmode & DMODE_INVITEONLY) {
-                       if (!map_get(&chan->o, client->key))
+                       if (!chan->o.has(client))
                                return err_chanoprivsneeded(client, chan), sendbuf(client), 0;
                } else {
-                       if (!map_get(&chan->members, client->key))
+                       if (!chan->members.has(client))
                                return err_notonchannel(client, chan), sendbuf(client), 0;
                }
                struct client_data *cl = findClient(args[0]);
                if (!cl)
                        return err_nosuchnick(client, args[0]), sendbuf(client), 0;
-               if (map_get(&chan->members, cl->key))
+               if (chan->members.has(cl))
                        return err_useronchannel(client, cl->nick, chan), sendbuf(client), 0;
-               if (map_set(&chan->invitees, cl->nick, cl, NULL) == -1)
-                       abort();
-               if (map_set(&cl->invites, chan->name, chan, NULL) == -1)
-                       abort();
+               chan->invitees.add(cl);
+               cl->invites.add(chan);
                rpl_inviting(client, cl, chan);
                sendbuf(client);
                msg_invite(client, cl, chan);
@@ -696,9 +693,9 @@ saslcleanup:
                struct channel *chan = findChannel(args[0]);
                if (!chan)
                        return err_nosuchchannel(client, args[0]), sendbuf(client), 0;
-               if (!map_get(&chan->o, client->key))
+               if (!chan->o.has(client))
                        return err_chanoprivsneeded(client, chan), sendbuf(client), 0;
-               if (!map_get(&chan->members, client->key))
+               if (!chan->members.has(client))
                        return err_notonchannel(client, chan), sendbuf(client), 0;
                char *p = args[1];
                do {
@@ -738,11 +735,11 @@ saslcleanup:
                        if (match_list(client, chan->listb) && !match_list(client, chan->liste))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
                        if (chan->dmode & DMODE_INVITEONLY
-                                       && !map_get(&chan->invitees, client->key) && !match_list(client, chan->listI))
+                                       && !chan->invitees.has(client) && !match_list(client, chan->listI))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
-                       if (chan->dmode & DMODE_NOEXTERNAL && !map_get(&chan->members, client->key))
+                       if (chan->dmode & DMODE_NOEXTERNAL && !chan->members.has(client))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
-                       if (chan->dmode & DMODE_MODERATED && !map_get(&chan->v, client->key) && !map_get(&chan->o, client->key))
+                       if (chan->dmode & DMODE_MODERATED && !chan->v.has(client) && !chan->o.has(client))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
 #ifdef HAS_LUA
                        switch (admin_hook("sendtochannel", client, 0, chan, args[1])) {
@@ -912,7 +909,7 @@ saslcleanup:
                                struct channel *chan = findChannel(nick);
                                if (!chan)
                                        return err_nosuchchannel(client, nick), sendbuf(client), 0;
-                               if (!map_get(&chan->o, client->key))
+                               if (!chan->o.has(client))
                                        return 0; // TODO: error
                                if (argc == 2) { // Type A channel modes
                                        int all = !strcmp(args[1], "+0");
@@ -965,7 +962,7 @@ saslcleanup:
                        return err_notregistered(client), sendbuf(client), 0;
                rpl_liststart(client), sendbuf(client);
                for (auto chan : channel_map)
-                       if (client->umode & UMODE_OPER || !(chan->dmode & DMODE_SECRET) || map_get(&chan->members, client->key))
+                       if (client->umode & UMODE_OPER || !(chan->dmode & DMODE_SECRET) || chan->members.has(client))
                                rpl_list(client, chan), sendbuf(client);
                rpl_listend(client), sendbuf(client);
        } else if(strcmp(command, "NAMES") == 0) {
@@ -979,7 +976,7 @@ saslcleanup:
                        if ((p = strchr(channel, ',')))
                                *p++ = '\0';
                        struct channel *chan = findChannel(channel);
-                       if (chan && (!(chan->dmode & DMODE_SECRET) || map_get(&chan->members, client->key))) {
+                       if (chan && (!(chan->dmode & DMODE_SECRET) || chan->members.has(client))) {
                                channel_sendnames(client, chan);
                        } else {
                                rpl_endofnames(client, channel);
@@ -1026,7 +1023,7 @@ saslcleanup:
                                int visible = client->umode & UMODE_OPER || !(cl->umode & UMODE_INVISIBLE) || client == cl;
                                if (!visible) {
                                        for (auto chan : cl->channels) {
-                                               if (map_get(&client->channels, chan->key)) {
+                                               if (client->channels.has(chan)) {
                                                        visible = 1;
                                                        break;
                                                }
@@ -1061,7 +1058,7 @@ saslcleanup:
                        if (cl->away)
                                rpl_away(client, cl), sendbuf(client);
                        for (auto chan : cl->channels) {
-                               if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !map_get(&chan->members, client->key))
+                               if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !chan->members.has(client))
                                        continue;
                                rpl_whoischannels(client, cl, chan), sendbuf(client);
                        }
@@ -1120,7 +1117,7 @@ saslcleanup:
                                        *p++ = '\0';
                                if (client->monitor.add(nick))
                                        monitor_count++;
-                               struct client_data *cl = (struct client_data *)map_get(&client_map, nick);
+                               struct client_data *cl = client_map.get(nick);
                                if (cl)
                                        rpl_mononline(client, cl), sendbuf(client);
                                else
@@ -1153,7 +1150,7 @@ saslcleanup:
                        break;
                case 'S':
                        for (auto key : client->monitor) {
-                               struct client_data *cl = (struct client_data *)map_get(&client_map, key);
+                               struct client_data *cl = client_map.get(key);
                                if (cl)
                                        rpl_mononline(client, cl), sendbuf(client);
                                else
@@ -1310,7 +1307,7 @@ void setNick(struct client_data *client, char* nickname) {
        stringlower(key);
 
        // TODO: make the cia nickname a define
-       if (!strcmp(key, "cia") || map_get(&client_map, key)) {
+       if (!strcmp(key, "cia") || client_map.get(key)) {
                err_nicknameinuse(client, nickname), sendbuf(client);
                return;
        }
@@ -1324,20 +1321,11 @@ void setNick(struct client_data *client, char* nickname) {
                sendbuf(client);
                sendbuf_visible(client);
                rpl_monoffline(0, client->key), sendbuf_monitor(client->key, 0, 0, 0);
-               map_unset(&client_map, client->key, NULL);
+               client_map.remove(client);
                for (auto chan : client->channels) {
-                       map_unset(&chan->members, client->key, NULL);
-                       if (map_set(&chan->members, key, client, NULL) == -1)
-                               abort();
-                       void *old;
-                       map_unset(&chan->o, client->key, &old);
-                       if (old)
-                               if (map_set(&chan->o, key, client, NULL) == -1)
-                                       abort();
-                       map_unset(&chan->v, client->key, &old);
-                       if (old)
-                               if (map_set(&chan->v, key, client, NULL) == -1)
-                                       abort();
+                       chan->members.rename(client, key);
+                       chan->o.rename(client, key);
+                       chan->v.rename(client, key);
                }
                free(client->nick);
                free(client->key);
@@ -1354,8 +1342,7 @@ void setNick(struct client_data *client, char* nickname) {
        client->key = mystrdup(key);
        if (!client->key)
                abort();
-       if (map_set(&client_map, client->key, client, 0) == -1)
-               abort();
+       client_map.add(client);
        rpl_mononline(0, client), sendbuf_monitor(client->key, 0, 0, 0);
        return;
 }
@@ -1418,11 +1405,11 @@ void client_chghost(struct client_data *client, const char *newusername, const c
                        sendbuf_list_sans_self_caps(client, chan->members, 0, 0, CAP_EXTENDEDJOIN|CAP_CHGHOST);
                        msg_join_extended(client, chan);
                        sendbuf_list_sans_self_caps(client, chan->members, 0, CAP_EXTENDEDJOIN, CAP_CHGHOST);
-                       if (map_get(&chan->v, client->key)) {
+                       if (chan->v.has(client)) {
                                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +v %s\r\n", chan->name, client->nick);
                                sendbuf_list_sans_self_caps(client, chan->members, 0, 0, CAP_CHGHOST);
                        }
-                       if (map_get(&chan->o, client->key)) {
+                       if (chan->o.has(client)) {
                                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick);
                                sendbuf_list_sans_self_caps(client, chan->members, 0, 0, CAP_CHGHOST);
                        }
@@ -1487,17 +1474,15 @@ void channel_join(struct client_data *client, const char *channel, const char *c
        char key[33];
        memcpy(key, channel, chanlen+1);
        stringlower(key);
-       struct channel *chan = (struct channel *)map_get(&channel_map, key);
+       struct channel *chan = channel_map.get(key);
        int newchan = !chan;
        if (!chan) {
                chan = channel_new(channel, key, get_time());
                chan->dmode &= ~DMODE_PERSIST;
-               if (map_set(&channel_map, key, chan, NULL) == -1)
-                       abort();
-               if (map_set(&chan->o, client->key, client, NULL) == -1)
-                       abort();
+               channel_map.add(chan);
+               chan->o.add(client);
        } else {
-               if (map_get(&chan->members, client->key))
+               if (chan->members.has(client))
                        return;
                if (chan->chankey && (!chankey || strcmp(chan->chankey, chankey) == 0))
                        return err_badchannelkey(client, chan), sendbuf(client);
@@ -1506,13 +1491,11 @@ void channel_join(struct client_data *client, const char *channel, const char *c
                if (match_list(client, chan->listb) && !match_list(client, chan->liste))
                        return err_bannedfromchan(client, chan), sendbuf(client);
                if (chan->dmode & DMODE_INVITEONLY
-                               && !map_get(&chan->invitees, client->key) && !match_list(client, chan->listI))
+                               && !chan->invitees.has(client) && !match_list(client, chan->listI))
                        return err_inviteonlychan(client, chan), sendbuf(client);
        }
-       if (map_set(&chan->members, client->key, client, NULL) == -1)
-               abort();
-       if (map_set(&client->channels, key, chan, NULL) == -1)
-               abort();
+       chan->members.add(client);
+       client->channels.add(chan);
        chan->member_count++;
        // send JOIN to everyone
        msg_join(client, chan);
@@ -1529,14 +1512,12 @@ void channel_join(struct client_data *client, const char *channel, const char *c
        // TODO: send channel modes to the joining client
        // apply +w modes
        if (match_list(client, chan->listwo)) {
-               if (map_set(&chan->o, client->key, client, NULL) == -1)
-                       abort();
+               chan->o.add(client);
                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick);
                sendbuf_chan(chan);
        }
        if (match_list(client, chan->listwv)) {
-               if (map_set(&chan->v, client->key, client, NULL) == -1)
-                       abort();
+               chan->v.add(client);
                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +v %s\r\n", chan->name, client->nick);
                sendbuf_chan(chan);
        }
@@ -1561,7 +1542,7 @@ struct channel *channel_new(const char *channel, const char *key, time_t creatio
 }
 void channel_part(struct client_data *client, struct channel *chan, const char *reason, struct client_data *kicker)
 {
-       if (!map_get(&chan->members, client->key))
+       if (!chan->members.has(client))
                return;
        if (kicker) {
                msg_kick(kicker, client, chan, reason);
@@ -1570,19 +1551,19 @@ void channel_part(struct client_data *client, struct channel *chan, const char *
                msg_part(client, chan, *reason ? reason : NULL);
                sendbuf_chan(chan);
        }
-       map_unset(&client->channels, chan->key, NULL);
-       map_unset(&chan->members, client->key, NULL);
-       map_unset(&chan->o, client->key, NULL);
-       map_unset(&chan->v, client->key, NULL);
+       client->channels.remove(chan);
+       chan->members.remove(client);
+       chan->o.remove(client);
+       chan->v.remove(client);
        chan->member_count--;
        if (!chan->member_count && !(chan->dmode & DMODE_PERSIST))
                channel_kill(chan);
 }
 void channel_kill(struct channel *chan)
 {
-       map_unset(&channel_map, chan->key, NULL);
+       channel_map.remove(chan);
        for (auto cl : chan->invitees)
-               map_unset(&cl->invites, chan->key, NULL);
+               cl->invites.remove(chan);
        free(chan->key);
        free(chan->name);
        free(chan->topic);
@@ -1743,13 +1724,16 @@ void channel_mode(struct client_data *client, struct channel *chan, char *args[]
                                        err_nosuchnick(client, nick), sendbuf(client);
                                break;
                        }
-                       if (!map_get(&chan->members, cl->key)) {
+                       if (!chan->members.has(cl)) {
                                if (client)
                                        err_usernotinchannel(client, cl->nick, chan), sendbuf(client);
                                break;
                        }
-                       if (map_set(*p == 'o' ? &chan->o : &chan->v, cl->key, is_plus ? cl : NULL, NULL) == -1)
-                               abort();
+                       clientmap &clmap = *p == 'o' ? chan->o : chan->v;
+                       if (is_plus)
+                               clmap.add(cl);
+                       else
+                               clmap.remove(cl);
                        copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
                                        n, u, h, chan->name, is_plus?"+":"-", which, cl->nick);
                        sendbuf_chan(chan);
@@ -1794,7 +1778,7 @@ struct client_data *findClient(const char *nickname)
                return NULL;
        memcpy(key, nickname, len+1);
        stringlower(key);
-       return (struct client_data *)map_get(&client_map, key);
+       return client_map.get(key);
 }
 struct channel *findChannel(const char *channel)
 {
@@ -1804,5 +1788,5 @@ struct channel *findChannel(const char *channel)
        char key[33];
        memcpy(key, channel, chanlen+1);
        stringlower(key);
-       return (struct channel *)map_get(&channel_map, key);
+       return channel_map.get(key);
 }
index 6ae8fdb..2eb65c4 100644 (file)
@@ -211,8 +211,7 @@ int main(int argc, char *argv[])
                } else if(!strcmp(argv[i], "--autojoin")) {
                        if (i + 1 >= argc)
                                return fprintf(stderr, "not enough parameters\n"), 1;
-                       if (map_set(&autojoin, argv[i+1], (void*)1, NULL) == -1)
-                               abort();
+                       autojoin.add(argv[i+1]);
                        i += 1;
                } else {
                        return fprintf(stderr, "unknown flag '%s'\n", argv[i]), 1;
@@ -383,7 +382,7 @@ int main(int argc, char *argv[])
 #endif
        free(databuf.buf);
        /* free any persistent channels */
-       for (struct channel *chan; (chan = (struct channel *)map_pop(&channel_map)); )
+       for (auto chan : channel_map.pop_view())
                channel_kill(chan);
        map_free(&client_map);
        map_free(&channel_map);
index dbe039f..b5e0f4a 100644 (file)
@@ -1,3 +1,4 @@
+#include "common.h"
 #include "map.h"
 #include <stdlib.h>
 #include <string.h>
@@ -85,7 +86,3 @@ int map_foriter(map_iter_t *it, const char **outkey, void *outvalue)
        it->index++;
        return 1;
 }
-void *map_pop(map_base *root)
-{
-       return root->len ? root->ptr[root->len-1].value : 0;
-}
index 5fe0c90..475311e 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -19,9 +19,6 @@ struct map_value {
 struct map_base {
        struct map_value *ptr;
        size_t len, cap;
-       size_t size() {
-               return len;
-       }
 };
 typedef struct map_iter {
        map_base *root;
@@ -45,11 +42,9 @@ void *map_get(map_base *root, const char *key);
 /* Associate a new value with a given key.
  * Returns 0 on success, -1 on allocation error.
  * If oldvalue is not NULL, it receives the old value of key.
+ * No allocation failures on value = NULL.
  * Dynarr complexity: O(n) */
 NODISCARD int map_set(map_base *root, const char *key, const void *value, void **oldvalue);
-/* Remove a key.
- * Same as associating a key to NULL. No allocation failures. */
-#define map_unset(root, key, oldvalue) ((void)map_set((root), (key), 0, (oldvalue)))
 /* Removes all keys from the map and frees any associated memory.
  * The map_t is reset to zero-initialized state and can be used again.
  * Dynarr complexity: O(n) */
@@ -65,70 +60,95 @@ void map_free(map_base *root);
  * Returns 0 on end of iteration, 1 otherwise.
  */
 NODISCARD int map_foriter(map_iter_t *f, const char **outkey, void *outvalue);
-#define map_foreach(rootp, outkey, outvalue) \
-       for (map_iter_t map_itertmp = { .root = rootp, .index = 0 }; map_foriter(&map_itertmp, outkey, outvalue); )
-/* Return a value from the map.
- * No guarantees about which one!
- * You don't get a key and the association is not removed.
- * Returns 0 if the map is empty.
- *
- * Typical use:
- * for (value_type *v; v = map_pop(&map); )
- *     map_unset(&map, v->key, 0);
- *     free(v);
- * }
- * map_free(&map);
- */
-NODISCARD void *map_pop(map_base *root);
 
 #include <utility>
+#include <iterator>
 #include <stdlib.h>
-template<typename T>
-struct iterator_base {
-       T *ptr;
-       iterator_base &operator++() { ++ptr; return *this; }
-       bool operator!=(iterator_base other) { return ptr != other.ptr; }
-};
 struct client_data;
 struct channel;
 
-struct clientmap : map_base {
-       struct iterator : iterator_base<map_value> {
-               auto operator*() { return (struct client_data *)ptr->value; }
+template<typename T, typename V>
+struct map_base2 : map_base {
+       using value_type = V;
+       struct iterator {
+               using iterator_category = std::bidirectional_iterator_tag;
+               using value_type = V;
+               using difference_type = ptrdiff_t;
+               using pointer = void;
+               using reference = V;
+               iterator &operator++() { ++ptr; return *this; }
+               iterator operator++(int) { auto it = *this; ++ptr; return it; }
+               iterator &operator--() { --ptr; return *this; }
+               iterator operator--(int) { auto it = *this; --ptr; return it; }
+               bool operator==(const iterator& other) const = default;
+               reference operator*() const { return T::to_value(ptr); }
+               map_value *ptr;
        };
+       static_assert(std::bidirectional_iterator<iterator>);
        auto begin() { return iterator{ptr}; }
        auto end() { return iterator{ptr+len}; }
-};
-struct channelmap : map_base {
-       struct iterator : iterator_base<map_value> {
-               auto operator*() { return (struct channel *)ptr->value; }
+       struct reverse {
+               map_base2 &obj;
+               auto begin() { return std::make_reverse_iterator(obj.end()); }
+               auto end() { return std::make_reverse_iterator(obj.begin()); }
        };
-       auto begin() { return iterator{ptr}; }
-       auto end() { return iterator{ptr+len}; }
-};
-struct stringset : map_base {
+       // Iterate over keys of the map in such a way that you can delete them.
+       auto pop_view() {
+               return reverse{*this};
+       }
        void clear() {
                map_free(this);
        }
-       bool has(const char *key) {
-               return !!map_get(this, key);
+       size_t size() {
+               return len;
+       }
+protected:
+       static const char *to_key(V v) {
+               return v->key;
+       }
+       static V to_value(map_value *v) {
+               return static_cast<V>(v->value);
        }
-       bool add(const char *key) {
+public:
+       bool has(V v) {
+               return !!map_get(this, T::to_key(v));
+       }
+       bool add(V v) {
                void *old;
-               if (map_set(this, key, (void *)1, &old) == -1)
+               if (map_set(this, T::to_key(v), v, &old) == -1)
                        abort();
                return !old;
        }
-       bool remove(const char *key) {
+       bool remove(V v) {
                void *old;
-               map_unset(this, key, &old);
+               (void)map_set(this, T::to_key(v), 0, &old);
                return !!old;
        }
-       struct iterator : iterator_base<map_value> {
-               auto operator*() { return (const char *)ptr->key; }
-       };
-       auto begin() { return iterator{ptr}; }
-       auto end() { return iterator{ptr+len}; }
+
+       V get(const char *k) {
+               return (V)map_get(this, k);
+       }
+};
+
+struct clientmap : map_base2<clientmap, struct client_data *> {
+       void rename(struct client_data *v, const char *newk) {
+               if (remove(v) && map_set(this, newk, v, 0) == -1)
+                       abort();
+       }
+};
+struct channelmap : map_base2<channelmap, struct channel *> {
+};
+struct stringset : map_base2<stringset, const char *> {
+protected:
+       friend map_base2;
+       static const char *to_key(const char *v) {
+               return v;
+       }
+       static const char *to_value(map_value *v) {
+               return v->key;
+       }
+public:
+       const char *get(const char *k) = delete;
 };
 
 #endif
index d9d5b3d..f0ab00b 100644 (file)
@@ -66,18 +66,17 @@ void killConnection(struct client_data *cl, int byChoice)
        }
        update_poll_reg(cl);
        /* Part all channels */
-       for (struct channel *chan; (chan = (struct channel *)map_pop(&cl->channels)); )
+       for (auto chan : cl->channels.pop_view())
                channel_part(cl, chan, NULL, NULL);
        /* Remove from client_map and get rid of the pending invites */
        if (cl->key) {
 #ifdef HAS_LUA
                admin_hook("nickdel", cl, 0, 0, cl->key);
 #endif
-               map_unset(&client_map, cl->key, NULL);
+               client_map.remove(cl);
                rpl_monoffline(0, cl->key), sendbuf_monitor(cl->key, 0, 0, 0);
-               struct channel *chan;
-               map_foreach(&cl->invites, 0, &chan)
-                       map_unset(&chan->invitees, cl->key, NULL);
+               for (auto chan : cl->invites)
+                       chan->invitees.remove(cl);
        }
        map_free(&cl->channels);
        map_free(&cl->invites);