]> PatchyGit - patchyircd.git/commitdiff
map: start c++ifying
authorEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 12:36:51 +0000 (14:36 +0200)
committerEgor <egor@patchysicp.xyz>
Sun, 2 Mar 2025 12:36:51 +0000 (14:36 +0200)
src/irc.cpp
src/map.h

index c9cd878..0b2373b 100644 (file)
@@ -28,17 +28,15 @@ static void chanlog(void) {
        }
 }
 static void sendbuf_chan_caps(struct channel *chan, unsigned positive, unsigned negative) {
-       struct client_data *cl;
-       map_foreach(&chan->members, 0, &cl)
+       for (auto cl : chan->members)
                if (!(~cl->caps & positive) && !(cl->caps & negative))
                        sendbuf(cl);
 }
 static void sendbuf_chan(struct channel *chan) {
        sendbuf_chan_caps(chan, 0, 0);
 }
-static void sendbuf_list_sans_self_caps(struct client_data *client, clientmap *ls, int cookie, int positive, int negative) {
-       struct client_data *cl;
-       map_foreach(ls, 0, &cl)
+static void sendbuf_list_sans_self_caps(struct client_data *client, clientmap &ls, int cookie, int positive, int negative) {
+       for (auto cl : ls)
                if (client != cl) {
                        if (cookie) {
                                if (cookie != cl->cookie)
@@ -50,14 +48,13 @@ static void sendbuf_list_sans_self_caps(struct client_data *client, clientmap *l
                                sendbuf(cl);
                }
 }
-static void sendbuf_list_sans_self(struct client_data *client, clientmap *ls, int cookie) {
+static void sendbuf_list_sans_self(struct client_data *client, clientmap &ls, int cookie) {
        sendbuf_list_sans_self_caps(client, ls, cookie, 0, 0);
 }
 void sendbuf_monitor(const char *nick, int cookie, int positive, int negative)
 {
-       struct client_data *cl;
-       map_foreach(&client_map, 0, &cl)
-               if (map_get(&cl->monitor, nick)) {
+       for (auto cl : client_map)
+               if (cl->monitor.has(nick)) {
                        if (cookie) {
                                if (cookie != cl->cookie)
                                        cl->cookie = cookie;
@@ -72,8 +69,7 @@ static int get_cookie(void) {
        static int cookie = 0;
        if (++cookie == 0) {
                // handle overflow
-               struct client_data *cl;
-               map_foreach(&client_map, 0, &cl)
+               for (auto cl : client_map)
                        cl->cookie = 0;
                cookie++;
        }
@@ -81,9 +77,8 @@ static int get_cookie(void) {
 }
 static int sendbuf_visible_caps(struct client_data *client, int positive, int negative) {
        int cookie = get_cookie();
-       struct channel *chan;
-       map_foreach(&client->channels, 0, &chan)
-               sendbuf_list_sans_self_caps(client, &chan->members, cookie, positive, negative);
+       for (auto chan : client->channels)
+               sendbuf_list_sans_self_caps(client, chan->members, cookie, positive, negative);
        return cookie;
 }
 void sendbuf_visible(struct client_data *client) {
@@ -102,10 +97,9 @@ const char *format_umodes(struct client_data *cl) {
        *p++ = '\0';
        return umodes;
 }
-static int match_list(struct client_data *cl, stringset *list)
+static int match_list(struct client_data *cl, stringset &list)
 {
-       const char *key;
-       map_foreach(list, &key, 0)
+       for (auto key : list)
                if (irc_glob(cl->nuh, key))
                        return 1;
        return 0;
@@ -569,8 +563,7 @@ saslcleanup:
                if (!(client->umode & UMODE_OPER))
                        return err_noprivileges(client), sendbuf(client), 0;
                msg_wallops(client, args[0]);
-               struct client_data *cl;
-               map_foreach(&client_map, 0, &cl)
+               for (auto cl : client_map)
                        if (cl->umode & UMODE_WALLOPS)
                                sendbuf(cl);
        } else if(strcmp(command, "KILL") == 0) {
@@ -586,8 +579,7 @@ saslcleanup:
                if (client == cl)
                        return 0; // FIXME: error message
                msg_kill(client, cl, args[1] ? args[1] : "(no reason)");
-               struct client_data *cl2;
-               map_foreach(&client_map, 0, &cl2)
+               for (auto cl2 : client_map)
                        if (cl2->umode & UMODE_OPER)
                                sendbuf(cl2);
                // FIXME: add appropraite QUIT message
@@ -666,8 +658,7 @@ saslcleanup:
                        return err_notregistered(client), sendbuf(client), 0;
                if (!args[0]) {
                        // List pending invites
-                       struct channel *chan;
-                       map_foreach(&client->invites, 0, &chan)
+                       for (auto chan : client->invites)
                                rpl_invitelist(client, chan), sendbuf(client);
                        return rpl_endofinvitelist(client), sendbuf(client), 0;
                }
@@ -742,12 +733,12 @@ saslcleanup:
                        struct channel *chan = findChannel(args[0]+is_modmsg);
                        if (!chan)
                                return err_nosuchchannel(client, args[0]), sendbuf(client), 0;
-                       if (match_list(client, &chan->listq))
+                       if (match_list(client, chan->listq))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
-                       if (match_list(client, &chan->listb) && !match_list(client, &chan->liste))
+                       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))
+                                       && !map_get(&chan->invitees, client->key) && !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))
                                return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
@@ -765,13 +756,13 @@ saslcleanup:
                        }
 #endif
                        if (!is_modmsg) {
-                               sendbuf_list_sans_self(client, &chan->members, 0);
+                               sendbuf_list_sans_self(client, chan->members, 0);
                        } else if (memchr(args[0], '+', is_modmsg)) {
                                int cookie = get_cookie();
-                               sendbuf_list_sans_self(client, &chan->v, cookie);
-                               sendbuf_list_sans_self(client, &chan->o, cookie);
+                               sendbuf_list_sans_self(client, chan->v, cookie);
+                               sendbuf_list_sans_self(client, chan->o, cookie);
                        } else {
-                               sendbuf_list_sans_self(client, &chan->o, 0);
+                               sendbuf_list_sans_self(client, chan->o, 0);
                        }
                } else {
                        struct client_data *cl = findClient(args[0]);
@@ -924,7 +915,6 @@ saslcleanup:
                                if (!map_get(&chan->o, client->key))
                                        return 0; // TODO: error
                                if (argc == 2) { // Type A channel modes
-                                       const char *key;
                                        int all = !strcmp(args[1], "+0");
                                        int any = 0;
                                        if (all) {
@@ -933,33 +923,33 @@ saslcleanup:
                                                any = 1;
                                        }
                                        if (all || !strcmp(args[1], "+b") || !strcmp(args[1], "b")) {
-                                               map_foreach(&chan->listb, &key, 0)
+                                               for (auto key : chan->listb)
                                                        rpl_banlist(client, chan, key), sendbuf(client);
                                                rpl_endofbanlist(client, chan), sendbuf(client);
                                                any = 1;
                                        }
                                        if (all || !strcmp(args[1], "+e") || !strcmp(args[1], "e")) {
-                                               map_foreach(&chan->liste, &key, 0)
+                                               for (auto key : chan->liste)
                                                        rpl_exceptlist(client, chan, key), sendbuf(client);
                                                rpl_endofexceptlist(client, chan), sendbuf(client);
                                                any = 1;
                                        }
                                        if (all || !strcmp(args[1], "+I") || !strcmp(args[1], "I")) {
-                                               map_foreach(&chan->listI, &key, 0)
+                                               for (auto key : chan->listI)
                                                        rpl_invexlist(client, chan, key), sendbuf(client);
                                                rpl_endofinvexlist(client, chan), sendbuf(client);
                                                any = 1;
                                        }
                                        if (all || !strcmp(args[1], "+q") || !strcmp(args[1], "q")) {
-                                               map_foreach(&chan->listq, &key, 0)
+                                               for (auto key : chan->listq)
                                                        rpl_quietlist(client, chan, key), sendbuf(client);
                                                rpl_endofquietlist(client, chan), sendbuf(client);
                                                any = 1;
                                        }
                                        if (all || !strcmp(args[1], "+w") || !strcmp(args[1], "w")) {
-                                               map_foreach(&chan->listwo, &key, 0)
+                                               for (auto key : chan->listwo)
                                                        rpl_accesslist(client, chan, 'o', key), sendbuf(client);
-                                               map_foreach(&chan->listwv, &key, 0)
+                                               for (auto key : chan->listwv)
                                                        rpl_accesslist(client, chan, 'v', key), sendbuf(client);
                                                rpl_endofaccesslist(client, chan), sendbuf(client);
                                                any = 1;
@@ -974,8 +964,7 @@ saslcleanup:
                if (!is_registered(client))
                        return err_notregistered(client), sendbuf(client), 0;
                rpl_liststart(client), sendbuf(client);
-               struct channel *chan;
-               map_foreach(&channel_map, 0, &chan)
+               for (auto chan : channel_map)
                        if (client->umode & UMODE_OPER || !(chan->dmode & DMODE_SECRET) || map_get(&chan->members, client->key))
                                rpl_list(client, chan), sendbuf(client);
                rpl_listend(client), sendbuf(client);
@@ -1022,8 +1011,7 @@ saslcleanup:
                        struct channel *chan = findChannel(args[0]);
                        // TODO: handle chanmode +s, umode +i
                        if (chan) {
-                               struct client_data *cl;
-                               map_foreach(&chan->members, 0, &cl)
+                               for (auto cl : chan->members)
                                        (args[1] ? rpl_whospcrpl(client, cl, chan, args[1]) : rpl_whoreply(client, cl, chan)), sendbuf(client);
                        }
                } else if (!strchr(args[0], '*')) {
@@ -1032,14 +1020,12 @@ saslcleanup:
                        if (cl)
                                (args[1] ? rpl_whospcrpl(client, cl, 0, args[1]) : rpl_whoreply(client, cl, 0)), sendbuf(client);
                } else {
-                       struct client_data *cl;
-                       map_foreach(&client_map, 0, &cl) {
+                       for (auto cl : client_map) {
                                if (!irc_glob(cl->nuh, args[0]))
                                        continue;
                                int visible = client->umode & UMODE_OPER || !(cl->umode & UMODE_INVISIBLE) || client == cl;
                                if (!visible) {
-                                       struct channel *chan;
-                                       map_foreach(&cl->channels, 0, &chan) {
+                                       for (auto chan : cl->channels) {
                                                if (map_get(&client->channels, chan->key)) {
                                                        visible = 1;
                                                        break;
@@ -1074,8 +1060,7 @@ saslcleanup:
                        rpl_whoisidle(client, cl), sendbuf(client);
                        if (cl->away)
                                rpl_away(client, cl), sendbuf(client);
-                       struct channel *chan;
-                       map_foreach(&cl->channels, 0, &chan) {
+                       for (auto chan : cl->channels) {
                                if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !map_get(&chan->members, client->key))
                                        continue;
                                rpl_whoischannels(client, cl, chan), sendbuf(client);
@@ -1125,9 +1110,7 @@ saslcleanup:
                        if (strchr(args[1], ' '))
                                return err_needmoreparams(client, command), sendbuf(client), 0; /* FIXME: wrong error */
                        stringlower(args[1]);
-                       int monitor_count = 0;
-                       map_foreach(&client->monitor, 0, 0)
-                               monitor_count++;
+                       int monitor_count = client->monitor.size();
                        char *p = args[1];
                        do {
                                char *nick = p;
@@ -1135,10 +1118,8 @@ saslcleanup:
                                        return rpl_monlistfull(client, MONITOR_LIMIT,nick), sendbuf(client), 0;
                                if ((p = strchr(nick, ',')))
                                        *p++ = '\0';
-                               char *existing;
-                               if (map_set(&client->monitor, nick, /* dummy */ nick, (void **)&existing) == -1)
-                                       abort();
-                               monitor_count += !existing;
+                               if (client->monitor.add(nick))
+                                       monitor_count++;
                                struct client_data *cl = (struct client_data *)map_get(&client_map, nick);
                                if (cl)
                                        rpl_mononline(client, cl), sendbuf(client);
@@ -1158,23 +1139,20 @@ saslcleanup:
                                char *nick = p;
                                if ((p = strchr(nick, ',')))
                                        *p++ = '\0';
-                               map_unset(&client->monitor, nick, 0);
+                               client->monitor.remove(nick);
                        } while (p);
                        break;
                }
                case 'C':
-                       map_free(&client->monitor);
+                       client->monitor.clear();
                        break;
-               case 'L': {
-                       const char *key;
-                       map_foreach(&client->monitor, &key, 0)
+               case 'L':
+                       for (auto key : client->monitor)
                                rpl_monlist(client, key), sendbuf(client);
                        rpl_endofmonlist(client), sendbuf(client);
                        break;
-               }
-               case 'S': {
-                       const char *key;
-                       map_foreach(&client->monitor, &key, 0) {
+               case 'S':
+                       for (auto key : client->monitor) {
                                struct client_data *cl = (struct client_data *)map_get(&client_map, key);
                                if (cl)
                                        rpl_mononline(client, cl), sendbuf(client);
@@ -1182,7 +1160,6 @@ saslcleanup:
                                        rpl_monoffline(client, key), sendbuf(client);
                        }
                        break;
-               }
                default:
                        return err_needmoreparams(client, command), sendbuf(client), 0; /* FIXME: wrong error */
                }
@@ -1255,8 +1232,7 @@ void newUser(struct client_data *client) {
 #ifdef HAS_LUA
        admin_hook("newuser", client, 0, 0, 0);
 #endif
-       const char *key;
-       map_foreach(&autojoin, &key, 0)
+       for (auto key : autojoin)
                channel_join(client, key, NULL);
 }
 void sendLUSERS(struct client_data *client)
@@ -1265,17 +1241,14 @@ void sendLUSERS(struct client_data *client)
        int registered = 0;
        int invisible = 0;
        int ops = 0;
-       int channels = 0;
-       struct client_data *cl;
-       map_foreach(&client_map, 0, &cl) {
+       int channels = channel_map.size();
+       for (auto cl : client_map) {
                registered++;
                if (cl->umode & UMODE_INVISIBLE)
                        invisible++;
                if (cl->umode & UMODE_OPER)
                        ops++;
        }
-       map_foreach(&channel_map, 0, 0)
-               channels++;
        for (struct client_data *cl = clients; cl; cl = cl->next)
                total++;
 
@@ -1352,8 +1325,7 @@ void setNick(struct client_data *client, char* nickname) {
                sendbuf_visible(client);
                rpl_monoffline(0, client->key), sendbuf_monitor(client->key, 0, 0, 0);
                map_unset(&client_map, client->key, NULL);
-               struct channel *chan;
-               map_foreach(&client->channels, 0, &chan) {
+               for (auto chan : client->channels) {
                        map_unset(&chan->members, client->key, NULL);
                        if (map_set(&chan->members, key, client, NULL) == -1)
                                abort();
@@ -1441,19 +1413,18 @@ void client_chghost(struct client_data *client, const char *newusername, const c
 
        // now we have to simulate rejoins for clients without chghost support
        if (is_registered(client)) {
-               struct channel *chan;
-               map_foreach(&client->channels, 0, &chan) {
+               for (auto chan : client->channels) {
                        msg_join(client, chan);
-                       sendbuf_list_sans_self_caps(client, &chan->members, 0, 0, CAP_EXTENDEDJOIN|CAP_CHGHOST);
+                       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);
+                       sendbuf_list_sans_self_caps(client, chan->members, 0, CAP_EXTENDEDJOIN, CAP_CHGHOST);
                        if (map_get(&chan->v, client->key)) {
                                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);
+                               sendbuf_list_sans_self_caps(client, chan->members, 0, 0, CAP_CHGHOST);
                        }
                        if (map_get(&chan->o, client->key)) {
                                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);
+                               sendbuf_list_sans_self_caps(client, chan->members, 0, 0, CAP_CHGHOST);
                        }
                }
                if (changedacc) {
@@ -1492,8 +1463,7 @@ void channel_sendtopic(struct client_data *client, struct channel *chan, int joi
 void channel_sendnames(struct client_data *client, struct channel *chan)
 {
        databuf.len = 0;
-       struct client_data *cl;
-       map_foreach(&chan->members, 0, &cl)
+       for (auto cl : chan->members)
                if (rpl_namreply(client, chan, cl)) {
                        sendbuf(client);
                        databuf.len = 0;
@@ -1533,10 +1503,10 @@ void channel_join(struct client_data *client, const char *channel, const char *c
                        return err_badchannelkey(client, chan), sendbuf(client);
                if (chan->member_limit != -1 && chan->member_count >= chan->member_limit)
                        return err_channelisfull(client, chan), sendbuf(client);
-               if (match_list(client, &chan->listb) && !match_list(client, &chan->liste))
+               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))
+                               && !map_get(&chan->invitees, client->key) && !match_list(client, chan->listI))
                        return err_inviteonlychan(client, chan), sendbuf(client);
        }
        if (map_set(&chan->members, client->key, client, NULL) == -1)
@@ -1554,17 +1524,17 @@ void channel_join(struct client_data *client, const char *channel, const char *c
        // send AWAY
        if (client->away) {
                msg_away(client);
-               sendbuf_list_sans_self_caps(client, &chan->members, 0, CAP_AWAYNOTIFY, 0);
+               sendbuf_list_sans_self_caps(client, chan->members, 0, CAP_AWAYNOTIFY, 0);
        }
        // TODO: send channel modes to the joining client
        // apply +w modes
-       if (match_list(client, &chan->listwo)) {
+       if (match_list(client, chan->listwo)) {
                if (map_set(&chan->o, client->key, client, NULL) == -1)
                        abort();
                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 (match_list(client, chan->listwv)) {
                if (map_set(&chan->v, client->key, client, NULL) == -1)
                        abort();
                copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +v %s\r\n", chan->name, client->nick);
@@ -1611,8 +1581,7 @@ void channel_part(struct client_data *client, struct channel *chan, const char *
 void channel_kill(struct channel *chan)
 {
        map_unset(&channel_map, chan->key, NULL);
-       struct client_data *cl;
-       map_foreach(&chan->invitees, 0, &cl)
+       for (auto cl : chan->invitees)
                map_unset(&cl->invites, chan->key, NULL);
        free(chan->key);
        free(chan->name);
@@ -1751,8 +1720,10 @@ void channel_mode(struct client_data *client, struct channel *chan, char *args[]
                        if (strchr(mask, ' '))
                                break; // TODO: error msg
                        stringlower(mask);
-                       if (map_set(list, mask, is_plus ? mask /* dummy */ : NULL, NULL) == -1)
-                               abort();
+                       if (is_plus)
+                               list->add(mask);
+                       else
+                               list->remove(mask);
                        char which[2] = {*p, 0};
                        copy_strf(&databuf, ":%s!%s@%s MODE %s %s%s %s\r\n",
                                        n, u, h, chan->name, is_plus?"+":"-", which, mask);
index b4c79a1..5fe0c90 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -19,19 +19,15 @@ 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;
        size_t index;
 } map_iter_t;
 
-struct clientmap : map_base {
-};
-struct channelmap : map_base {
-};
-struct stringset : map_base {
-};
-
 /* A map abstract data type with following properties:
  * - keys are lexicographically-sorted unique NUL-terminated strings
  * - values are non-NULL pointers
@@ -84,4 +80,55 @@ NODISCARD int map_foriter(map_iter_t *f, const char **outkey, void *outvalue);
  * map_free(&map);
  */
 NODISCARD void *map_pop(map_base *root);
+
+#include <utility>
+#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; }
+       };
+       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; }
+       };
+       auto begin() { return iterator{ptr}; }
+       auto end() { return iterator{ptr+len}; }
+};
+struct stringset : map_base {
+       void clear() {
+               map_free(this);
+       }
+       bool has(const char *key) {
+               return !!map_get(this, key);
+       }
+       bool add(const char *key) {
+               void *old;
+               if (map_set(this, key, (void *)1, &old) == -1)
+                       abort();
+               return !old;
+       }
+       bool remove(const char *key) {
+               void *old;
+               map_unset(this, key, &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}; }
+};
+
 #endif