}
static int match_list(Client *cl, stringset &list)
{
- for (auto key : list)
+ for (auto& key : list)
if (irc_glob(cl->nuh, key))
return 1;
return 0;
any = 1;
}
if (all || !strcmp(args[1], "+b") || !strcmp(args[1], "b")) {
- for (auto key : chan->listb)
+ 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")) {
- for (auto key : chan->liste)
+ 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")) {
- for (auto key : chan->listI)
+ 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")) {
- for (auto key : chan->listq)
+ for (const 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")) {
- for (auto key : chan->listwo)
+ for (const auto& key : chan->listwo)
rpl_accesslist(client, chan, 'o', key), sendbuf(client);
- for (auto key : chan->listwv)
+ for (const auto& key : chan->listwv)
rpl_accesslist(client, chan, 'v', key), sendbuf(client);
rpl_endofaccesslist(client, chan), sendbuf(client);
any = 1;
client->monitor.clear();
break;
case 'L':
- for (auto key : client->monitor)
+ for (auto& key : client->monitor)
rpl_monlist(client, key), sendbuf(client);
rpl_endofmonlist(client), sendbuf(client);
break;
case 'S':
- for (auto key : client->monitor) {
+ for (auto& key : client->monitor) {
Client *cl = client_map.get(key);
if (cl)
rpl_mononline(client, cl), sendbuf(client);
{
copy_strf(&databuf, ":%s 341 %s %s %s\r\n", hostname, client->nick, cl->nick, chan->name);
}
-void rpl_invexlist(Client *client, Channel *chan, const char *mask) // 346
+void rpl_invexlist(Client *client, Channel *chan, std::string_view mask) // 346
{
- copy_strf(&databuf, ":%s 346 %s %s %s\r\n", hostname, client->nick, chan->name, mask);
+ copy_strf(&databuf, ":%s 346 %s %s %.*s\r\n", hostname, client->nick, chan->name, (int)mask.size(), mask.data());
}
void rpl_endofinvexlist(Client *client, Channel *chan) // 347
{
copy_strf(&databuf, ":%s 347 %s %s :End of Channel Invite Exception List\r\n", hostname, client->nick, chan->name);
}
-void rpl_exceptlist(Client *client, Channel *chan, const char *mask) // 348
+void rpl_exceptlist(Client *client, Channel *chan, std::string_view mask) // 348
{
- copy_strf(&databuf, ":%s 348 %s %s %s\r\n", hostname, client->nick, chan->name, mask);
+ copy_strf(&databuf, ":%s 348 %s %s %.*s\r\n", hostname, client->nick, chan->name, (int)mask.size(), mask.data());
}
void rpl_endofexceptlist(Client *client, Channel *chan) // 349
{
}
// 364 RPL_LINKS
// 365 RPL_ENDOFLINKS
-void rpl_banlist(Client *client, Channel *chan, const char *mask) // 367
+void rpl_banlist(Client *client, Channel *chan, std::string_view mask) // 367
{
- copy_strf(&databuf, ":%s 367 %s %s %s\r\n", hostname, client->nick, chan->name, mask);
+ copy_strf(&databuf, ":%s 367 %s %s %.*s\r\n", hostname, client->nick, chan->name, (int)mask.size(), mask.data());
}
void rpl_endofbanlist(Client *client, Channel *chan) // 368
{
copy_strf(&databuf, ":%s 706 %s * :End of /HELP\r\n", hostname, client->nick);
}
// 723 ERR_NOPRIVS
-void rpl_quietlist(Client *client, Channel *chan, const char *mask) // 728
+void rpl_quietlist(Client *client, Channel *chan, std::string_view mask) // 728
{
- copy_strf(&databuf, ":%s 728 %s %s q %s\r\n", hostname, client->nick, chan->name, mask);
+ copy_strf(&databuf, ":%s 728 %s %s q %.*s\r\n", hostname, client->nick, chan->name, (int)mask.size(), mask.data());
}
void rpl_endofquietlist(Client *client, Channel *chan) // 729
{
{
copy_strf(&databuf, ":%s 730 %s :%s!%s@%s\r\n", hostname, client ? client->nick : "*", cl->nick, cl->username, cl->hostname);
}
-void rpl_monoffline(Client *client, const char *nick) // 731
+void rpl_monoffline(Client *client, std::string_view nick) // 731
{
- copy_strf(&databuf, ":%s 731 %s :%s\r\n", hostname, client ? client->nick : "*", nick);
+ copy_strf(&databuf, ":%s 731 %s :%.*s\r\n", hostname, client ? client->nick : "*", (int)nick.size(), nick.data());
}
-void rpl_monlist(Client *client, const char *nick) // 732
+void rpl_monlist(Client *client, std::string_view nick) // 732
{
- copy_strf(&databuf, ":%s 732 %s :%s\r\n", hostname, client->nick, nick);
+ copy_strf(&databuf, ":%s 732 %s :%.*s\r\n", hostname, client->nick, (int)nick.size(), nick.data());
}
void rpl_endofmonlist(Client *client) // 733
{
{
copy_strf(&databuf, ":%s 908 * PLAIN,EXTERNAL :are available SASL mechanisms\r\n", hostname);
}
-void rpl_accesslist(Client *client, Channel *chan, char mode, const char *mask) // 910
+void rpl_accesslist(Client *client, Channel *chan, char mode, std::string_view mask) // 910
{
- char modes[2] = {mode,0};
- copy_strf(&databuf, ":%s 910 %s %s %s:%s\r\n", hostname, client->nick, chan->name, modes, mask);
+ copy_strf(&databuf, ":%s 910 %s %s %c:%.*s\r\n", hostname, client->nick, chan->name, mode, (int)mask.size(), mask.data());
}
void rpl_endofaccesslist(Client *client, Channel *chan) // 911
{
-// Copyright (c) 2022-2025 Egor
+// Copyright (c) 2022-2026 Egor
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef IRCFMT_H_
#define IRCFMT_H_
void rpl_endofinvitelist(Client *client); // 337
void rpl_whoisactually(Client *client, Client *cl); // 338
void rpl_inviting(Client *client, Client *cl, Channel *chan); // 341
-void rpl_invexlist(Client *client, Channel *chan, const char *mask); // 346
+void rpl_invexlist(Client *client, Channel *chan, std::string_view mask); // 346
void rpl_endofinvexlist(Client *client, Channel *chan); // 347
-void rpl_exceptlist(Client *client, Channel *chan, const char *mask); // 348
+void rpl_exceptlist(Client *client, Channel *chan, std::string_view mask); // 348
void rpl_endofexceptlist(Client *client, Channel *chan); // 349
void rpl_version(Client *client, const char *ver, const char *comments); // 351
int rpl_namreply(Client *client, Channel *chan, Client *cl); // 353
void rpl_endofnames(Client *client, const char *channel); // 366
// 364 RPL_LINKS
// 365 RPL_ENDOFLINKS
-void rpl_banlist(Client *client, Channel *chan, const char *mask); // 367
+void rpl_banlist(Client *client, Channel *chan, std::string_view mask); // 367
void rpl_endofbanlist(Client *client, Channel *chan); // 368
// 369 RPL_ENDOFWHOWAS
// 371 RPL_INFO
void rpl_helptxt(Client *client, const char *line); // 705
void rpl_endofhelp(Client *client); // 706
// 723 ERR_NOPRIVS
-void rpl_quietlist(Client *client, Channel *chan, const char *mask); // 728
+void rpl_quietlist(Client *client, Channel *chan, std::string_view mask); // 728
void rpl_endofquietlist(Client *client, Channel *chan); // 729
void rpl_mononline(Client *client, Client *cl); // 730
-void rpl_monoffline(Client *client, const char *nick); // 731
-void rpl_monlist(Client *client, const char *nick); // 732
+void rpl_monoffline(Client *client, std::string_view nick); // 731
+void rpl_monlist(Client *client, std::string_view nick); // 732
void rpl_endofmonlist(Client *client); // 733
void rpl_monlistfull(Client *client, int limit, const char *targets); // 734
void rpl_loggedin(Client *client); // 900
void err_saslaborted(void); // 906
void err_saslalready(void); // 907
void rpl_saslmechs(void); // 908
-void rpl_accesslist(Client *client, Channel *chan, char mode, const char *mask); // 910
+void rpl_accesslist(Client *client, Channel *chan, char mode, std::string_view mask); // 910
void rpl_endofaccesslist(Client *client, Channel *chan); // 911
#endif
}
using value_to_void_type = decltype(value_to_void(std::declval<T>()));
- constexpr T void_to_value(void *p) noexcept requires (std::same_as<T, Client*> || std::same_as<T, Channel*>) {
+ static constexpr T void_to_value(void *p) noexcept requires (std::same_as<T, Client*> || std::same_as<T, Channel*>) {
return static_cast<T>(p);
}
- constexpr std::string_view void_to_value(void *p) noexcept requires std::same_as<T, std::string> {
+ static constexpr std::string_view void_to_value(void *p) noexcept requires std::same_as<T, std::string> {
return static_cast<char *>(p);
}
public:
using value_type = T;
struct iterator {
using iterator_category = std::bidirectional_iterator_tag;
- using value_type = value_to_void_type;
+ using value_type = T;
using difference_type = ptrdiff_t;
- using pointer = void;
- using reference = value_to_void_type;
+ using pointer = const T*;
+ using reference = const T&;
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 value_to_void(*ptr); }
+ reference operator*() const { return *ptr; }
decltype(m)::iterator ptr;
};
static_assert(std::bidirectional_iterator<iterator>);
const char *c = va_arg(ap, const char *);
append_str(v, c ? c : "(null)");
s = end + 2;
+ } else if (end[1] == 's') { // %s
+ append_strn(v, s, end-s);
+ char c = static_cast<char>(va_arg(ap, int));
+ append_strn(v, &c, 1);
+ s = end + 2;
} else if (end[1] == 'u') { // %u
append_strn(v, s, end-s);
unsigned c = va_arg(ap, unsigned);
}
/* https://research.swtch.com/glob */
-int irc_glob(const char *key, const char *mask)
+int irc_glob(std::string_view key, std::string_view mask)
{
- const char *key2 = 0, *mask2 = 0;
- while (*key || *mask) {
- if (*mask) {
- switch (*mask) {
+ std::string_view key2, mask2;
+ while (!key.empty() || !mask.empty()) {
+ if (!mask.empty()) {
+ switch (mask.front()) {
case '\\':
- if (*key == *mask) {
- key++, mask++;
- if (!*mask)
+ if (key.front() == mask.front()) {
+ key.remove_prefix(1), mask.remove_prefix(1);
+ if (mask.empty())
continue;
- if (*key == *mask) {
- key++, mask++;
+ if (key.front() == mask.front()) {
+ key.remove_prefix(1), mask.remove_prefix(1);
continue;
}
}
break;
default:
- if (*key == *mask) {
- key++, mask++;
+ if (key.front() == mask.front()) {
+ key.remove_prefix(1), mask.remove_prefix(1);
continue;
}
break;
case '?':
- if (*key) {
- key++, mask++;
+ if (!key.empty()) {
+ key.remove_prefix(1), mask.remove_prefix(1);
continue;
}
break;
case '*':
- key2 = *key ? key + 1 : 0;
- mask2 = mask++;
+ key2 = !key.empty() ? key.substr(1) : std::string_view();
+ mask2 = mask;
+ mask.remove_prefix(1);
continue;
}
}
- if (key2) {
+ if (key2.data()) {
key = key2;
mask = mask2;
continue;
char *mystrdup(const char *s);
time_t get_time(void);
void set_time(time_t t);
-int irc_glob(const char *key, const char *mask);
+int irc_glob(std::string_view key, std::string_view mask);
extern const char *datadir;
const char *getdatafile(const char *fn);
extern const char *luadir;