From: Egor Date: Sun, 8 Feb 2026 13:28:45 +0000 (+0200) Subject: map: get rid of map_base2 X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=ad51cf3dbd05a10abb2e9f567e1db724bcee5ca9;p=patchyircd.git map: get rid of map_base2 --- diff --git a/src/admin.cpp b/src/admin.cpp index e37bcd2..9292540 100644 --- a/src/admin.cpp +++ b/src/admin.cpp @@ -44,7 +44,7 @@ static void push(lua_State *L, Channel *chan); template struct SetRef { - map_base2 &s; + FlatSet> &s; static consteval const char *get_mtname() { if constexpr (std::same_as) { @@ -61,24 +61,25 @@ struct SetRef { int index(lua_State *L) { std::string_view key = checkstringview(L, 2); - if (!s.has(key)) + if (!s.contains(key)) return 0; - push(L, s.get(key)); + auto it = s.find(key); + push(L, it != s.end() ? *it : T()); return 1; } int newindex(lua_State *L) { std::string_view key = checkstringview(L, 2); luaL_checkany(L, 3); if (lua_isnil(L, 3)) { - s.remove(key); + s.erase(key); return 0; } if constexpr (std::same_as) { - s.add(key); + s.insert(key); } else if constexpr (std::same_as) { - s.add(*(Client **)luaL_checkudata(L, 3, "Client")); + s.insert(*(Client **)luaL_checkudata(L, 3, "Client")); } else if constexpr (std::same_as) { - s.add(*(Channel **)luaL_checkudata(L, 3, "Channel")); + s.insert(*(Channel **)luaL_checkudata(L, 3, "Channel")); } else { static_assert(false); } @@ -100,10 +101,9 @@ struct SetRef { size_t index = 0; int next(lua_State *L) { lua_getiuservalue(L, 1, 1); - SetRef &ref = *static_cast(lua_touserdata(L, -1)); - auto &m = ref.s.m; - auto it = m.begin() + index; - if (it == m.end()) + auto &s = static_cast(lua_touserdata(L, -1))->s; + auto it = s.begin() + index; + if (it == s.end()) return 0; index++; push(L, to_key(*it)); @@ -119,7 +119,7 @@ struct SetRef { lua_pushnil(L); return 3; } - static void _push(lua_State *L, map_base2 &s) { + static void _push(lua_State *L, FlatSet> &s) { pushreftype(L, s); } static void regmt(lua_State *L) { @@ -138,7 +138,7 @@ struct SetRef { } }; template -static void push(lua_State *L, map_base2 &s) { +static void push(lua_State *L, FlatSet> &s) { SetRef::_push(L, s); } @@ -330,12 +330,13 @@ static int fn_channel_new(lua_State *L) size_t chanlen = strlen(channel); if (chanlen > 32) luaL_error(L, "channel name length too long!"); - char key[33]; - memcpy(key, channel, chanlen+1); - stringlower(key); - Channel *chan = channel_map.get(key); - if (!chan) + Channel *chan = findChannel(channel); + if (!chan) { + char key[33]; + memcpy(key, channel, chanlen+1); + stringlower(key); chan = new Channel(channel, key, creation ? creation : get_time()); + } return 0; } static int fn_channel_mode(lua_State *L) diff --git a/src/irc.cpp b/src/irc.cpp index 72cbbcb..2e85411 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -8,8 +8,8 @@ #include "job.hpp" #include "admin.hpp" std::vector databuf; -clientmap client_map = {}; -channelmap channel_map = {}; +clientset client_map = {}; +channelset channel_map = {}; const char *hostname = 0; void sendbuf(Client *client) { @@ -37,7 +37,7 @@ static void sendbuf_chan_caps(Channel *chan, unsigned positive, unsigned negativ static void sendbuf_chan(Channel *chan) { sendbuf_chan_caps(chan, 0, 0); } -static void sendbuf_list_sans_self_caps(Client *client, clientmap &ls, int cookie, int positive, int negative) { +static void sendbuf_list_sans_self_caps(Client *client, clientset &ls, int cookie, int positive, int negative) { for (auto cl : ls) if (client != cl) { if (cookie) { @@ -50,13 +50,13 @@ static void sendbuf_list_sans_self_caps(Client *client, clientmap &ls, int cooki sendbuf(cl); } } -static void sendbuf_list_sans_self(Client *client, clientmap &ls, int cookie) { +static void sendbuf_list_sans_self(Client *client, clientset &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) { for (auto cl : client_map) - if (cl->monitor.has(nick)) { + if (cl->monitor.contains(nick)) { if (cookie) { if (cookie != cl->cookie) cl->cookie = cookie; @@ -608,9 +608,9 @@ saslcleanup: Channel *chan = findChannel(args[0]); if (!chan) return err_nosuchchannel(client, args[0]), sendbuf(client), false; - if (!chan->members.has(client)) + if (!chan->members.contains(client)) return err_notonchannel(client, chan), sendbuf(client), false; - chan->o.add(client); + chan->o.insert(client); copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +o %s\r\n", chan->name, client->nick); sendbuf_chan(chan); } MATCH_COMMAND("JOIN") { @@ -662,7 +662,7 @@ saslcleanup: channel_sendtopic(client, chan, 0); } else { // TODO: membership check, maybe? - if (chan->dmode & DMODE_TOPICPROT && !chan->o.has(client)) + if (chan->dmode & DMODE_TOPICPROT && !chan->o.contains(client)) return false; // FIXME: error 482 channel_topic(client, chan, args[1], client->nick, get_time()); } @@ -681,19 +681,19 @@ saslcleanup: if (!chan) return err_nosuchchannel(client, args[1]), sendbuf(client), false; if (chan->dmode & DMODE_INVITEONLY) { - if (!chan->o.has(client)) + if (!chan->o.contains(client)) return err_chanoprivsneeded(client, chan), sendbuf(client), false; } else { - if (!chan->members.has(client)) + if (!chan->members.contains(client)) return err_notonchannel(client, chan), sendbuf(client), false; } Client *cl = findClient(args[0]); if (!cl) return err_nosuchnick(client, args[0]), sendbuf(client), false; - if (chan->members.has(cl)) + if (chan->members.contains(cl)) return err_useronchannel(client, cl->nick, chan), sendbuf(client), false; - chan->invitees.add(cl); - cl->invites.add(chan); + chan->invitees.insert(cl); + cl->invites.insert(chan); rpl_inviting(client, cl, chan); sendbuf(client); msg_invite(client, cl, chan); @@ -707,9 +707,9 @@ saslcleanup: Channel *chan = findChannel(args[0]); if (!chan) return err_nosuchchannel(client, args[0]), sendbuf(client), false; - if (!chan->o.has(client)) + if (!chan->o.contains(client)) return err_chanoprivsneeded(client, chan), sendbuf(client), false; - if (!chan->members.has(client)) + if (!chan->members.contains(client)) return err_notonchannel(client, chan), sendbuf(client), false; char *p = args[1]; do { @@ -750,11 +750,11 @@ privmsg_notice_common: if (match_list(client, chan->listb) && !match_list(client, chan->liste)) return err_cannotsendtochan(client, chan->name), sendbuf(client), false; if (chan->dmode & DMODE_INVITEONLY - && !chan->invitees.has(client) && !match_list(client, chan->listI)) + && !chan->invitees.contains(client) && !match_list(client, chan->listI)) return err_cannotsendtochan(client, chan->name), sendbuf(client), false; - if (chan->dmode & DMODE_NOEXTERNAL && !chan->members.has(client)) + if (chan->dmode & DMODE_NOEXTERNAL && !chan->members.contains(client)) return err_cannotsendtochan(client, chan->name), sendbuf(client), false; - if (chan->dmode & DMODE_MODERATED && !chan->v.has(client) && !chan->o.has(client)) + if (chan->dmode & DMODE_MODERATED && !chan->v.contains(client) && !chan->o.contains(client)) return err_cannotsendtochan(client, chan->name), sendbuf(client), false; switch (admin_hook("sendtochannel", client, 0, chan, args[1])) { case -1: @@ -941,7 +941,7 @@ privmsg_notice_common: Channel *chan = findChannel(nick); if (!chan) return err_nosuchchannel(client, nick), sendbuf(client), false; - if (!chan->o.has(client)) + if (!chan->o.contains(client)) return false; // TODO: error if (argc == 2) { // Type A channel modes int all = !strcmp(args[1], "+0"); @@ -994,7 +994,7 @@ privmsg_notice_common: return err_notregistered(client), sendbuf(client), false; rpl_liststart(client), sendbuf(client); for (auto chan : channel_map) - if (client->umode & UMODE_OPER || !(chan->dmode & DMODE_SECRET) || chan->members.has(client)) + if (client->umode & UMODE_OPER || !(chan->dmode & DMODE_SECRET) || chan->members.contains(client)) rpl_list(client, chan), sendbuf(client); rpl_listend(client), sendbuf(client); } MATCH_COMMAND("NAMES") { @@ -1008,7 +1008,7 @@ privmsg_notice_common: if ((p = strchr(channel, ','))) *p++ = '\0'; Channel *chan = findChannel(channel); - if (chan && (!(chan->dmode & DMODE_SECRET) || chan->members.has(client))) { + if (chan && (!(chan->dmode & DMODE_SECRET) || chan->members.contains(client))) { channel_sendnames(client, chan); } else { rpl_endofnames(client, channel); @@ -1055,7 +1055,7 @@ privmsg_notice_common: int visible = client->umode & UMODE_OPER || !(cl->umode & UMODE_INVISIBLE) || client == cl; if (!visible) { for (auto chan : cl->channels) { - if (client->channels.has(chan)) { + if (client->channels.contains(chan)) { visible = 1; break; } @@ -1090,7 +1090,7 @@ privmsg_notice_common: if (cl->away) rpl_away(client, cl), sendbuf(client); for (auto chan : cl->channels) { - if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !chan->members.has(client)) + if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !chan->members.contains(client)) continue; rpl_whoischannels(client, cl, chan), sendbuf(client); } @@ -1143,8 +1143,8 @@ privmsg_notice_common: return rpl_monlistfull(client, MONITOR_LIMIT,nick), sendbuf(client), false; if ((p = strchr(nick, ','))) *p++ = '\0'; - client->monitor.add(nick); - Client *cl = client_map.get(nick); + client->monitor.insert(nick); + Client *cl = findClientByKey(nick); if (cl) rpl_mononline(client, cl), sendbuf(client); else @@ -1163,7 +1163,7 @@ privmsg_notice_common: char *nick = p; if ((p = strchr(nick, ','))) *p++ = '\0'; - client->monitor.remove(nick); + client->monitor.erase(nick); } while (p); break; } @@ -1177,7 +1177,7 @@ privmsg_notice_common: break; case 'S': for (auto& key : client->monitor) { - Client *cl = client_map.get(key); + Client *cl = findClientByKey(key); if (cl) rpl_mononline(client, cl), sendbuf(client); else @@ -1330,7 +1330,7 @@ void setNick(Client *client, char* nickname) { return; } - if (Client *other = client_map.get(LowercasingView(nickname)); other) { + if (Client *other = findClient(nickname); other) { if (client != other) err_nicknameinuse(client, nickname), sendbuf(client); return; @@ -1352,11 +1352,12 @@ void setNick(Client *client, char* nickname) { sendbuf(client); sendbuf_visible(client); rpl_monoffline(0, client->key), sendbuf_monitor(client->key, 0, 0, 0); - client_map.remove(client); + client_map.erase(client); for (auto chan : client->channels) { - chan->members.rename(client, key); - chan->o.rename(client, key); - chan->v.rename(client, key); + renameClient(chan->members, client, key); + renameClient(chan->o, client, key); + renameClient(chan->v, client, key); + renameClient(chan->invitees, client, key); } delete[] client->nick; delete[] client->key; @@ -1367,7 +1368,7 @@ void setNick(Client *client, char* nickname) { client->nick = mystrdup(nickname); updateNuh(client); client->key = mystrdup(key); - client_map.add(client); + client_map.insert(client); rpl_mononline(0, client), sendbuf_monitor(client->key, 0, 0, 0); } /* changes username, hostname or both @@ -1425,11 +1426,11 @@ void client_chghost(Client *client, const char *newusername, const char *newhost 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 (chan->v.has(client)) { + if (chan->v.contains(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 (chan->o.has(client)) { + if (chan->o.contains(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); } @@ -1489,17 +1490,17 @@ void channel_join(Client *client, const char *channel, const char *chankey) size_t chanlen = strlen(channel); if (chanlen >= MAX_CHANLEN) return err_badchanmask(client, channel), sendbuf(client); - char key[MAX_CHANLEN]; - memcpy(key, channel, chanlen+1); - stringlower(key); - Channel *chan = channel_map.get(key); + Channel *chan = findChannel(channel); int newchan = !chan; if (!chan) { + char key[MAX_CHANLEN]; + memcpy(key, channel, chanlen+1); + stringlower(key); chan = new Channel(channel, key, get_time()); chan->dmode &= ~DMODE_PERSIST; - chan->o.add(client); + chan->o.insert(client); } else { - if (chan->members.has(client)) + if (chan->members.contains(client)) return; if (chan->chankey && (!chankey || strcmp(chan->chankey, chankey) == 0)) return err_badchannelkey(client, chan), sendbuf(client); @@ -1508,11 +1509,11 @@ void channel_join(Client *client, const char *channel, const char *chankey) if (match_list(client, chan->listb) && !match_list(client, chan->liste)) return err_bannedfromchan(client, chan), sendbuf(client); if (chan->dmode & DMODE_INVITEONLY - && !chan->invitees.has(client) && !match_list(client, chan->listI)) + && !chan->invitees.contains(client) && !match_list(client, chan->listI)) return err_inviteonlychan(client, chan), sendbuf(client); } - chan->members.add(client); - client->channels.add(chan); + chan->members.insert(client); + client->channels.insert(chan); chan->member_count++; // send JOIN to everyone msg_join(client, chan); @@ -1529,12 +1530,12 @@ void channel_join(Client *client, const char *channel, const char *chankey) // TODO: send channel modes to the joining client // apply +w modes if (match_list(client, chan->listwo)) { - chan->o.add(client); + chan->o.insert(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)) { - chan->v.add(client); + chan->v.insert(client); copy_strf(&databuf, ":cia!cia@cia.gov MODE %s +v %s\r\n", chan->name, client->nick); sendbuf_chan(chan); } @@ -1546,11 +1547,11 @@ void channel_join(Client *client, const char *channel, const char *chankey) Channel::Channel(const char *channel, const char *key, time_t creation) :key(mystrdup(key)), name(mystrdup(channel)), creation(creation) { - channel_map.add(this); + channel_map.insert(this); } void channel_part(Client *client, Channel *chan, const char *reason, Client *kicker) { - if (!chan->members.has(client)) + if (!chan->members.contains(client)) return; if (kicker) { msg_kick(kicker, client, chan, reason); @@ -1559,18 +1560,18 @@ void channel_part(Client *client, Channel *chan, const char *reason, Client *kic msg_part(client, chan, *reason ? reason : NULL); sendbuf_chan(chan); } - client->channels.remove(chan); - chan->members.remove(client); - chan->o.remove(client); - chan->v.remove(client); + client->channels.erase(chan); + chan->members.erase(client); + chan->o.erase(client); + chan->v.erase(client); chan->member_count--; if (!chan->member_count && !(chan->dmode & DMODE_PERSIST)) delete chan; } Channel::~Channel() { - channel_map.remove(this); + channel_map.erase(this); for (auto cl : invitees) - cl->invites.remove(this); + cl->invites.erase(this); delete[] key; delete[] name; delete[] topic; @@ -1695,9 +1696,9 @@ void channel_mode(Client *client, Channel *chan, char *args[]) { break; // TODO: error msg stringlower(mask); if (is_plus) - list->add(mask); + list->insert(mask); else - list->remove(mask); + list->erase(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); @@ -1717,16 +1718,16 @@ void channel_mode(Client *client, Channel *chan, char *args[]) { err_nosuchnick(client, nick), sendbuf(client); break; } - if (!chan->members.has(cl)) { + if (!chan->members.contains(cl)) { if (client) err_usernotinchannel(client, cl->nick, chan), sendbuf(client); break; } - clientmap &clmap = *p == 'o' ? chan->o : chan->v; + clientset &clset = *p == 'o' ? chan->o : chan->v; if (is_plus) - clmap.add(cl); + clset.insert(cl); else - clmap.remove(cl); + clset.erase(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); @@ -1761,9 +1762,15 @@ 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) { - return client_map.get(LowercasingView(nickname)); +Client *findClientByKey(std::string_view key) { + auto it = client_map.find(key); + return it != client_map.end() ? *it : nullptr; +} +Client *findClient(std::string_view nickname) { + auto it = client_map.find(LowercasingView(nickname)); + return it != client_map.end() ? *it : nullptr; } -Channel *findChannel(const char *channel) { - return channel_map.get(LowercasingView(channel)); +Channel *findChannel(std::string_view channel) { + auto it = channel_map.find(LowercasingView(channel)); + return it != channel_map.end() ? *it : nullptr; } diff --git a/src/irc.hpp b/src/irc.hpp index 0360d55..89d8fcf 100644 --- a/src/irc.hpp +++ b/src/irc.hpp @@ -16,8 +16,9 @@ void sendLUSERS(Client *client); void sendMOTD(Client *client); void setNick(Client *client, char* nickname); void client_chghost(Client *client, const char *newusername, const char *newhostname); -Client *findClient(const char *nickname); -Channel *findChannel(const char *channel); +Client *findClientByKey(std::string_view key); +Client *findClient(std::string_view nickname); +Channel *findChannel(std::string_view channel); void channel_sendtopic(Client *client, Channel *chan, int joining); void channel_sendnames(Client *client, Channel *chan); void channel_join(Client *client, const char *channel, const char *chankey); diff --git a/src/ircdata.hpp b/src/ircdata.hpp index 02af147..a9990fc 100644 --- a/src/ircdata.hpp +++ b/src/ircdata.hpp @@ -54,8 +54,8 @@ struct Client { size_t wlen = 0; char umode = 0; char regstate = REG_INIT; - channelmap channels; - channelmap invites; + channelset channels; + channelset invites; stringset monitor; int cookie = 0; time_t signon = 0; @@ -93,9 +93,9 @@ struct Channel { char *topic_who = nullptr; time_t topic_when = 0; time_t creation = 0; - clientmap members; - clientmap o; - clientmap v; + clientset members; + clientset o; + clientset v; int member_count = 0; char dmode = DMODE_NOEXTERNAL | DMODE_TOPICPROT | DMODE_PERSIST; stringset listb; @@ -104,7 +104,7 @@ struct Channel { stringset listq; stringset listwo; stringset listwv; - clientmap invitees; + clientset invitees; char *chankey = nullptr; int member_limit = -1; @@ -113,18 +113,18 @@ struct Channel { ~Channel(); bool is_op(Client *client) { - return o.has(client); + return o.contains(client); } bool is_voice(Client *client) { - return v.has(client); + return v.contains(client); } }; constexpr std::string_view to_key(const Channel *v) noexcept { return v->key; } -extern clientmap client_map; -extern channelmap channel_map; +extern clientset client_map; +extern channelset channel_map; extern Client *clients; extern Client *dyingclients; #endif diff --git a/src/map.hpp b/src/map.hpp index c2ea4a8..0cb41f3 100644 --- a/src/map.hpp +++ b/src/map.hpp @@ -150,16 +150,6 @@ public: FlatSet& operator=(FlatSet&&) = delete; }; -/* A map abstract data type with following properties: - * - keys are lexicographically-sorted unique NUL-terminated strings - * - values are non-NULL pointers - * - a NULL value is synonymous with absence of a key - * - keys are owned by the map, values are not. - * - the map can't be modified during traversal - * - * A map is created by allocating and zero-initializing an object of type - * map_t. All map functions take a pointer to map_t. - */ struct Client; struct Channel; constexpr std::string_view to_key(const std::string &v) noexcept { @@ -169,7 +159,7 @@ constexpr std::string_view to_key(const Client *v) noexcept; constexpr std::string_view to_key(const Channel *v) noexcept; template -struct MapValueLess { +struct SetValueLess { using is_transparent = void; constexpr bool operator()(const T& lhs, const T& rhs) noexcept { return to_key(lhs) < to_key(rhs); @@ -194,65 +184,35 @@ struct MapValueLess { } }; -template -struct map_base2 { - map_base2& operator=(map_base2&&) = delete; - FlatSet> m; - - void clear() { - m.clear(); - } - - using value_type = T; - auto begin() { return m.begin(); } - auto end() { return m.end(); } - auto rbegin() { return m.rbegin(); } - auto rend() { return m.rend(); } - size_t size() { - return m.size(); - } - template - bool has(const K& k) { - return m.contains(k); - } - template - void add(const K &v) { - m.insert(v); - } - template - void remove(const K &k) { - m.erase(k); - } - - template - T get(const K& k) { - auto it = m.find(k); - return it != m.end() ? *it : T(); - } -}; - -struct clientmap : map_base2 { - void rename(Client *v, const char *newk) { - auto it1 = m.find(v); - if (it1 == m.end()) - return; - auto it2 = m.lower_bound(std::string_view(newk)); - // Have to to this with a const_cast on the underlying vector, instead - // of m.extract/m.replace, because it's UB to replace with an unsorted - // vector. This will be an actual problem in e.g. libcxx with hardening - // enabled, since they assert that the array is sorted. - Client **p = const_cast(&*it1); - Client **q = const_cast(&*it2); - if (p < q) - std::rotate(p, p+1, q); - else - std::rotate(q, p, p+1); - } -}; -using channelmap = map_base2; -struct stringset : map_base2 { - template - std::string get(const K& k) = delete; -}; +using clientset = FlatSet>; +using channelset = FlatSet>; +using stringset = FlatSet>; +/** + * Move a client to a different key position in the set. + * + * When a user updates the nickname (setNick()) we have to update all sets + * referencing the user. Rather than removing and readding the user, we simply + * put him at the position of the new key. This temporarily breaks the + * invariant of flat_set. The benefit is that we don't have to track the list + * of sets we have to readd the user to. + * + * This function is a no-op when the client isn't a member of the set. + */ +inline void renameClient(clientset &s, Client *cl, std::string_view newk) { + auto it1 = s.find(cl); + if (it1 == s.end()) + return; + auto it2 = s.lower_bound(newk); + // Have to to this with a const_cast on the underlying vector, instead + // of m.extract/m.replace, because it's UB to replace with an unsorted + // vector. This will be an actual problem in e.g. libcxx with hardening + // enabled, since they assert that the array is sorted. + Client **p = const_cast(&*it1); + Client **q = const_cast(&*it2); + if (p < q) + std::rotate(p, p+1, q); + else + std::rotate(q, p, p+1); +} #endif diff --git a/src/net.cpp b/src/net.cpp index f6d0e80..0033c86 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -78,10 +78,10 @@ void killConnection(Client *cl, int byChoice) /* Remove from client_map and get rid of the pending invites */ if (cl->key) { admin_hook("nickdel", cl, 0, 0, cl->key); - client_map.remove(cl); + client_map.erase(cl); rpl_monoffline(0, cl->key), sendbuf_monitor(cl->key, 0, 0, 0); for (auto chan : cl->invites) - chan->invitees.remove(cl); + chan->invitees.erase(cl); } cl->channels.clear(); cl->invites.clear();