replace all c number parsing with numFromString

This commit is contained in:
altalk23 2024-07-25 15:17:35 +03:00
parent 2cd1a9ee26
commit 006ede8f34
7 changed files with 65 additions and 89 deletions

View file

@ -3,6 +3,7 @@
#include <Geode/utils/VersionInfo.hpp> #include <Geode/utils/VersionInfo.hpp>
#include <Geode/utils/file.hpp> #include <Geode/utils/file.hpp>
#include <Geode/utils/string.hpp> #include <Geode/utils/string.hpp>
#include <Geode/utils/general.hpp>
#include <about.hpp> #include <about.hpp>
#include <matjson.hpp> #include <matjson.hpp>
#include <utility> #include <utility>
@ -149,13 +150,9 @@ Result<ModMetadata> ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs
ver = "0.000"; ver = "0.000";
} }
if (ver != "*") { if (ver != "*") {
double val = 0.0; auto res = numFromString<double>(ver);
errno = 0; if (res.isErr()) {
if (std::setlocale(LC_NUMERIC, "C")) { return Err("[mod.json] has invalid target GD version");
val = std::strtod(ver.c_str(), nullptr);
if (errno == ERANGE) {
return Err("[mod.json] has invalid target GD version");
}
} }
impl->m_gdVersion = ver; impl->m_gdVersion = ver;
} }
@ -567,7 +564,11 @@ Result<> ModMetadata::checkGameVersion() const {
if (!m_impl->m_gdVersion.empty()) { if (!m_impl->m_gdVersion.empty()) {
auto const ver = m_impl->m_gdVersion; auto const ver = m_impl->m_gdVersion;
double modTargetVer = std::stod(ver); auto res = numFromString<double>(ver);
if (res.isErr()) {
return Err("Invalid target GD version");
}
double modTargetVer = res.unwrap();
if (modTargetVer == 0.0) { // O.o if (modTargetVer == 0.0) { // O.o
return Err(fmt::format("This mod doesn't support the current platform.")); return Err(fmt::format("This mod doesn't support the current platform."));

View file

@ -264,7 +264,11 @@ int writeAndGetPid() {
log::warn("Failed to read last-pid file: {}", res.error()); log::warn("Failed to read last-pid file: {}", res.error());
} }
else { else {
lastPid = std::stoi(res.unwrap()); auto res = numFromString<int>(res.unwrap());
if (!res) {
log::warn("Failed to parse last-pid file: {}", res.error());
}
else lastPid = res.unwrap();
} }
std::error_code ec; std::error_code ec;

View file

@ -9,37 +9,13 @@
#include <Geode/binding/CCMenuItemToggler.hpp> #include <Geode/binding/CCMenuItemToggler.hpp>
#include <Geode/loader/Loader.hpp> #include <Geode/loader/Loader.hpp>
#include <Geode/loader/Dirs.hpp> #include <Geode/loader/Dirs.hpp>
#include <Geode/utils/general.hpp>
#include <charconv> #include <charconv>
#include <clocale> #include <clocale>
#include <filesystem> #include <filesystem>
// Helpers // Helpers
template <class Num>
Num parseNumForInput(std::string const& str) {
if constexpr (std::is_same_v<Num, int64_t>) {
int64_t i = 0;
auto res = std::from_chars(str.data(), str.data() + str.size(), i);
if (res.ec == std::errc()) {
return i;
}
}
else if constexpr (std::is_same_v<Num, double>) {
double val = 0.0;
errno = 0;
if (std::setlocale(LC_NUMERIC, "C")) {
val = std::strtod(str.c_str(), nullptr);
if (errno == 0) {
return val;
}
}
}
else {
static_assert(!std::is_same_v<Num, Num>, "Impl Num for parseNumForInput");
}
return 0;
}
template<class T> template<class T>
static float valueToSlider(T const& setting, typename T::ValueType value) { static float valueToSlider(T const& setting, typename T::ValueType value) {
auto min = setting.min ? setting.min.value() : -100; auto min = setting.min ? setting.min.value() : -100;
@ -193,7 +169,9 @@ void IntSettingNode::onArrow(CCObject* sender) {
} }
void IntSettingNode::textChanged(CCTextInputNode* input) { void IntSettingNode::textChanged(CCTextInputNode* input) {
m_uncommittedValue = parseNumForInput<ValueType>(input->getString()); auto res = numFromString<ValueType>(input->getString());
if (!res) return;
m_uncommittedValue = res.unwrap();
this->valueChanged(false); this->valueChanged(false);
} }
@ -275,7 +253,9 @@ void FloatSettingNode::onArrow(CCObject* sender) {
} }
void FloatSettingNode::textChanged(CCTextInputNode* input) { void FloatSettingNode::textChanged(CCTextInputNode* input) {
m_uncommittedValue = parseNumForInput<ValueType>(input->getString()); auto res = numFromString<ValueType>(input->getString());
if (!res) return;
m_uncommittedValue = res.unwrap();
this->valueChanged(false); this->valueChanged(false);
} }

View file

@ -10,27 +10,6 @@
using namespace geode::prelude; using namespace geode::prelude;
static GLubyte parseInt(char const* str) {
int i = 0;
auto res = std::from_chars(str, str + strlen(str), i);
if (res.ec == std::errc()) {
return static_cast<GLubyte>(i);
}
return 255;
}
static GLubyte parseFloat(char const* str) {
float val = 0.0f;
errno = 0;
if (std::setlocale(LC_NUMERIC, "C")) {
val = std::strtof(str, nullptr);
if (errno == 0) {
return val;
}
}
return 255.f;
}
bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) { bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) {
m_noElasticity = true; m_noElasticity = true;
m_color = color; m_color = color;
@ -307,8 +286,7 @@ bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) {
sliderWrapper->addChildAtPosition(m_opacitySlider, Anchor::Center, ccp(0, 0)); sliderWrapper->addChildAtPosition(m_opacitySlider, Anchor::Center, ccp(0, 0));
sliderColumn->addChild(sliderWrapper); sliderColumn->addChild(sliderWrapper);
m_opacityInput = TextInput::create(60.f, "0.00"); m_opacityInput = TextInput::create(60.f, "Opacity");
m_opacityInput->setPosition(85.f, -95.f);
m_opacityInput->setScale(.7f); m_opacityInput->setScale(.7f);
m_opacityInput->setDelegate(this, TAG_OPACITY_INPUT); m_opacityInput->setDelegate(this, TAG_OPACITY_INPUT);
m_opacityInput->setID("opacity-input"); m_opacityInput->setID("opacity-input");
@ -382,15 +360,27 @@ void ColorPickPopup::textChanged(CCTextInputNode* input) {
} }
break; break;
case TAG_OPACITY_INPUT: case TAG_OPACITY_INPUT: {
{ auto res = numFromString<float>(input->getString().c_str());
m_color.a = parseFloat(input->getString().c_str()); if (res) m_color.a = std::clamp(static_cast<int>(res.unwrap() * 255.f), 0, 255);
}
break; break;
}
case TAG_R_INPUT: m_color.r = parseInt(input->getString().c_str()); break; case TAG_R_INPUT: {
case TAG_G_INPUT: m_color.g = parseInt(input->getString().c_str()); break; auto res = numFromString<uint32_t>(input->getString().c_str());
case TAG_B_INPUT: m_color.b = parseInt(input->getString().c_str()); break; if (res) m_color.r = std::clamp(res.unwrap(), 0u, 255u);
break;
}
case TAG_G_INPUT: {
auto res = numFromString<uint32_t>(input->getString().c_str());
if (res) m_color.g = std::clamp(res.unwrap(), 0u, 255u);
break;
}
case TAG_B_INPUT: {
auto res = numFromString<uint32_t>(input->getString().c_str());
if (res) m_color.b = std::clamp(res.unwrap(), 0u, 255u);
break;
}
default: break; default: break;
} }

View file

@ -79,12 +79,11 @@ public:
Result<ccColor3B> colorForIdentifier(std::string const& tag) { Result<ccColor3B> colorForIdentifier(std::string const& tag) {
if (utils::string::contains(tag, ' ')) { if (utils::string::contains(tag, ' ')) {
auto hexStr = utils::string::split(utils::string::normalize(tag), " ").at(1); auto hexStr = utils::string::split(utils::string::normalize(tag), " ").at(1);
int hex = 0; auto res = numFromString<uint32_t>(hexStr, 16);
auto res = std::from_chars(hexStr.data(), hexStr.data() + hexStr.size(), hex, 16); if (res.isErr()) {
if (res.ec != std::errc()) {
return Err("Invalid hex"); return Err("Invalid hex");
} }
return Ok(cc3x(hex)); return Ok(cc3x(res.unwrap()));
} }
else { else {
auto colorText = tag.substr(1); auto colorText = tag.substr(1);
@ -190,40 +189,36 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject()); auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto profile = std::string(href->getCString()); auto profile = std::string(href->getCString());
profile = profile.substr(profile.find(":") + 1); profile = profile.substr(profile.find(":") + 1);
int id = 0; auto res = numFromString<int>(profile);
auto res = std::from_chars(profile.data(), profile.data() + profile.size(), id); if (res.isErr()) {
if (res.ec != std::errc()) {
FLAlertLayer::create( FLAlertLayer::create(
"Error", "Error",
"Invalid profile ID: <cr>" + profile + "Invalid profile ID: <cr>" + profile +
"</c>. This is " "</c>. This is "
"probably the mod developer's fault, report the bug to them.", "probably the mod developer's fault, report the bug to them.",
"OK" "OK"
) )->show();
->show();
return; return;
} }
ProfilePage::create(id, false)->show(); ProfilePage::create(res.unwrap(), false)->show();
} }
void MDTextArea::onGDLevel(CCObject* pSender) { void MDTextArea::onGDLevel(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject()); auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto level = std::string(href->getCString()); auto level = std::string(href->getCString());
level = level.substr(level.find(":") + 1); level = level.substr(level.find(":") + 1);
int id = 0; auto res = numFromString<int>(level);
auto res = std::from_chars(level.data(), level.data() + level.size(), id); if (res.isErr()) {
if (res.ec != std::errc()) {
FLAlertLayer::create( FLAlertLayer::create(
"Error", "Error",
"Invalid level ID: <cr>" + level + "Invalid level ID: <cr>" + level +
"</c>. This is " "</c>. This is "
"probably the mod developers's fault, report the bug to them.", "probably the mod developers's fault, report the bug to them.",
"OK" "OK"
) )->show();
->show();
return; return;
} }
auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", id)); auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", res.unwrap()));
auto scene = LevelBrowserLayer::scene(searchObject); auto scene = LevelBrowserLayer::scene(searchObject);
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene)); CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene));
} }

View file

@ -131,11 +131,11 @@ Result<ccColor3B> geode::cocos::cc3bFromHexString(std::string const& rawHexValue
if (hexValue.size() > 6) { if (hexValue.size() > 6) {
return Err("Hex value too large"); return Err("Hex value too large");
} }
size_t numValue; auto res = numFromString<uint32_t>(hexValue, 16);
auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16); if (!res) {
if (res.ec != std::errc()) {
return Err("Invalid hex value '{}'", hexValue); return Err("Invalid hex value '{}'", hexValue);
} }
auto numValue = res.unwrap();
switch (hexValue.size()) { switch (hexValue.size()) {
case 6: { case 6: {
auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16); auto r = static_cast<uint8_t>((numValue & 0xFF0000) >> 16);
@ -189,11 +189,11 @@ Result<ccColor4B> geode::cocos::cc4bFromHexString(std::string const& rawHexValue
if (hexValue.size() > 8) { if (hexValue.size() > 8) {
return Err("Hex value too large"); return Err("Hex value too large");
} }
size_t numValue; auto res = numFromString<uint32_t>(hexValue, 16);
auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16); if (!res) {
if (res.ec != std::errc()) {
return Err("Invalid hex value '{}'", hexValue); return Err("Invalid hex value '{}'", hexValue);
} }
auto numValue = res.unwrap();
switch (hexValue.size()) { switch (hexValue.size()) {
case 8: { case 8: {
auto r = static_cast<uint8_t>((numValue & 0xFF000000) >> 24); auto r = static_cast<uint8_t>((numValue & 0xFF000000) >> 24);

View file

@ -488,7 +488,13 @@ WebRequest& WebRequest::header(std::string_view name, std::string_view value) {
const size_t comma = value.find(',', numStart); const size_t comma = value.find(',', numStart);
const size_t numLength = (comma == std::string::npos ? value.size() : comma) - numStart; const size_t numLength = (comma == std::string::npos ? value.size() : comma) - numStart;
timeout(std::chrono::seconds(std::stol(std::string(value.substr(numStart, numLength))))); int timeoutValue = 5;
auto res = numFromString<int>(value.substr(numStart, numLength));
if (res) {
timeoutValue = res.value();
}
timeout(std::chrono::seconds(timeoutValue));
return *this; return *this;
} }