From 29e7674e56bf2b829bba22def2760d034a76e788 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Mon, 11 Mar 2024 13:53:05 +0000 Subject: Replace convertTo/stringify with non-throwing alternatives. Having these throw is terrible for ergonomics and there are loads of places where the exception was either silently ignored or not handled at all. Having a function which returns an optional and another that returns a default works a lot better imo. --- include/anope.h | 69 +-------------- include/config.h | 9 +- include/convert.h | 133 +++++++++++++++++++++++++++++ include/modules/sql.h | 13 ++- include/protocol.h | 6 +- include/uplink.h | 8 +- modules/botserv/botserv.cpp | 8 +- modules/botserv/bs_badwords.cpp | 4 +- modules/botserv/bs_info.cpp | 2 +- modules/botserv/bs_kick.cpp | 96 +++++---------------- modules/chanserv/cs_access.cpp | 33 +++---- modules/chanserv/cs_akick.cpp | 4 +- modules/chanserv/cs_enforce.cpp | 10 +-- modules/chanserv/cs_entrymsg.cpp | 23 ++--- modules/chanserv/cs_flags.cpp | 2 +- modules/chanserv/cs_info.cpp | 2 +- modules/chanserv/cs_list.cpp | 12 +-- modules/chanserv/cs_log.cpp | 2 +- modules/chanserv/cs_mode.cpp | 2 +- modules/chanserv/cs_set.cpp | 17 ++-- modules/chanserv/cs_xop.cpp | 4 +- modules/database/db_atheme.cpp | 27 ++---- modules/database/db_flatfile.cpp | 9 +- modules/database/db_old.cpp | 4 +- modules/database/db_redis.cpp | 50 +++++------ modules/database/db_sql.cpp | 18 ++-- modules/database/db_sql_live.cpp | 15 ++-- modules/encryption/enc_bcrypt.cpp | 20 ++--- modules/extra/mysql.cpp | 4 +- modules/extra/regex_pcre2.cpp | 2 +- modules/extra/sqlite.cpp | 4 +- modules/hostserv/hs_list.cpp | 13 ++- modules/hostserv/hs_request.cpp | 2 +- modules/httpd.cpp | 9 +- modules/memoserv/memoserv.cpp | 4 +- modules/memoserv/ms_list.cpp | 4 +- modules/memoserv/ms_set.cpp | 16 +--- modules/nickserv/nickserv.cpp | 2 +- modules/nickserv/ns_ajoin.cpp | 8 +- modules/nickserv/ns_alist.cpp | 6 +- modules/nickserv/ns_list.cpp | 12 +-- modules/operserv/os_akill.cpp | 4 +- modules/operserv/os_defcon.cpp | 8 +- modules/operserv/os_dns.cpp | 25 +++--- modules/operserv/os_list.cpp | 4 +- modules/operserv/os_logsearch.cpp | 26 ++---- modules/operserv/os_news.cpp | 18 ++-- modules/operserv/os_session.cpp | 26 ++---- modules/operserv/os_set.cpp | 6 +- modules/operserv/os_sxline.cpp | 4 +- modules/protocol/bahamut.cpp | 38 ++++----- modules/protocol/hybrid.cpp | 24 ++---- modules/protocol/inspircd.cpp | 103 +++++++--------------- modules/protocol/ngircd.cpp | 7 +- modules/protocol/plexus.cpp | 22 ++--- modules/protocol/ratbox.cpp | 4 +- modules/protocol/solanum.cpp | 2 +- modules/protocol/unrealircd.cpp | 91 ++++++-------------- modules/proxyscan.cpp | 10 +-- modules/redis.cpp | 27 ++---- modules/rewrite.cpp | 41 +++++---- modules/webcpanel/pages/memoserv/memos.cpp | 12 +-- modules/webcpanel/pages/nickserv/alist.cpp | 4 +- modules/webcpanel/pages/operserv/akill.cpp | 2 +- modules/xmlrpc_main.cpp | 28 +++--- src/config.cpp | 16 ++-- src/init.cpp | 6 +- src/misc.cpp | 80 ++++++++--------- src/modes.cpp | 27 +++--- src/modulemanager.cpp | 2 +- src/nickcore.cpp | 2 +- src/protocol.cpp | 2 +- src/regchannel.cpp | 11 ++- src/socketengines/epoll.cpp | 2 +- src/socketengines/poll.cpp | 4 +- src/sockets.cpp | 8 +- 76 files changed, 573 insertions(+), 811 deletions(-) create mode 100644 include/convert.h diff --git a/include/anope.h b/include/anope.h index fd3728d84..c4a2079aa 100644 --- a/include/anope.h +++ b/include/anope.h @@ -39,6 +39,7 @@ namespace Anope typedef std::string::reverse_iterator reverse_iterator; typedef std::string::const_reverse_iterator const_reverse_iterator; typedef std::string::size_type size_type; + typedef std::string::value_type value_type; static const size_type npos = static_cast(-1); /** @@ -729,72 +730,6 @@ public: virtual ~ModuleException() noexcept = default; }; -class CoreExport ConvertException final - : public CoreException -{ -public: - ConvertException(const Anope::string &reason = "") : CoreException(reason) { } - - virtual ~ConvertException() noexcept = default; -}; - -/** Convert something to a string - */ -inline Anope::string stringify(const Anope::string &x) -{ - return x; -} - -template inline Anope::string stringify(const T &x) -{ - std::ostringstream stream; - - if (!(stream << x)) - throw ConvertException("Stringify fail"); - - return stream.str(); -} - -template inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true) -{ - leftover.clear(); - std::istringstream i(s.str()); - char c; - if (!(i >> x)) - throw ConvertException("Convert fail"); - if (failIfLeftoverChars) - { - if (i.get(c)) - throw ConvertException("Convert fail"); - } - else - { - std::string left; - getline(i, left); - leftover = left; - } -} - -template inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true) -{ - Anope::string Unused; - convert(s, x, Unused, failIfLeftoverChars); -} - -template inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true) -{ - T x; - convert(s, x, leftover, failIfLeftoverChars); - return x; -} - -template inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true) -{ - T x; - convert(s, x, failIfLeftoverChars); - return x; -} - /** Casts to be used instead of dynamic_cast, this uses dynamic_cast * for debug builds and static_cast on release builds * to speed up the program because dynamic_cast relies on RTTI. @@ -814,3 +749,5 @@ template inline T anope_dynamic_static_cast(O ptr) return static_cast(ptr); } #endif + +#include "convert.h" diff --git a/include/config.h b/include/config.h index 022ee503d..652d42a7a 100644 --- a/include/config.h +++ b/include/config.h @@ -46,14 +46,7 @@ namespace Configuration template T Get(const Anope::string &tag, const Anope::string &def = "") const { - const Anope::string &value = this->Get(tag, def); - if (!value.empty()) - try - { - return convertTo(value); - } - catch (const ConvertException &) { } - return T(); + return Anope::TryConvert(this->Get(tag, def)).value_or(T()); } bool Set(const Anope::string &tag, const Anope::string &value); diff --git a/include/convert.h b/include/convert.h new file mode 100644 index 000000000..3cdbcd787 --- /dev/null +++ b/include/convert.h @@ -0,0 +1,133 @@ +/* + * + * (C) 2003-2024 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#pragma once + +#include + +namespace Anope +{ + /** Attempts to convert a string to any type. + * @param in The value to convert. + * @param leftover If non-nullptr then the location to store leftover data. + */ + template + inline std::optional TryConvert(const Anope::string &in, Anope::string *leftover = nullptr) + { + std::istringstream tmp(in.str()); + T out; + if (!(tmp >> out)) + return std::nullopt; + + if (leftover) + { + std::string extra; + std::getline(tmp, extra); + *leftover = extra; + } + else + { + char extra; + if (tmp >> extra) + return std::nullopt; + } + return out; + } + + /** Converts a string to any type. + * @param in The value to convert. + * @param def The default to use if the conversion failed. + * @param leftover If non-nullptr then the location to store leftover data. + */ + template + inline T Convert(const Anope::string &in, T def, Anope::string *leftover = nullptr) + { + return TryConvert(in, leftover).value_or(def); + } + + /** Attempts to convert any type to a string. + * @param in The value to convert. + */ + template + inline std::optional TryString(const T &in) + { + std::ostringstream tmp; + if (!(tmp << in)) + return std::nullopt; + return tmp.str(); + } + + /** No-op function that returns the string that was passed to it. + * @param in The string to return. + */ + inline const string &ToString(const string &in) + { + return in; + } + + /** Converts a std::string to a string. + * @param in The value to convert. + */ + inline string ToString(const std::string &in) + { + return in; + } + + /** Converts a char array to a string. + * @param in The value to convert. + */ + inline string ToString(const char *in) + { + return string(in); + } + + /** Converts a char to a string. + * @param in The value to convert. + */ + inline string ToString(char in) + { + return string(1, static_cast(in)); + } + + /** Converts an unsigned char to a string. + * @param in The value to convert. + */ + inline string ToString(unsigned char in) + { + return string(1, static_cast(in)); + } + + /** Converts a bool to a string. + * @param in The value to convert. + */ + inline string ToString(bool in) + { + return (in ? "1" : "0"); + } + + /** Converts a type that std::to_string is implemented for to a string. + * @param in The value to convert. + */ + template + inline std::enable_if_t, string> ToString(const Stringable &in) + { + return std::to_string(in); + } + + /** Converts any type to a string. + * @param in The value to convert. + */ + template + inline std::enable_if_t, string> ToString(const T &in) + { + return TryString(in).value_or(Anope::string()); + } +} diff --git a/include/modules/sql.h b/include/modules/sql.h index 8ac03803f..4c1b7d455 100644 --- a/include/modules/sql.h +++ b/include/modules/sql.h @@ -128,13 +128,12 @@ namespace SQL template void SetValue(const Anope::string &key, const T &value, bool escape = true) { - try - { - Anope::string string_value = stringify(value); - this->parameters[key].data = string_value; - this->parameters[key].escape = escape; - } - catch (const ConvertException &ex) { } + auto str = Anope::TryString(value); + if (!str.has_value()) + return; + + this->parameters[key].data = str.value(); + this->parameters[key].escape = escape; } }; diff --git a/include/protocol.h b/include/protocol.h index 88bb94bfc..612593c89 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -164,14 +164,14 @@ public: template void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args &&...args) { - SendModeInternal(source, chan, modes, { stringify(args)... }); + SendModeInternal(source, chan, modes, { Anope::ToString(args)... }); } virtual void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector &values); template void SendMode(const MessageSource &source, User *u, const Anope::string &modes, Args &&...args) { - SendModeInternal(source, u, modes, { stringify(args)... }); + SendModeInternal(source, u, modes, { Anope::ToString(args)... }); } /** Introduces a client to the rest of the network @@ -258,7 +258,7 @@ public: template void SendNumeric(int numeric, const Anope::string &dest, Args &&...args) { - SendNumericInternal(numeric, dest, { stringify(args)... }); + SendNumericInternal(numeric, dest, { Anope::ToString(args)... }); } virtual void SendLogin(User *u, NickAlias *na) = 0; diff --git a/include/uplink.h b/include/uplink.h index 12365dd65..924c05cfc 100644 --- a/include/uplink.h +++ b/include/uplink.h @@ -23,25 +23,25 @@ namespace Uplink template void Send(const Anope::map &tags, const MessageSource &source, const Anope::string &command, Args &&...args) { - SendInternal(tags, source, command, { stringify(args)... }); + SendInternal(tags, source, command, { Anope::ToString(args)... }); } template void Send(const Anope::map &tags, const Anope::string &command, Args &&...args) { - SendInternal(tags, Me, command, { stringify(args)... }); + SendInternal(tags, Me, command, { Anope::ToString(args)... }); } template void Send(const MessageSource &source, const Anope::string &command, Args &&...args) { - SendInternal({}, source, command, { stringify(args)... }); + SendInternal({}, source, command, { Anope::ToString(args)... }); } template void Send(const Anope::string &command, Args &&...args) { - SendInternal({}, Me, command, { stringify(args)... }); + SendInternal({}, Me, command, { Anope::ToString(args)... }); } } diff --git a/modules/botserv/botserv.cpp b/modules/botserv/botserv.cpp index d2b8df4bb..706865522 100644 --- a/modules/botserv/botserv.cpp +++ b/modules/botserv/botserv.cpp @@ -67,12 +67,8 @@ public: Anope::string Limit; unsigned limit = 0; - try - { - if (c->GetParam("LIMIT", Limit)) - limit = convertTo(Limit); - } - catch (const ConvertException &) { } + if (c->GetParam("LIMIT", Limit)) + limit = Anope::Convert(Limit, limit); /* Should we be invited? */ if (c->HasMode("INVITE") || (limit && c->users.size() >= limit)) diff --git a/modules/botserv/bs_badwords.cpp b/modules/botserv/bs_badwords.cpp index 5dee8ed2c..09e96564b 100644 --- a/modules/botserv/bs_badwords.cpp +++ b/modules/botserv/bs_badwords.cpp @@ -222,7 +222,7 @@ private: const BadWord *b = bw->GetBadWord(Number - 1); ListFormatter::ListEntry entry; - entry["Number"] = stringify(Number); + entry["Number"] = Anope::ToString(Number); entry["Word"] = b->word; entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : "")); this->list.AddEntry(entry); @@ -241,7 +241,7 @@ private: continue; ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Word"] = b->word; entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : "")); list.AddEntry(entry); diff --git a/modules/botserv/bs_info.cpp b/modules/botserv/bs_info.cpp index c8e05577b..b4a5592b1 100644 --- a/modules/botserv/bs_info.cpp +++ b/modules/botserv/bs_info.cpp @@ -55,7 +55,7 @@ public: info[_("Real name")] = bi->realname; info[_("Created")] = Anope::strftime(bi->created, source.GetAccount()); info[_("Options")] = bi->oper_only ? _("Private") : _("None"); - info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)"; + info[_("Used on")] = Anope::ToString(bi->GetChannelCount()) + " channel(s)"; FOREACH_MOD(OnBotInfo, (source, bi, ci, info)); diff --git a/modules/botserv/bs_kick.cpp b/modules/botserv/bs_kick.cpp index 29c8cb598..9183eae22 100644 --- a/modules/botserv/bs_kick.cpp +++ b/modules/botserv/bs_kick.cpp @@ -106,11 +106,10 @@ struct KickerDataImpl final data["ttb"] >> ttb; spacesepstream sep(ttb); for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i) - try - { - kd->ttb[i] = convertTo(tok); - } - catch (const ConvertException &) { } + { + if (auto n = Anope::TryConvert(tok)) + kd->ttb[i] = n.value(); + } kd->Check(ci); } @@ -206,21 +205,13 @@ protected: { if (!ttb.empty()) { - int16_t i; - - try - { - i = convertTo(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) + kd->ttb[ttb_idx] = Anope::Convert(ttb, -1); + if (kd->ttb[ttb_idx] < 0) { + kd->ttb[ttb_idx] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); return; } - - kd->ttb[ttb_idx] = i; } else kd->ttb[ttb_idx] = 0; @@ -386,13 +377,8 @@ public: if (!ttb.empty()) { - try - { - kd->ttb[TTB_CAPS] = convertTo(ttb); - if (kd->ttb[TTB_CAPS] < 0) - throw ConvertException(); - } - catch (const ConvertException &) + kd->ttb[TTB_CAPS] = Anope::Convert(ttb, -1); + if (kd->ttb[TTB_CAPS] < 0) { kd->ttb[TTB_CAPS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); @@ -402,21 +388,11 @@ public: else kd->ttb[TTB_CAPS] = 0; - kd->capsmin = 10; - try - { - kd->capsmin = convertTo(min); - } - catch (const ConvertException &) { } + kd->capsmin = Anope::Convert(min, 0); if (kd->capsmin < 1) kd->capsmin = 10; - kd->capspercent = 25; - try - { - kd->capspercent = convertTo(percent); - } - catch (const ConvertException &) { } + kd->capspercent = Anope::Convert(percent, 0); if (kd->capspercent < 1 || kd->capspercent > 100) kd->capspercent = 25; @@ -518,42 +494,25 @@ public: if (!ttb.empty()) { - int16_t i; - - try - { - i = convertTo(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) + kd->ttb[TTB_FLOOD] = Anope::Convert(ttb, -1); + if (kd->ttb[TTB_FLOOD] < 0) { + kd->ttb[TTB_FLOOD] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); return; } - - kd->ttb[TTB_FLOOD] = i; } else kd->ttb[TTB_FLOOD] = 0; - kd->floodlines = 6; - try - { - kd->floodlines = convertTo(lines); - } - catch (const ConvertException &) { } + kd->floodlines = Anope::Convert(lines, -1); if (kd->floodlines < 2) kd->floodlines = 6; - kd->floodsecs = 10; - try - { - kd->floodsecs = convertTo(secs); - } - catch (const ConvertException &) { } + kd->floodsecs = Anope::Convert(secs, -1); if (kd->floodsecs < 1) kd->floodsecs = 10; + if (kd->floodsecs > Config->GetModule(me)->Get("keepdata")) kd->floodsecs = Config->GetModule(me)->Get("keepdata"); @@ -651,31 +610,18 @@ public: if (!ttb.empty()) { - int16_t i; - - try - { - i = convertTo(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) + kd->ttb[TTB_REPEAT] = Anope::Convert(ttb, -1); + if (kd->ttb[TTB_REPEAT] < 0) { + kd->ttb[TTB_REPEAT] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); return; } - - kd->ttb[TTB_REPEAT] = i; } else kd->ttb[TTB_REPEAT] = 0; - kd->repeattimes = 3; - try - { - kd->repeattimes = convertTo(times); - } - catch (const ConvertException &) { } + kd->repeattimes = Anope::Convert(times, -1); if (kd->repeattimes < 1) kd->repeattimes = 3; diff --git a/modules/chanserv/cs_access.cpp b/modules/chanserv/cs_access.cpp index 3d2c3c8d6..f86d9f5bc 100644 --- a/modules/chanserv/cs_access.cpp +++ b/modules/chanserv/cs_access.cpp @@ -37,18 +37,13 @@ public: Anope::string AccessSerialize() const override { - return stringify(this->level); + return Anope::ToString(this->level); } void AccessUnserialize(const Anope::string &data) override { - try - { - this->level = convertTo(data); - } - catch (const ConvertException &) - { - } + if (auto l = Anope::TryConvert(data)) + this->level = l.value(); } bool operator>(const ChanAccess &other) const override @@ -95,11 +90,9 @@ class CommandCSAccess final Privilege *p = NULL; int level = ACCESS_INVALID; - try - { - level = convertTo(params[3]); - } - catch (const ConvertException &) + if (auto lvl = Anope::TryConvert(params[3])) + level = lvl.value(); + else { p = PrivilegeManager::FindPrivilege(params[3]); if (p != NULL && defaultLevels[p->name]) @@ -402,7 +395,7 @@ class CommandCSAccess final } ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); + entry["Number"] = Anope::ToString(number); entry["Level"] = access->AccessSerialize(); entry["Mask"] = access->Mask(); entry["By"] = access->creator; @@ -442,7 +435,7 @@ class CommandCSAccess final } ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Level"] = access->AccessSerialize(); entry["Mask"] = access->Mask(); entry["By"] = access->creator; @@ -652,11 +645,9 @@ class CommandCSLevels final level = ACCESS_FOUNDER; else { - try - { - level = convertTo(lev); - } - catch (const ConvertException &) + if (auto lvl = Anope::TryConvert(lev)) + level = lvl.value(); + else { this->OnSyntaxError(source, "SET"); return; @@ -734,7 +725,7 @@ class CommandCSLevels final else if (j == ACCESS_FOUNDER) entry["Level"] = Language::Translate(source.GetAccount(), _("(founder only)")); else - entry["Level"] = stringify(j); + entry["Level"] = Anope::ToString(j); list.AddEntry(entry); } diff --git a/modules/chanserv/cs_akick.cpp b/modules/chanserv/cs_akick.cpp index 6457f2856..35052e63d 100644 --- a/modules/chanserv/cs_akick.cpp +++ b/modules/chanserv/cs_akick.cpp @@ -311,7 +311,7 @@ class CommandCSAKick final lastused = UNKNOWN; ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); + entry["Number"] = Anope::ToString(number); if (akick->nc) entry["Mask"] = akick->nc->display; else @@ -351,7 +351,7 @@ class CommandCSAKick final lastused = UNKNOWN; ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); if (akick->nc) entry["Mask"] = akick->nc->display; else diff --git a/modules/chanserv/cs_enforce.cpp b/modules/chanserv/cs_enforce.cpp index 825301cdd..3c0a464ef 100644 --- a/modules/chanserv/cs_enforce.cpp +++ b/modules/chanserv/cs_enforce.cpp @@ -166,14 +166,8 @@ private: return; } - int l; - try - { - l = convertTo(l_str); - if (l < 0) - throw ConvertException(); - } - catch (const ConvertException &) + auto l = Anope::Convert(l_str, -1); + if (l < 0) { source.Reply(_("The limit on %s is not valid."), ci->name.c_str()); return; diff --git a/modules/chanserv/cs_entrymsg.cpp b/modules/chanserv/cs_entrymsg.cpp index 03e4b22de..efe13d1aa 100644 --- a/modules/chanserv/cs_entrymsg.cpp +++ b/modules/chanserv/cs_entrymsg.cpp @@ -123,7 +123,7 @@ private: EntryMsg *msg = (*messages)->at(i); ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Creator"] = msg->creator; entry["Created"] = Anope::strftime(msg->when, NULL, true); entry["Message"] = msg->message; @@ -162,21 +162,16 @@ private: source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str()); else { - try + auto i = Anope::Convert(message, 0); + if (i > 0 && i <= (*messages)->size()) { - unsigned i = convertTo(message); - if (i > 0 && i <= (*messages)->size()) - { - delete (*messages)->at(i - 1); - if ((*messages)->empty()) - ci->Shrink("entrymsg"); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message"; - source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str()); - } - else - throw ConvertException(); + delete (*messages)->at(i - 1); + if ((*messages)->empty()) + ci->Shrink("entrymsg"); + Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message"; + source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str()); } - catch (const ConvertException &) + else { source.Reply(_("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str()); } diff --git a/modules/chanserv/cs_flags.cpp b/modules/chanserv/cs_flags.cpp index feb64aacd..7404aef57 100644 --- a/modules/chanserv/cs_flags.cpp +++ b/modules/chanserv/cs_flags.cpp @@ -331,7 +331,7 @@ class CommandCSFlags final ListFormatter::ListEntry entry; ++count; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Mask"] = access->Mask(); entry["Flags"] = flags; entry["Creator"] = access->creator; diff --git a/modules/chanserv/cs_info.cpp b/modules/chanserv/cs_info.cpp index 685538284..e02660301 100644 --- a/modules/chanserv/cs_info.cpp +++ b/modules/chanserv/cs_info.cpp @@ -58,7 +58,7 @@ public: if (show_all) { - info[_("Ban type")] = stringify(ci->bantype); + info[_("Ban type")] = Anope::ToString(ci->bantype); } FOREACH_MOD(OnChanInfo, (source, ci, info, show_all)); diff --git a/modules/chanserv/cs_list.cpp b/modules/chanserv/cs_list.cpp index 29add4596..c9589a268 100644 --- a/modules/chanserv/cs_list.cpp +++ b/modules/chanserv/cs_list.cpp @@ -36,12 +36,10 @@ public: sepstream(pattern.substr(1), '-').GetToken(n1, 0); sepstream(pattern, '-').GetToken(n2, 1); - try - { - from = convertTo(n1); - to = convertTo(n2); - } - catch (const ConvertException &) + auto num1 = Anope::TryConvert(n1); + auto num2 = Anope::TryConvert(n2); + + if (!num1.has_value() || !num2.has_value()) { source.Reply(LIST_INCORRECT_RANGE); source.Reply(_("To search for channels starting with #, search for the channel\n" @@ -49,6 +47,8 @@ public: return; } + from = num1.value(); + to = num2.value(); pattern = "*"; } diff --git a/modules/chanserv/cs_log.cpp b/modules/chanserv/cs_log.cpp index 213940a5c..8c1004eeb 100644 --- a/modules/chanserv/cs_log.cpp +++ b/modules/chanserv/cs_log.cpp @@ -135,7 +135,7 @@ public: const LogSetting *log = (*ls)->at(i); ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Service"] = log->command_service; entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name; entry["Method"] = log->method; diff --git a/modules/chanserv/cs_mode.cpp b/modules/chanserv/cs_mode.cpp index 8c7c7c1c3..8f462a3cb 100644 --- a/modules/chanserv/cs_mode.cpp +++ b/modules/chanserv/cs_mode.cpp @@ -716,7 +716,7 @@ class CommandCSMode final std::vector new_params; new_params.push_back(params[0]); new_params.emplace_back("SET"); - new_params.push_back("-" + stringify(cm->mchar)); + new_params.push_back("-" + Anope::ToString(cm->mchar)); new_params.emplace_back("*"); this->DoSet(source, ci, new_params); } diff --git a/modules/chanserv/cs_set.cpp b/modules/chanserv/cs_set.cpp index d5ed4713f..c7952baba 100644 --- a/modules/chanserv/cs_set.cpp +++ b/modules/chanserv/cs_set.cpp @@ -165,19 +165,16 @@ public: return; } - try - { - int16_t new_type = convertTo(params[1]); - if (new_type < 0 || new_type > 3) - throw ConvertException("Invalid range"); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type; - ci->bantype = new_type; - source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype); - } - catch (const ConvertException &) + auto new_type = Anope::Convert(params[1], -1); + if (new_type < 0 || new_type > 3) { source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str()); + return; } + + Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type; + ci->bantype = new_type; + source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype); } bool OnHelp(CommandSource &source, const Anope::string &) override diff --git a/modules/chanserv/cs_xop.cpp b/modules/chanserv/cs_xop.cpp index b47e1e988..0ec8e8d25 100644 --- a/modules/chanserv/cs_xop.cpp +++ b/modules/chanserv/cs_xop.cpp @@ -420,7 +420,7 @@ private: return; ListFormatter::ListEntry entry; - entry["Number"] = stringify(Number); + entry["Number"] = Anope::ToString(Number); entry["Mask"] = a->Mask(); entry["Description"] = a->description; this->list.AddEntry(entry); @@ -440,7 +440,7 @@ private: continue; ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Mask"] = a->Mask(); entry["Description"] = a->description; list.AddEntry(entry); diff --git a/modules/database/db_atheme.cpp b/modules/database/db_atheme.cpp index 3e613562b..3f62c29ca 100644 --- a/modules/database/db_atheme.cpp +++ b/modules/database/db_atheme.cpp @@ -56,16 +56,7 @@ public: template std::enable_if_t, Numeric> GetNum() { - try - { - auto token = Get(); - std::stringstream stream(token.str()); - Numeric ntoken = 0; - stream >> ntoken; - return ntoken; - } - catch (const ConvertException &) { } - return 0; + return Anope::Convert(Get(), 0); } // Retrieves the entire row. @@ -869,7 +860,7 @@ private: else if (key == "private:close:reason") data->suspend_reason = value; else if (key == "private:close:timestamp") - data->suspend_ts = convertTo(value); + data->suspend_ts = Anope::Convert(value, 0); else if (key == "private:entrymsg") { auto *eml = ci->Require("entrymsg"); @@ -891,19 +882,19 @@ private: else if (key == "private:klinechan:reason") data->suspend_reason = value; else if (key == "private:klinechan:timestamp") - data->suspend_ts = convertTo(value); + data->suspend_ts = Anope::Convert(value, 0); else if (key == "private:mark:reason") data->info_message = value; else if (key == "private:mark:setter") data->info_adder = value; else if (key == "private:mark:timestamp") - data->info_ts = convertTo(value); + data->info_ts = Anope::Convert(value, 0); else if (key == "private:topic:setter") ci->last_topic_setter = value; else if (key == "private:topic:text") ci->last_topic = value; else if (key == "private:topic:ts") - ci->last_topic_time = convertTo(value); + ci->last_topic_time = Anope::Convert(value, 0); else Log(this) << "Unknown channel metadata " << key << " = " << value; @@ -953,7 +944,7 @@ private: auto kill = Config->GetModule("nickserv")->Get("kill", "60s"); auto killquick = Config->GetModule("nickserv")->Get("killquick", "20s"); - auto secs = convertTo(value); + auto secs = Anope::Convert(value, kill); if (secs >= kill) nc->Extend("KILLPROTECT"); else if (secs >= killquick) @@ -966,7 +957,7 @@ private: else if (key == "private:freeze:reason") data->suspend_reason = value; else if (key == "private:freeze:timestamp") - data->suspend_ts = convertTo(value); + data->suspend_ts = Anope::Convert(value, 0); else if (key == "private:host:actual") data->last_real_mask = value; else if (key == "private:host:vhost") @@ -978,13 +969,13 @@ private: else if (key == "private:mark:setter") data->info_adder = value; else if (key == "private:mark:timestamp") - data->info_ts = convertTo(value); + data->info_ts = Anope::Convert(value, 0); else if (key == "private:usercloak") data->vhost = value; else if (key == "private:usercloak-assigner") data->vhost_creator = value; else if (key == "private:usercloak-timestamp") - data->vhost_ts = convertTo(value); + data->vhost_ts = Anope::Convert(value, 0); else if (key.compare(0, 18, "private:usercloak:", 18) == 0) data->vhost_nick[key.substr(18)] = value; else diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp index d2225ce88..63c18f744 100644 --- a/modules/database/db_flatfile.cpp +++ b/modules/database/db_flatfile.cpp @@ -52,12 +52,7 @@ public: { if (token.find("ID ") == 0) { - try - { - this->id = convertTo(token.substr(3)); - } - catch (const ConvertException &) { } - + this->id = Anope::Convert(token.substr(3), 0); continue; } else if (token.find("DATA ") != 0) @@ -136,7 +131,7 @@ class DBFlatFile final for (const auto &db : dbs) { const Anope::string &oldname = Anope::DataDir + "/" + db; - Anope::string newname = Anope::DataDir + "/backups/" + db + "-" + stringify(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday); + Anope::string newname = Anope::DataDir + "/backups/" + db + "-" + Anope::ToString(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday); /* Backup already exists or no database to backup */ if (Anope::IsFile(newname) || !Anope::IsFile(oldname)) diff --git a/modules/database/db_old.cpp b/modules/database/db_old.cpp index c3e82ea39..e95cc19ef 100644 --- a/modules/database/db_old.cpp +++ b/modules/database/db_old.cpp @@ -152,7 +152,7 @@ static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status, uint32_t if (cm && ml) { if (limit && mlock_info.c == 'l') - ml->SetMLock(cm, status, stringify(*limit)); + ml->SetMLock(cm, status, Anope::ToString(*limit)); else if (key && mlock_info.c == 'k') ml->SetMLock(cm, status, *key); else @@ -889,7 +889,7 @@ static void LoadChannels() } } else - access->AccessUnserialize(stringify(level)); + access->AccessUnserialize(Anope::ToString(level)); } Anope::string mask; diff --git a/modules/database/db_redis.cpp b/modules/database/db_redis.cpp index b4abcab7f..413729887 100644 --- a/modules/database/db_redis.cpp +++ b/modules/database/db_redis.cpp @@ -162,7 +162,7 @@ public: std::vector args; args.emplace_back("HGETALL"); - args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id)); + args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id)); /* Get object attrs to clear before updating */ redis->SendCommand(new Updater(this, t->GetName(), obj->id), args); @@ -248,7 +248,7 @@ public: std::vector args; args.emplace_back("HGETALL"); - args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id)); + args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id)); /* Get all of the attributes for this object */ redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args); @@ -278,19 +278,14 @@ void TypeLoader::OnResult(const Reply &r) if (reply->type != Reply::BULK) continue; - int64_t id; - try - { - id = convertTo(reply->bulk); - } - catch (const ConvertException &) - { + auto i = Anope::TryConvert(reply->bulk); + if (!i) continue; - } + auto id = i.value(); std::vector args; args.emplace_back("HGETALL"); - args.push_back("hash:" + this->type + ":" + stringify(id)); + args.push_back("hash:" + this->type + ":" + Anope::ToString(id)); me->redis->SendCommand(new ObjectLoader(me, this->type, id), args); } @@ -364,7 +359,7 @@ void Deleter::OnResult(const Reply &r) std::vector args; args.emplace_back("DEL"); - args.push_back("hash:" + this->type + ":" + stringify(this->id)); + args.push_back("hash:" + this->type + ":" + Anope::ToString(this->id)); /* Delete hash object */ me->redis->SendCommand(NULL, args); @@ -372,7 +367,7 @@ void Deleter::OnResult(const Reply &r) args.clear(); args.emplace_back("SREM"); args.push_back("ids:" + this->type); - args.push_back(stringify(this->id)); + args.push_back(Anope::ToString(this->id)); /* Delete id from ids set */ me->redis->SendCommand(NULL, args); @@ -385,7 +380,7 @@ void Deleter::OnResult(const Reply &r) args.clear(); args.emplace_back("SREM"); args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk); - args.push_back(stringify(this->id)); + args.push_back(Anope::ToString(this->id)); /* Delete value -> object id */ me->redis->SendCommand(NULL, args); @@ -428,7 +423,7 @@ void Updater::OnResult(const Reply &r) std::vector args; args.emplace_back("SREM"); args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk); - args.push_back(stringify(this->id)); + args.push_back(Anope::ToString(this->id)); /* Delete value -> object id */ me->redis->SendCommand(NULL, args); @@ -438,12 +433,12 @@ void Updater::OnResult(const Reply &r) std::vector args; args.emplace_back("SADD"); args.push_back("ids:" + this->type); - args.push_back(stringify(obj->id)); + args.push_back(Anope::ToString(obj->id)); me->redis->SendCommand(NULL, args); args.clear(); args.emplace_back("HMSET"); - args.push_back("hash:" + this->type + ":" + stringify(obj->id)); + args.push_back("hash:" + this->type + ":" + Anope::ToString(obj->id)); for (const auto &[key, value] : data.data) { @@ -454,7 +449,7 @@ void Updater::OnResult(const Reply &r) args2.emplace_back("SADD"); args2.push_back("value:" + this->type + ":" + key + ":" + value->str()); - args2.push_back(stringify(obj->id)); + args2.push_back(Anope::ToString(obj->id)); /* Add to value -> object id set */ me->redis->SendCommand(NULL, args2); @@ -505,16 +500,11 @@ void SubscriptionListener::OnResult(const Reply &r) if (s_type == NULL) return; - uint64_t obj_id; - try - { - obj_id = convertTo(id); - } - catch (const ConvertException &) - { + auto oid = Anope::TryConvert(id); + if (!oid.has_value()) return; - } + auto obj_id = oid.value(); if (op == "hset" || op == "hdel") { Serializable *s = s_type->objects[obj_id]; @@ -564,7 +554,7 @@ void SubscriptionListener::OnResult(const Reply &r) std::vector args; args.emplace_back("SREM"); args.push_back("ids:" + type); - args.push_back(stringify(s->id)); + args.push_back(Anope::ToString(s->id)); /* Delete object from id set */ me->redis->SendCommand(NULL, args); @@ -604,7 +594,7 @@ void ModifiedObject::OnResult(const Reply &r) std::vector args; args.emplace_back("SREM"); args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str()); - args.push_back(stringify(this->id)); + args.push_back(Anope::ToString(this->id)); /* Delete value -> object id */ me->redis->SendCommand(NULL, args); @@ -633,7 +623,7 @@ void ModifiedObject::OnResult(const Reply &r) std::vector args; args.emplace_back("SADD"); args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str()); - args.push_back(stringify(obj->id)); + args.push_back(Anope::ToString(obj->id)); /* Add to value -> object id set */ me->redis->SendCommand(NULL, args); @@ -642,7 +632,7 @@ void ModifiedObject::OnResult(const Reply &r) std::vector args; args.emplace_back("SADD"); args.push_back("ids:" + st->GetName()); - args.push_back(stringify(obj->id)); + args.push_back(Anope::ToString(obj->id)); /* Add to type -> id set */ me->redis->SendCommand(NULL, args); diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp index 24b5c1f1f..d8fe89972 100644 --- a/modules/database/db_sql.cpp +++ b/modules/database/db_sql.cpp @@ -209,7 +209,7 @@ public: return; Serialize::Type *s_type = obj->GetSerializableType(); if (s_type && obj->id > 0) - this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id)); + this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id)); this->updated_items.erase(obj); } @@ -240,18 +240,14 @@ public: data[key] << value; Serializable *obj = sb->Unserialize(NULL, data); - try - { - if (obj) - obj->id = convertTo(res.Get(j, "id")); - } - catch (const ConvertException &) - { - Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName(); - } - if (obj) { + auto oid = Anope::TryConvert(res.Get(j, "id")); + if (oid.has_value()) + obj->id = oid.value(); + else + Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName(); + /* The Unserialize operation is destructive so rebuild the data for UpdateCache. * Also the old data may contain columns that we don't use, so we reserialize the * object to know for sure our cache is consistent diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp index d97fe6683..839126d41 100644 --- a/modules/database/db_sql_live.cpp +++ b/modules/database/db_sql_live.cpp @@ -163,7 +163,7 @@ public: if (s_type) { if (obj->id > 0) - this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id)); + this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id)); s_type->objects.erase(obj->id); } this->updated_items.erase(obj); @@ -185,17 +185,16 @@ public: { const std::map &row = res.Row(i); - unsigned int id; - try - { - id = convertTo(res.Get(i, "id")); - } - catch (const ConvertException &) + + + auto oid = Anope::TryConvert(res.Get(i, "id")); + if (!oid.has_value()) { Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName(); continue; } + auto id = oid.value(); if (res.Get(i, "timestamp").empty()) { clear_null = true; @@ -237,7 +236,7 @@ public: else { if (!s) - this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id)); + this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id)); else delete s; } diff --git a/modules/encryption/enc_bcrypt.cpp b/modules/encryption/enc_bcrypt.cpp index 7fd3864ac..0800b2d66 100644 --- a/modules/encryption/enc_bcrypt.cpp +++ b/modules/encryption/enc_bcrypt.cpp @@ -142,19 +142,15 @@ public: if (bcryptprovider.Compare(hash_value, req->GetPassword())) { unsigned long rounds = 0; - try - { - // Try to extract the rounds count to cher - pos = hash_value.find('$', 4); - if (pos == Anope::string::npos) - throw ConvertException("Malformed BCrypt hash?!"); - - rounds = convertTo(hash_value.substr(4, pos - 4)); - } - catch (const ConvertException &) - { + + // Try to extract the rounds count to check if we need to + // re-encrypt the password. + pos = hash_value.find('$', 4); + if (pos != Anope::string::npos) + rounds = Anope::Convert(hash_value.substr(4, pos - 4), 0); + + if (!rounds) Log(LOG_DEBUG) << "Unable to determine the rounds of a bcrypt hash: " << hash_value; - } // If we are NOT the first encryption module or the Bcrypt rounds // are different we want to re-encrypt the password with the primary diff --git a/modules/extra/mysql.cpp b/modules/extra/mysql.cpp index 49149464f..72c026dad 100644 --- a/modules/extra/mysql.cpp +++ b/modules/extra/mysql.cpp @@ -452,7 +452,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat for (const auto &[field, _] : data.data) query_text += ",`" + field + "`"; - query_text += ") VALUES (" + stringify(id); + query_text += ") VALUES (" + Anope::ToString(id); for (const auto &[field, _] : data.data) query_text += ",@" + field + "@"; query_text += ") ON DUPLICATE KEY UPDATE "; @@ -536,7 +536,7 @@ Anope::string MySQLService::BuildQuery(const Query &q) Anope::string MySQLService::FromUnixtime(time_t t) { - return "FROM_UNIXTIME(" + stringify(t) + ")"; + return "FROM_UNIXTIME(" + Anope::ToString(t) + ")"; } void DispatcherThread::Run() diff --git a/modules/extra/regex_pcre2.cpp b/modules/extra/regex_pcre2.cpp index ef2786823..991be3f6c 100644 --- a/modules/extra/regex_pcre2.cpp +++ b/modules/extra/regex_pcre2.cpp @@ -30,7 +30,7 @@ public: { PCRE2_UCHAR error[128]; pcre2_get_error_message(errcode, error, sizeof error); - throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + reinterpret_cast(error)); + throw RegexException("Error in regex " + expr + " at offset " + Anope::ToString(erroffset) + ": " + reinterpret_cast(error)); } } diff --git a/modules/extra/sqlite.cpp b/modules/extra/sqlite.cpp index b481093ca..4968e8e0d 100644 --- a/modules/extra/sqlite.cpp +++ b/modules/extra/sqlite.cpp @@ -297,7 +297,7 @@ Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Da query_text.erase(query_text.length() - 1); query_text += ") VALUES ("; if (id > 0) - query_text += stringify(id) + ","; + query_text += Anope::ToString(id) + ","; for (const auto &[field, _] : data.data) query_text += "@" + field + "@,"; query_text.erase(query_text.length() - 1); @@ -339,7 +339,7 @@ Anope::string SQLiteService::BuildQuery(const Query &q) Anope::string SQLiteService::FromUnixtime(time_t t) { - return "datetime('" + stringify(t) + "', 'unixepoch')"; + return "datetime('" + Anope::ToString(t) + "', 'unixepoch')"; } MODULE_INIT(ModuleSQLite) diff --git a/modules/hostserv/hs_list.cpp b/modules/hostserv/hs_list.cpp index 7b85bead3..dd459fd78 100644 --- a/modules/hostserv/hs_list.cpp +++ b/modules/hostserv/hs_list.cpp @@ -45,12 +45,9 @@ public: source.Reply(LIST_INCORRECT_RANGE); return; } - try - { - from = convertTo(key.substr(1, tmp - 1)); - to = convertTo(key.substr(tmp + 1)); - } - catch (const ConvertException &) { } + + from = Anope::Convert(key.substr(1, tmp - 1), 0); + to = Anope::Convert(key.substr(tmp + 1), 0); } } @@ -70,7 +67,7 @@ public: ++display_counter; ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); + entry["Number"] = Anope::ToString(display_counter); entry["Nick"] = na->nick; entry["Vhost"] = na->GetVhostMask(); entry["Creator"] = na->GetVhostCreator(); @@ -88,7 +85,7 @@ public: { ++display_counter; ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); + entry["Number"] = Anope::ToString(display_counter); entry["Nick"] = na->nick; entry["Vhost"] = na->GetVhostMask(); entry["Creator"] = na->GetVhostCreator(); diff --git a/modules/hostserv/hs_request.cpp b/modules/hostserv/hs_request.cpp index 021e5f5b7..d7bc6bc34 100644 --- a/modules/hostserv/hs_request.cpp +++ b/modules/hostserv/hs_request.cpp @@ -320,7 +320,7 @@ public: ++display_counter; ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); + entry["Number"] = Anope::ToString(display_counter); entry["Nick"] = nick; if (!hr->ident.empty()) entry["Vhost"] = hr->ident + "@" + hr->host; diff --git a/modules/httpd.cpp b/modules/httpd.cpp index 226d750fe..f784d2d32 100644 --- a/modules/httpd.cpp +++ b/modules/httpd.cpp @@ -216,11 +216,8 @@ public: } else if (buf.find_ci("Content-Length: ") == 0) { - try - { - this->content_length = convertTo(buf.substr(16)); - } - catch (const ConvertException &ex) { } + if (auto len = Anope::TryConvert(buf.substr(16))) + this->content_length = len.value(); } else if (buf.find(':') != Anope::string::npos) { @@ -252,7 +249,7 @@ public: this->WriteClient("Content-Type: text/html"); else this->WriteClient("Content-Type: " + msg->content_type); - this->WriteClient("Content-Length: " + stringify(msg->length)); + this->WriteClient("Content-Length: " + Anope::ToString(msg->length)); for (const auto &cookie : msg->cookies) { diff --git a/modules/memoserv/memoserv.cpp b/modules/memoserv/memoserv.cpp index 45642b46d..084650542 100644 --- a/modules/memoserv/memoserv.cpp +++ b/modules/memoserv/memoserv.cpp @@ -24,13 +24,13 @@ class MemoServCore final subject = subject.replace_all_cs("%n", nc->display); subject = subject.replace_all_cs("%s", m->sender); - subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + subject = subject.replace_all_cs("%d", Anope::ToString(mi->GetIndex(m) + 1)); subject = subject.replace_all_cs("%t", m->text); subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get("networkname")); message = message.replace_all_cs("%n", nc->display); message = message.replace_all_cs("%s", m->sender); - message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + message = message.replace_all_cs("%d", Anope::ToString(mi->GetIndex(m) + 1)); message = message.replace_all_cs("%t", m->text); message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get("networkname")); diff --git a/modules/memoserv/ms_list.cpp b/modules/memoserv/ms_list.cpp index 127cfdaaf..a25a95ed0 100644 --- a/modules/memoserv/ms_list.cpp +++ b/modules/memoserv/ms_list.cpp @@ -85,7 +85,7 @@ public: const Memo *m = mi->GetMemo(number - 1); ListFormatter::ListEntry entry; - entry["Number"] = (m->unread ? "* " : " ") + stringify(number); + entry["Number"] = (m->unread ? "* " : " ") + Anope::ToString(number); entry["Sender"] = m->sender; entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount()); this->list.AddEntry(entry); @@ -120,7 +120,7 @@ public: const Memo *m = mi->GetMemo(i); ListFormatter::ListEntry entry; - entry["Number"] = (m->unread ? "* " : " ") + stringify(i + 1); + entry["Number"] = (m->unread ? "* " : " ") + Anope::ToString(i + 1); entry["Sender"] = m->sender; entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount()); list.AddEntry(entry); diff --git a/modules/memoserv/ms_set.cpp b/modules/memoserv/ms_set.cpp index 83b28fb20..54ad7c252 100644 --- a/modules/memoserv/ms_set.cpp +++ b/modules/memoserv/ms_set.cpp @@ -135,12 +135,8 @@ private: else nc->Shrink("MEMO_HARDMAX"); } - limit = -1; - try - { - limit = convertTo(p1); - } - catch (const ConvertException &) { } + + limit = Anope::Convert(p1, -1); } else { @@ -160,12 +156,8 @@ private: return; } int max_memos = Config->GetModule("memoserv")->Get("maxmemos"); - limit = -1; - try - { - limit = convertTo(p1); - } - catch (const ConvertException &) { } + limit = Anope::Convert(p1, -1); + /* The first character is a digit, but we could still go negative * from overflow... watch out! */ if (limit < 0 || (max_memos > 0 && limit > max_memos)) diff --git a/modules/nickserv/nickserv.cpp b/modules/nickserv/nickserv.cpp index 541b7f0f9..f1f087163 100644 --- a/modules/nickserv/nickserv.cpp +++ b/modules/nickserv/nickserv.cpp @@ -246,7 +246,7 @@ public: int i = 0; do { - guestnick = guestprefix + stringify(static_cast(Anope::RandomNumber())); + guestnick = guestprefix + Anope::ToString(static_cast(Anope::RandomNumber())); if (guestnick.length() > nicklen) guestnick = guestnick.substr(0, nicklen); } diff --git a/modules/nickserv/ns_ajoin.cpp b/modules/nickserv/ns_ajoin.cpp index f6e716a36..91e700e4a 100644 --- a/modules/nickserv/ns_ajoin.cpp +++ b/modules/nickserv/ns_ajoin.cpp @@ -105,7 +105,7 @@ class CommandNSAJoin final { AJoinEntry *aj = (*channels)->at(i); ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Channel"] = aj->channel; entry["Key"] = aj->key; list.AddEntry(entry); @@ -382,13 +382,11 @@ public: Anope::string l; if (c->GetParam("LIMIT", l)) { - try + if (auto limit = Anope::TryConvert(l)) { - unsigned limit = convertTo(l); - if (c->users.size() >= limit) + if (c->users.size() >= limit.value()) need_invite = true; } - catch (const ConvertException &) { } } } } diff --git a/modules/nickserv/ns_alist.cpp b/modules/nickserv/ns_alist.cpp index e4adfb870..0d02894af 100644 --- a/modules/nickserv/ns_alist.cpp +++ b/modules/nickserv/ns_alist.cpp @@ -59,7 +59,7 @@ public: if (ci->GetFounder() == nc) { ++chan_count; - entry["Number"] = stringify(chan_count); + entry["Number"] = Anope::ToString(chan_count); entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; entry["Access"] = Language::Translate(source.GetAccount(), _("Founder")); entry["Description"] = ci->desc; @@ -70,7 +70,7 @@ public: if (ci->GetSuccessor() == nc) { ++chan_count; - entry["Number"] = stringify(chan_count); + entry["Number"] = Anope::ToString(chan_count); entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; entry["Access"] = Language::Translate(source.GetAccount(), _("Successor")); entry["Description"] = ci->desc; @@ -84,7 +84,7 @@ public: ++chan_count; - entry["Number"] = stringify(chan_count); + entry["Number"] = Anope::ToString(chan_count); entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; for (auto &p : access.paths) { diff --git a/modules/nickserv/ns_list.cpp b/modules/nickserv/ns_list.cpp index a1c28a28d..1bd4ea043 100644 --- a/modules/nickserv/ns_list.cpp +++ b/modules/nickserv/ns_list.cpp @@ -39,17 +39,17 @@ public: Anope::string n1, n2; sepstream(pattern.substr(1), '-').GetToken(n1, 0); sepstream(pattern, '-').GetToken(n2, 1); - try - { - from = convertTo(n1); - to = convertTo(n2); - } - catch (const ConvertException &) + + auto num1 = Anope::TryConvert(n1); + auto num2 = Anope::TryConvert(n2); + if (!num1.has_value() || !num2.has_value()) { source.Reply(LIST_INCORRECT_RANGE); return; } + from = num1.value(); + to = num2.value(); pattern = "*"; } diff --git a/modules/operserv/os_akill.cpp b/modules/operserv/os_akill.cpp index 3f5e9c7d2..7fcacd9ad 100644 --- a/modules/operserv/os_akill.cpp +++ b/modules/operserv/os_akill.cpp @@ -285,7 +285,7 @@ private: return; ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); + entry["Number"] = Anope::ToString(number); entry["Mask"] = x->mask; entry["Creator"] = x->by; entry["Created"] = Anope::strftime(x->created, NULL, true); @@ -307,7 +307,7 @@ private: if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true)) { ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Mask"] = x->mask; entry["Creator"] = x->by; entry["Created"] = Anope::strftime(x->created, NULL, true); diff --git a/modules/operserv/os_defcon.cpp b/modules/operserv/os_defcon.cpp index dbb0edb69..564cfec50 100644 --- a/modules/operserv/os_defcon.cpp +++ b/modules/operserv/os_defcon.cpp @@ -192,13 +192,7 @@ public: return; } - int newLevel = 0; - try - { - newLevel = convertTo(lvl); - } - catch (const ConvertException &) { } - + auto newLevel = Anope::Convert(lvl, 0); if (newLevel < 1 || newLevel > 5) { this->OnSyntaxError(source, ""); diff --git a/modules/operserv/os_dns.cpp b/modules/operserv/os_dns.cpp index 99d01e7b7..18e53b25a 100644 --- a/modules/operserv/os_dns.cpp +++ b/modules/operserv/os_dns.cpp @@ -42,7 +42,7 @@ struct DNSZone final data["name"] << name; unsigned count = 0; for (const auto &server : servers) - data["server" + stringify(count++)] << server; + data["server" + Anope::ToString(count++)] << server; } static Serializable *Unserialize(Serializable *obj, Serialize::Data &data) @@ -64,7 +64,7 @@ struct DNSZone final for (unsigned count = 0; true; ++count) { Anope::string server_str; - data["server" + stringify(count)] >> server_str; + data["server" + Anope::ToString(count)] >> server_str; if (server_str.empty()) break; zone->servers.insert(server_str); @@ -146,12 +146,12 @@ public: { data["server_name"] << server_name; for (unsigned i = 0; i < ips.size(); ++i) - data["ip" + stringify(i)] << ips[i]; + data["ip" + Anope::ToString(i)] << ips[i]; data["limit"] << limit; data["pooled"] << pooled; unsigned count = 0; for (const auto &zone : zones) - data["zone" + stringify(count++)] << zone; + data["zone" + Anope::ToString(count++)] << zone; } static Serializable *Unserialize(Serializable *obj, Serialize::Data &data) @@ -172,7 +172,7 @@ public: for (unsigned i = 0; true; ++i) { Anope::string ip_str; - data["ip" + stringify(i)] >> ip_str; + data["ip" + Anope::ToString(i)] >> ip_str; if (ip_str.empty()) break; req->ips.push_back(ip_str); @@ -185,7 +185,7 @@ public: for (unsigned i = 0; true; ++i) { Anope::string zone_str; - data["zone" + stringify(i)] >> zone_str; + data["zone" + Anope::ToString(i)] >> zone_str; if (zone_str.empty()) break; req->zones.insert(zone_str); @@ -225,7 +225,7 @@ class CommandOSDNS final ListFormatter::ListEntry entry; entry["Server"] = s->GetName(); - entry["Limit"] = s->GetLimit() ? stringify(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None")); + entry["Limit"] = s->GetLimit() ? Anope::ToString(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None")); Anope::string ip_str; for (const auto &ip : s->GetIPs()) @@ -579,16 +579,15 @@ class CommandOSDNS final if (params[2].equals_ci("LIMIT")) { - try + if (auto l = Anope::TryConvert(params[3])) { - unsigned l = convertTo(params[3]); - s->SetLimit(l); - if (l) - source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), l); + s->SetLimit(l.value()); + if (s->GetLimit()) + source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), s->GetLimit()); else source.Reply(_("User limit for %s removed."), s->GetName().c_str()); } - catch (const ConvertException &ex) + else { source.Reply(_("Invalid value for LIMIT. Must be numerical.")); } diff --git a/modules/operserv/os_list.cpp b/modules/operserv/os_list.cpp index a6969dc24..ba1156967 100644 --- a/modules/operserv/os_list.cpp +++ b/modules/operserv/os_list.cpp @@ -60,7 +60,7 @@ public: ListFormatter::ListEntry entry; entry["Name"] = cc->chan->name; - entry["Users"] = stringify(cc->chan->users.size()); + entry["Users"] = Anope::ToString(cc->chan->users.size()); entry["Modes"] = cc->chan->GetModes(true, true); entry["Topic"] = cc->chan->topic; list.AddEntry(entry); @@ -87,7 +87,7 @@ public: ListFormatter::ListEntry entry; entry["Name"] = c->name; - entry["Users"] = stringify(c->users.size()); + entry["Users"] = Anope::ToString(c->users.size()); entry["Modes"] = c->GetModes(true, true); entry["Topic"] = c->topic; list.AddEntry(entry); diff --git a/modules/operserv/os_logsearch.cpp b/modules/operserv/os_logsearch.cpp index 606a74d78..0282644b2 100644 --- a/modules/operserv/os_logsearch.cpp +++ b/modules/operserv/os_logsearch.cpp @@ -47,32 +47,22 @@ public: if (params[i].length() > 2) { Anope::string dur = params[i].substr(1, params[i].length() - 2); - try - { - days = convertTo(dur); - if (days <= 0) - throw ConvertException(); - } - catch (const ConvertException &) - { + auto d = Anope::Convert(dur, 0); + if (d > 0) + days = d; + else source.Reply(_("Invalid duration %s, using %d days."), dur.c_str(), days); - } } break; case 'l': if (params[i].length() > 2) { Anope::string dur = params[i].substr(1, params[i].length() - 2); - try - { - replies = convertTo(dur); - if (replies <= 0) - throw ConvertException(); - } - catch (const ConvertException &) - { + auto r = Anope::Convert(dur, 0); + if (r > 0) + replies = r; + else source.Reply(_("Invalid limit %s, using %d."), dur.c_str(), replies); - } } break; default: diff --git a/modules/operserv/os_news.cpp b/modules/operserv/os_news.cpp index 067bfbc74..2cf011c0e 100644 --- a/modules/operserv/os_news.cpp +++ b/modules/operserv/os_news.cpp @@ -168,7 +168,7 @@ protected: for (unsigned i = 0, end = list.size(); i < end; ++i) { ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); + entry["Number"] = Anope::ToString(i + 1); entry["Creator"] = list[i]->who; entry["Created"] = Anope::strftime(list[i]->time, NULL, true); entry["Text"] = list[i]->text; @@ -232,18 +232,14 @@ protected: source.Reply(READ_ONLY_MODE); if (!text.equals_ci("ALL")) { - try + unsigned num = Anope::Convert(text, 0); + if (num > 0 && num <= list.size()) { - unsigned num = convertTo(text); - if (num > 0 && num <= list.size()) - { - this->ns->DelNewsItem(list[num - 1]); - source.Reply(msgs[MSG_DELETED], num); - Log(LOG_ADMIN, source, this) << "to delete a news item"; - return; - } + this->ns->DelNewsItem(list[num - 1]); + source.Reply(msgs[MSG_DELETED], num); + Log(LOG_ADMIN, source, this) << "to delete a news item"; + return; } - catch (const ConvertException &) { } source.Reply(msgs[MSG_DEL_NOT_FOUND], text.c_str()); } diff --git a/modules/operserv/os_session.cpp b/modules/operserv/os_session.cpp index 02695c55a..1e59f7d04 100644 --- a/modules/operserv/os_session.cpp +++ b/modules/operserv/os_session.cpp @@ -178,13 +178,7 @@ private: { Anope::string param = params[1]; - unsigned mincount = 0; - try - { - mincount = convertTo(param); - } - catch (const ConvertException &) { } - + auto mincount = Anope::Convert(param, 0); if (mincount <= 1) source.Reply(_("Invalid threshold value. It must be a valid integer greater than 1.")); else @@ -197,7 +191,7 @@ private: if (session->count >= mincount) { ListFormatter::ListEntry entry; - entry["Session"] = stringify(session->count); + entry["Session"] = Anope::ToString(session->count); entry["Host"] = session->addr.mask(); list.AddEntry(entry); } @@ -327,13 +321,7 @@ private: else if (expires > 0) expires += Anope::CurTime; - unsigned limit = -1; - try - { - limit = convertTo(limitstr); - } - catch (const ConvertException &) { } - + auto limit = Anope::C