diff options
author | Sadie Powell <sadie@witchery.services> | 2024-03-11 13:53:05 +0000 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2024-03-11 19:17:29 +0000 |
commit | 29e7674e56bf2b829bba22def2760d034a76e788 (patch) | |
tree | f40049ba995b03dd7c510d88f9f19db2d2e65a2e /include/convert.h | |
parent | e2df7d4d01f8fdb41c49ce8efc462cab005e7d5c (diff) |
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.
Diffstat (limited to 'include/convert.h')
-rw-r--r-- | include/convert.h | 133 |
1 files changed, 133 insertions, 0 deletions
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 <optional> + +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<typename T> + inline std::optional<T> 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<typename T> + inline T Convert(const Anope::string &in, T def, Anope::string *leftover = nullptr) + { + return TryConvert<T>(in, leftover).value_or(def); + } + + /** Attempts to convert any type to a string. + * @param in The value to convert. + */ + template <class T> + inline std::optional<Anope::string> 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<string::value_type>(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<string::value_type>(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<typename Stringable> + inline std::enable_if_t<std::is_arithmetic_v<Stringable>, string> ToString(const Stringable &in) + { + return std::to_string(in); + } + + /** Converts any type to a string. + * @param in The value to convert. + */ + template <class T> + inline std::enable_if_t<!std::is_arithmetic_v<T>, string> ToString(const T &in) + { + return TryString(in).value_or(Anope::string()); + } +} |