changeset 211:7cf53145de11

strings: use templates for ToInt, std::to_string -> Strings::ToUtf8String
author Paper <mrpapersonic@gmail.com>
date Sun, 07 Jan 2024 09:54:17 -0500
parents da91af31ae73
children 6b08fbd7f206
files include/core/strings.h src/core/anime.cc src/core/strings.cc src/core/time.cc src/gui/pages/anime_list.cc src/services/anilist.cc
diffstat 6 files changed, 44 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/include/core/strings.h	Tue Jan 02 02:37:03 2024 -0500
+++ b/include/core/strings.h	Sun Jan 07 09:54:17 2024 -0500
@@ -3,10 +3,7 @@
 
 #include <string>
 #include <vector>
-#include <array>
-#include <limits>
-#include <stdexcept>
-#include <cstdint>
+#include <sstream>
 
 class QString;
 class QByteArray;
@@ -14,7 +11,8 @@
 namespace Strings {
 
 /* Implode function: takes a vector of strings and turns it
-   into a string, separated by delimiters. */
+ * into a string, separated by delimiters.
+*/
 std::string Implode(const std::vector<std::string>& vector, const std::string& delimiter);
 std::vector<std::string> Split(const std::string &text, const std::string& delimiter);
 
@@ -31,7 +29,10 @@
 std::string ToLower(const std::string& string);
 
 /* functions that make the way we convert from and to
-   different string formats universal */
+ * different string formats universal (and these functions
+ * typically do things the right way so we avoid retarded
+ * code)
+*/
 std::wstring ToWstring(const std::string& string);
 std::wstring ToWstring(const QString& string);
 std::string ToUtf8String(const std::wstring& wstring);
@@ -40,28 +41,26 @@
 QString ToQString(const std::string& string);
 QString ToQString(const std::wstring& wstring);
 
-/* arithmetic :) */
-template<typename T = int>
+/* not really an "int"... but who cares? */
+template<typename T = int,
+         std::enable_if_t<std::is_integral<T>::value, bool> = true>
 T ToInt(const std::string& str, T def = 0) {
-   auto clamp = [](const T& val, const T& min, const T& max){
-      return std::max(min, std::min(val, max));
-   };
-
-   try {
-      if constexpr (std::is_signed<T>::value) {
-         return clamp(std::stoll(str), std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
-      } else if constexpr (std::is_unsigned<T>::value) {
-         return clamp(std::stoull(str), std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
-      } else {
-         throw std::invalid_argument("Invalid input to Strings::ToInt()!");
-      }
-   } catch (std::invalid_argument const& ex) {
-      return def;
-   }
+	std::istringstream s(str);
+	s >> std::noboolalpha >> def;
+	return def;
 }
 
-bool ToBool(const std::string& s, const bool def = false);
-std::string ToUtf8String(const bool b);
+template<typename T,
+         std::enable_if_t<std::is_integral<T>::value && !std::is_same<T, bool>::value, bool> = true>
+std::string ToUtf8String(T i) {
+	std::ostringstream s;
+	s << i;
+	return s.str();
+}
+
+bool ToBool(const std::string& s, bool def);
+
+std::string ToUtf8String(bool b);
 
 uint64_t HumanReadableSizeToBytes(const std::string& str);
 
@@ -72,4 +71,4 @@
 
 }; // namespace Strings
 
-#endif // __core__strings_h
\ No newline at end of file
+#endif // __core__strings_h
--- a/src/core/anime.cc	Tue Jan 02 02:37:03 2024 -0500
+++ b/src/core/anime.cc	Sun Jan 07 09:54:17 2024 -0500
@@ -5,6 +5,7 @@
 #include "core/anime.h"
 #include "core/date.h"
 #include "core/session.h"
+#include "core/strings.h"
 
 #include <algorithm>
 #include <string>
@@ -50,9 +51,9 @@
 
 	switch (session.config.anime_list.score_format) {
 		case ScoreFormat::POINT_10_DECIMAL:
-			return std::to_string(score / 10) + "." + std::to_string(score % 10);
+			return Strings::ToUtf8String(score / 10) + "." + Strings::ToUtf8String(score % 10);
 		case ScoreFormat::POINT_10:
-			return std::to_string(score / 10);
+			return Strings::ToUtf8String(score / 10);
 		case ScoreFormat::POINT_5: {
 			std::string stars = "";
 
@@ -73,7 +74,7 @@
 		}
 		default:
 		case ScoreFormat::POINT_100:
-			return std::to_string(score);
+			return Strings::ToUtf8String(score);
 	}
 }
 
@@ -243,7 +244,7 @@
 
 std::string Anime::GetServiceUrl() const {
 	/* todo: add support for other services... */
-	return "https://anilist.co/anime/" + std::to_string(GetId());
+	return "https://anilist.co/anime/" + Strings::ToUtf8String(GetId());
 }
 
 void Anime::SetId(int id) {
--- a/src/core/strings.cc	Tue Jan 02 02:37:03 2024 -0500
+++ b/src/core/strings.cc	Sun Jan 07 09:54:17 2024 -0500
@@ -159,33 +159,17 @@
 	return QString::fromWCharArray(wstring.c_str(), wstring.length());
 }
 
-/* not really an "int"... but who cares? */
-int ToInt(const std::string& str, int def) {
-	int tmp = 0;
-	try {
-		tmp = std::stoi(str);
-	} catch (std::invalid_argument const& ex) {
-		qDebug() << "Failed to parse int from std::string: no number found in " << ToQString(str) << " defaulting to " << def;
-		tmp = def;
-	}
-	return tmp;
+std::string ToUtf8String(const bool b) {
+	return b ? "true" : "false"; // lol
 }
 
-bool ToBool(const std::string& s, const bool def) {
-	if (s.length() < 4)
-		return def;
-	const std::string l = Strings::ToLower(s);
-	if (Strings::BeginningMatchesSubstring(l, "true"))
-		return true;
-	else if (Strings::BeginningMatchesSubstring(l, "false"))
-		return false;
+bool ToBool(const std::string& str, bool def) {
+	std::istringstream s(Strings::ToLower(str));
+	s >> std::boolalpha >> def;
 	return def;
 }
 
-std::string ToUtf8String(const bool b) {
-	return b ? "true" : "false";
-}
-
+/* util funcs */
 uint64_t HumanReadableSizeToBytes(const std::string& str) {
 	static const std::unordered_map<std::string, uint64_t> bytes_map = {
 		{"KB", 1ull << 10},
--- a/src/core/time.cc	Tue Jan 02 02:37:03 2024 -0500
+++ b/src/core/time.cc	Sun Jan 07 09:54:17 2024 -0500
@@ -1,4 +1,6 @@
 #include "core/time.h"
+#include "core/strings.h"
+
 #include <cassert>
 #include <cmath>
 #include <cstdint>
@@ -15,7 +17,7 @@
 	std::string result;
 
 	auto get = [](int64_t val, const std::string& s, const std::string& p) {
-		return std::to_string(val) + " " + (val == 1 ? s : p);
+		return Strings::ToUtf8String(val) + " " + (val == 1 ? s : p);
 	};
 
 	if (InSeconds() < 60)
@@ -61,4 +63,4 @@
 	return *reinterpret_cast<int64_t*>(&t);
 }
 
-} // namespace Time
\ No newline at end of file
+} // namespace Time
--- a/src/gui/pages/anime_list.cc	Tue Jan 02 02:37:03 2024 -0500
+++ b/src/gui/pages/anime_list.cc	Sun Jan 07 09:54:17 2024 -0500
@@ -119,7 +119,7 @@
 					std::optional<unsigned int> year = list[index.row()].GetAirDate().GetYear();
 					if (!year)
 						return "Unknown Unknown";
-					return Strings::ToQString(Translate::ToLocalString(list[index.row()].GetSeason()) + " " + std::to_string(year.value()));
+					return Strings::ToQString(Translate::ToLocalString(list[index.row()].GetSeason()) + " " + Strings::ToUtf8String(year.value()));
 				}
 				case AL_AVG_SCORE: return QString::number(list[index.row()].GetAudienceScore()) + "%";
 				case AL_STARTED: return list[index.row()].GetUserDateStarted().GetAsQDate();
@@ -349,8 +349,8 @@
 
 void AnimeListPage::RefreshTabs() {
 	for (unsigned int i = 0; i < sort_models.size(); i++)
-		tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i]) + " (" +
-								   std::to_string(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")"));
+		tab_bar->setTabText(i, Strings::ToQString(Translate::ToString(Anime::ListStatuses[i])) + " (" +
+								   QString::number(Anime::db.GetListsAnimeAmount(Anime::ListStatuses[i])) + ")");
 }
 
 void AnimeListPage::Refresh() {
--- a/src/services/anilist.cc	Tue Jan 02 02:37:03 2024 -0500
+++ b/src/services/anilist.cc	Sun Jan 07 09:54:17 2024 -0500
@@ -308,7 +308,7 @@
 bool AuthorizeUser() {
 	/* Prompt for PIN */
 	QDesktopServices::openUrl(
-		QUrl(Strings::ToQString("https://anilist.co/api/v2/oauth/authorize?client_id=" + std::to_string(CLIENT_ID) + "&response_type=token")));
+		QUrl(Strings::ToQString("https://anilist.co/api/v2/oauth/authorize?client_id=" + Strings::ToUtf8String(CLIENT_ID) + "&response_type=token")));
 
 	bool ok;
 	QString token = QInputDialog::getText(