From: Egor Date: Sun, 2 Mar 2025 12:36:51 +0000 (+0200) Subject: map: start c++ifying X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=c18dfef914712011527d8994ba9afd0e9208050a;p=patchyircd.git map: start c++ifying --- diff --git a/src/irc.cpp b/src/irc.cpp index c9cd878..0b2373b 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -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); diff --git a/src/map.h b/src/map.h index b4c79a1..5fe0c90 100644 --- 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 +#include +template +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 { + 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 { + 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 { + auto operator*() { return (const char *)ptr->key; } + }; + auto begin() { return iterator{ptr}; } + auto end() { return iterator{ptr+len}; } +}; + #endif