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/file.hpp>
#include <Geode/utils/string.hpp>
#include <Geode/utils/general.hpp>
#include <about.hpp>
#include <matjson.hpp>
#include <utility>
@ -149,13 +150,9 @@ Result<ModMetadata> ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs
ver = "0.000";
}
if (ver != "*") {
double val = 0.0;
errno = 0;
if (std::setlocale(LC_NUMERIC, "C")) {
val = std::strtod(ver.c_str(), nullptr);
if (errno == ERANGE) {
return Err("[mod.json] has invalid target GD version");
}
auto res = numFromString<double>(ver);
if (res.isErr()) {
return Err("[mod.json] has invalid target GD version");
}
impl->m_gdVersion = ver;
}
@ -567,7 +564,11 @@ Result<> ModMetadata::checkGameVersion() const {
if (!m_impl->m_gdVersion.empty()) {
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
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());
}
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;

View file

@ -9,37 +9,13 @@
#include <Geode/binding/CCMenuItemToggler.hpp>
#include <Geode/loader/Loader.hpp>
#include <Geode/loader/Dirs.hpp>
#include <Geode/utils/general.hpp>
#include <charconv>
#include <clocale>
#include <filesystem>
// 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>
static float valueToSlider(T const& setting, typename T::ValueType value) {
auto min = setting.min ? setting.min.value() : -100;
@ -193,7 +169,9 @@ void IntSettingNode::onArrow(CCObject* sender) {
}
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);
}
@ -275,7 +253,9 @@ void FloatSettingNode::onArrow(CCObject* sender) {
}
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);
}

View file

@ -10,27 +10,6 @@
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) {
m_noElasticity = true;
m_color = color;
@ -307,8 +286,7 @@ bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) {
sliderWrapper->addChildAtPosition(m_opacitySlider, Anchor::Center, ccp(0, 0));
sliderColumn->addChild(sliderWrapper);
m_opacityInput = TextInput::create(60.f, "0.00");
m_opacityInput->setPosition(85.f, -95.f);
m_opacityInput = TextInput::create(60.f, "Opacity");
m_opacityInput->setScale(.7f);
m_opacityInput->setDelegate(this, TAG_OPACITY_INPUT);
m_opacityInput->setID("opacity-input");
@ -382,15 +360,27 @@ void ColorPickPopup::textChanged(CCTextInputNode* input) {
}
break;
case TAG_OPACITY_INPUT:
{
m_color.a = parseFloat(input->getString().c_str());
}
case TAG_OPACITY_INPUT: {
auto res = numFromString<float>(input->getString().c_str());
if (res) m_color.a = std::clamp(static_cast<int>(res.unwrap() * 255.f), 0, 255);
break;
}
case TAG_R_INPUT: m_color.r = parseInt(input->getString().c_str()); break;
case TAG_G_INPUT: m_color.g = parseInt(input->getString().c_str()); break;
case TAG_B_INPUT: m_color.b = parseInt(input->getString().c_str()); break;
case TAG_R_INPUT: {
auto res = numFromString<uint32_t>(input->getString().c_str());
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;
}

View file

@ -79,12 +79,11 @@ public:
Result<ccColor3B> colorForIdentifier(std::string const& tag) {
if (utils::string::contains(tag, ' ')) {
auto hexStr = utils::string::split(utils::string::normalize(tag), " ").at(1);
int hex = 0;
auto res = std::from_chars(hexStr.data(), hexStr.data() + hexStr.size(), hex, 16);
if (res.ec != std::errc()) {
auto res = numFromString<uint32_t>(hexStr, 16);
if (res.isErr()) {
return Err("Invalid hex");
}
return Ok(cc3x(hex));
return Ok(cc3x(res.unwrap()));
}
else {
auto colorText = tag.substr(1);
@ -190,40 +189,36 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto profile = std::string(href->getCString());
profile = profile.substr(profile.find(":") + 1);
int id = 0;
auto res = std::from_chars(profile.data(), profile.data() + profile.size(), id);
if (res.ec != std::errc()) {
auto res = numFromString<int>(profile);
if (res.isErr()) {
FLAlertLayer::create(
"Error",
"Invalid profile ID: <cr>" + profile +
"</c>. This is "
"probably the mod developer's fault, report the bug to them.",
"OK"
)
->show();
)->show();
return;
}
ProfilePage::create(id, false)->show();
ProfilePage::create(res.unwrap(), false)->show();
}
void MDTextArea::onGDLevel(CCObject* pSender) {
auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
auto level = std::string(href->getCString());
level = level.substr(level.find(":") + 1);
int id = 0;
auto res = std::from_chars(level.data(), level.data() + level.size(), id);
if (res.ec != std::errc()) {
auto res = numFromString<int>(level);
if (res.isErr()) {
FLAlertLayer::create(
"Error",
"Invalid level ID: <cr>" + level +
"</c>. This is "
"probably the mod developers's fault, report the bug to them.",
"OK"
)
->show();
)->show();
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);
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) {
return Err("Hex value too large");
}
size_t numValue;
auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16);
if (res.ec != std::errc()) {
auto res = numFromString<uint32_t>(hexValue, 16);
if (!res) {
return Err("Invalid hex value '{}'", hexValue);
}
auto numValue = res.unwrap();
switch (hexValue.size()) {
case 6: {
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) {
return Err("Hex value too large");
}
size_t numValue;
auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16);
if (res.ec != std::errc()) {
auto res = numFromString<uint32_t>(hexValue, 16);
if (!res) {
return Err("Invalid hex value '{}'", hexValue);
}
auto numValue = res.unwrap();
switch (hexValue.size()) {
case 8: {
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 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;
}