Move from std::atoi to std::from_char

depth-refraction
Shi Han 1 year ago committed by psi29a
parent ca13aa6332
commit a90e3b8c3b

@ -66,6 +66,7 @@
Feature #7148: Optimize string literal lookup in mwscript
Feature #7194: Ori to show texture paths
Feature #7214: Searching in the in-game console
Task #7113: Move from std::atoi to std::from_char
Task #7117: Replace boost::scoped_array with std::vector
Task #7151: Do not use std::strerror to get errno error message

@ -6,6 +6,7 @@
#include <components/esm3/cellstate.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/format.hpp>
namespace
@ -68,9 +69,7 @@ namespace
std::string type_str = "INVALID";
std::string func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1, 3));
int func;
std::istringstream iss(rule.substr(2, 2));
iss >> func;
int func = Misc::StringUtils::toNumeric<int>(rule.substr(2, 2), 0);
switch (type)
{

@ -1,9 +1,10 @@
#include "land.hpp"
#include <sstream>
#include <stddef.h>
#include <stdexcept>
#include <components/misc/strings/conversion.hpp>
namespace ESM
{
class ESMReader;
@ -30,7 +31,7 @@ namespace CSMWorld
if (mid == std::string::npos || id[0] != '#')
throw std::runtime_error("Invalid Land ID");
x = std::stoi(id.substr(1, mid - 1));
y = std::stoi(id.substr(mid + 1));
x = Misc::StringUtils::toNumeric<int>(id.substr(1, mid - 1), 0);
y = Misc::StringUtils::toNumeric<int>(id.substr(mid + 1), 0);
}
}

@ -1,10 +1,10 @@
#include "landtexture.hpp"
#include <sstream>
#include <stddef.h>
#include <stdexcept>
#include <components/esm3/esmreader.hpp>
#include <components/misc/strings/conversion.hpp>
namespace CSMWorld
{
@ -29,7 +29,7 @@ namespace CSMWorld
if (middle == std::string::npos || id[0] != 'L')
throw std::runtime_error("Invalid LandTexture ID");
plugin = std::stoi(id.substr(1, middle - 1));
index = std::stoi(id.substr(middle + 1));
plugin = Misc::StringUtils::toNumeric<int>(id.substr(1, middle - 1), 0);
index = Misc::StringUtils::toNumeric<int>(id.substr(middle + 1), 0);
}
}

@ -9,6 +9,7 @@
#include <components/esm3/cellref.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/misc/strings/conversion.hpp>
#include "cell.hpp"
#include "record.hpp"
@ -231,7 +232,7 @@ unsigned int CSMWorld::RefCollection::extractIdNum(std::string_view id) const
if (separator == std::string::npos)
throw std::runtime_error("invalid ref ID: " + std::string(id));
return static_cast<unsigned int>(std::stoi(std::string(id.substr(separator + 1))));
return Misc::StringUtils::toNumeric<unsigned int>(id.substr(separator + 1), 0);
}
int CSMWorld::RefCollection::getIntIndex(unsigned int id) const

@ -27,6 +27,8 @@
#include <apps/opencs/view/render/terrainselection.hpp>
#include <apps/opencs/view/widget/scenetool.hpp>
#include <components/misc/strings/conversion.hpp>
#include "../widget/scenetoolbar.hpp"
#include "../widget/scenetooltexturebrush.hpp"
@ -360,7 +362,9 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
std::size_t hashlocation = mBrushTexture.find('#');
std::string mBrushTextureInt = mBrushTexture.substr(hashlocation + 1);
int brushInt = stoi(mBrushTexture.substr(hashlocation + 1)) + 1; // All indices are offset by +1
// All indices are offset by +1
int brushInt = Misc::StringUtils::toNumeric<int>(mBrushTexture.substr(hashlocation + 1), 0) + 1;
int r = static_cast<float>(mBrushSize) / 2;

@ -4,6 +4,7 @@
#include <sstream>
#include <stdexcept>
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/lower.hpp>
namespace
@ -48,9 +49,7 @@ namespace
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const
{
int index = 0;
std::istringstream(mSelect.mSelectRule.substr(2, 2)) >> index;
const int index = Misc::StringUtils::toNumeric<int>(mSelect.mSelectRule.substr(2, 2), 0);
switch (index)
{

@ -1,5 +1,8 @@
#include "formatting.hpp"
#include <charconv>
#include <system_error>
#include <MyGUI_EditBox.h>
#include <MyGUI_EditText.h>
#include <MyGUI_Gui.h>
@ -363,10 +366,9 @@ namespace MWGui::Formatting
{
if (attr.find("color") != attr.end())
{
unsigned int color;
std::stringstream ss;
ss << attr.at("color");
ss >> std::hex >> color;
auto& colorString = attr.at("color");
unsigned int color = 0;
std::from_chars(colorString.data(), colorString.data() + colorString.size(), color, 16);
mTextStyle.mColour
= MyGUI::Colour((color >> 16 & 0xFF) / 255.f, (color >> 8 & 0xFF) / 255.f, (color & 0xFF) / 255.f);

@ -6,6 +6,7 @@
#include <components/esm3/loadcrea.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/misc/strings/conversion.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
@ -148,9 +149,7 @@ namespace MWGui
void TravelWindow::onTravelButtonClick(MyGUI::Widget* _sender)
{
std::istringstream iss(_sender->getUserString("price"));
int price;
iss >> price;
const int price = Misc::StringUtils::toNumeric<int>(_sender->getUserString("price"), 0);
MWWorld::Ptr player = MWMechanics::getPlayer();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);

@ -19,13 +19,12 @@
#include "character.hpp"
#include <sstream>
#include <components/esm/records.hpp>
#include <components/misc/mathutil.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/rng.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/settings/settings.hpp>
@ -1006,23 +1005,23 @@ namespace MWMechanics
std::string_view soundgen = evt.substr(10);
// The event can optionally contain volume and pitch modifiers
float volume = 1.f, pitch = 1.f;
float volume = 1.0f;
float pitch = 1.0f;
if (soundgen.find(' ') != std::string::npos)
{
std::vector<std::string_view> tokens;
Misc::StringUtils::split(soundgen, tokens);
soundgen = tokens[0];
if (tokens.size() >= 2)
{
std::stringstream stream;
stream << tokens[1];
stream >> volume;
volume = Misc::StringUtils::toNumeric<float>(tokens[1], volume);
}
if (tokens.size() >= 3)
{
std::stringstream stream;
stream << tokens[2];
stream >> pitch;
pitch = Misc::StringUtils::toNumeric<float>(tokens[2], pitch);
}
}

@ -24,6 +24,7 @@
#include <components/esm3/loadmgef.hpp>
#include <components/misc/convert.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/resource/bulletshapemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/settings/settings.hpp>
@ -121,14 +122,13 @@ namespace MWPhysics
mCollisionWorld->setForceUpdateAllAabbs(false);
// Check if a user decided to override a physics system FPS
const char* env = getenv("OPENMW_PHYSICS_FPS");
if (env)
if (const char* env = getenv("OPENMW_PHYSICS_FPS"))
{
float physFramerate = std::atof(env);
if (physFramerate > 0)
if (const auto physFramerate = Misc::StringUtils::toNumeric<float>(env);
physFramerate.has_value() && *physFramerate > 0)
{
mPhysicsDt = 1.f / physFramerate;
Log(Debug::Warning) << "Warning: using custom physics framerate (" << physFramerate << " FPS).";
mPhysicsDt = 1.f / *physFramerate;
Log(Debug::Warning) << "Warning: using custom physics framerate (" << *physFramerate << " FPS).";
}
}

@ -9,6 +9,7 @@
#include <osg/TextureCubeMap>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/depth.hpp>
@ -195,13 +196,19 @@ namespace MWRender
int cubeSize = screenshotMapping == Planet ? screenshotW : screenshotW / 2;
if (settingArgs.size() > 1)
screenshotW = std::min(10000, std::atoi(settingArgs[1].c_str()));
{
screenshotW = std::min(10000, Misc::StringUtils::toNumeric<int>(settingArgs[1], 0));
}
if (settingArgs.size() > 2)
screenshotH = std::min(10000, std::atoi(settingArgs[2].c_str()));
{
screenshotH = std::min(10000, Misc::StringUtils::toNumeric<int>(settingArgs[2], 0));
}
if (settingArgs.size() > 3)
cubeSize = std::min(5000, std::atoi(settingArgs[3].c_str()));
{
cubeSize = std::min(5000, Misc::StringUtils::toNumeric<int>(settingArgs[3], 0));
}
bool rawCubemap = screenshotMapping == RawCubemap;

@ -45,6 +45,7 @@
#include <components/esm3/loadweap.hpp>
#include <components/files/conversion.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/vfs/manager.hpp>
#include "../mwbase/environment.hpp"
@ -575,9 +576,12 @@ namespace MWScript
return;
}
char* end;
long key = strtol(effect.data(), &end, 10);
if (key < 0 || key > 32767 || *end != '\0')
long key;
if (const auto k = ::Misc::StringUtils::toNumeric<long>(effect.data());
k.has_value() && *k >= 0 && *k <= 32767)
key = *k;
else
key = ESM::MagicEffect::effectStringToId({ effect });
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);

@ -8,6 +8,7 @@
#include "extensions.hpp"
#include "parser.hpp"
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/lower.hpp>
namespace
@ -207,12 +208,8 @@ namespace Compiler
TokenLoc loc(mLoc);
mLoc.mLiteral.clear();
std::istringstream stream(value);
cont = parser.parseInt(Misc::StringUtils::toNumeric<int>(value, 0), loc, *this);
int intValue = 0;
stream >> intValue;
cont = parser.parseInt(intValue, loc, *this);
return true;
}
@ -247,12 +244,8 @@ namespace Compiler
TokenLoc loc(mLoc);
mLoc.mLiteral.clear();
std::istringstream stream(value);
float floatValue = 0;
stream >> floatValue;
cont = parser.parseFloat(Misc::StringUtils::toNumeric<float>(value, 0.0f), loc, *this);
cont = parser.parseFloat(floatValue, loc, *this);
return true;
}

@ -10,6 +10,7 @@
#include <components/crashcatcher/crashcatcher.hpp>
#include <components/files/conversion.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/lower.hpp>
#ifdef _WIN32
@ -314,7 +315,8 @@ int wrapApplication(int (*innerApplication)(int argc, char* argv[]), int argc, c
int ret = 0;
try
{
if (const auto env = std::getenv("OPENMW_DISABLE_CRASH_CATCHER"); env == nullptr || std::atol(env) == 0)
if (const auto env = std::getenv("OPENMW_DISABLE_CRASH_CATCHER");
env == nullptr || Misc::StringUtils::toNumeric<int>(env, 0) == 0)
{
#if defined(_WIN32)
const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp";

@ -22,13 +22,10 @@
*/
#include "formid.hpp"
#include <algorithm>
#include <climits> // LONG_MIN, LONG_MAX for gcc
#include <cstdlib> // strtol
#include <sstream>
#include <charconv>
#include <stdexcept>
#include <string>
#include <system_error>
namespace ESM4
{
@ -54,16 +51,13 @@ namespace ESM4
if (str.size() != 8)
return false;
char* tmp;
errno = 0;
unsigned long val = strtol(str.c_str(), &tmp, 16);
unsigned long value = 0;
if (tmp == str.c_str() || *tmp != '\0'
|| ((val == (unsigned long)LONG_MIN || val == (unsigned long)LONG_MAX) && errno == ERANGE))
if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc())
return false;
if (id != nullptr)
*id = static_cast<FormId>(val);
*id = static_cast<FormId>(value);
return true;
}
@ -73,6 +67,11 @@ namespace ESM4
if (str.size() != 8)
throw std::out_of_range("StringToFormId: incorrect string size");
return static_cast<FormId>(std::stoul(str, nullptr, 16));
unsigned long value = 0;
if (auto [_ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, 16); ec != std::errc())
throw std::invalid_argument("StringToFormId: string not a valid hexadecimal number");
return static_cast<FormId>(value);
}
}

@ -1,8 +1,11 @@
#include "fallback.hpp"
#include <sstream>
#include <string>
#include <vector>
#include <components/debug/debuglog.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
namespace Fallback
{
@ -27,31 +30,13 @@ namespace Fallback
float Map::getFloat(std::string_view fall)
{
std::string_view fallback = getString(fall);
if (!fallback.empty())
{
std::stringstream stream;
stream << fallback;
float number = 0.f;
stream >> number;
return number;
}
return 0;
return Misc::StringUtils::toNumeric<float>(fallback, 0.0f);
}
int Map::getInt(std::string_view fall)
{
std::string_view fallback = getString(fall);
if (!fallback.empty())
{
std::stringstream stream;
stream << fallback;
int number = 0;
stream >> number;
return number;
}
return 0;
return Misc::StringUtils::toNumeric<int>(fallback, 0);
}
bool Map::getBool(std::string_view fall)
@ -62,30 +47,29 @@ namespace Fallback
osg::Vec4f Map::getColour(std::string_view fall)
{
std::string_view sum = getString(fall);
const std::string_view sum = getString(fall);
if (!sum.empty())
{
try
std::vector<std::string> ret;
Misc::StringUtils::split(sum, ret, ",");
if (ret.size() == 3)
{
std::string ret[3];
unsigned int j = 0;
for (unsigned int i = 0; i < sum.length(); ++i)
const auto r = Misc::StringUtils::toNumeric<float>(ret[0]);
const auto g = Misc::StringUtils::toNumeric<float>(ret[1]);
const auto b = Misc::StringUtils::toNumeric<float>(ret[2]);
if (r.has_value() && g.has_value() && b.has_value())
{
if (sum[i] == ',')
j++;
else if (sum[i] != ' ')
ret[j] += sum[i];
return osg::Vec4f(*r / 255.0f, *g / 255.0f, *b / 255.0f, 1.0f);
}
return osg::Vec4f(std::stoi(ret[0]) / 255.f, std::stoi(ret[1]) / 255.f, std::stoi(ret[2]) / 255.f, 1.f);
}
catch (const std::invalid_argument&)
{
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << sum
<< ") is not a valid color, using middle gray as a fallback";
}
Log(Debug::Error) << "Error: '" << fall << "' setting value (" << sum
<< ") is not a valid color, using middle gray as a fallback";
}
return osg::Vec4f(0.5f, 0.5f, 0.5f, 1.f);
}
}

@ -4,6 +4,7 @@
#include <array>
#include <charconv>
#include <sstream>
#include <system_error>
namespace Misc
{

@ -1,7 +1,19 @@
#ifndef COMPONENTS_MISC_STRINGS_CONVERSION_H
#define COMPONENTS_MISC_STRINGS_CONVERSION_H
#include <charconv>
#include <optional>
#include <string>
#include <system_error>
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
#include <ios>
#include <locale>
#include <sstream>
#endif
namespace Misc::StringUtils
{
@ -45,6 +57,78 @@ namespace Misc::StringUtils
{
return { str.begin(), str.end() }; // Undefined behavior if the contents of "char" aren't UTF8 or ASCII.
}
template <typename T>
inline std::optional<T> toNumeric(std::string_view s)
{
T result{};
auto [ptr, ec]{ std::from_chars(s.data(), s.data() + s.size(), result) };
if (ec == std::errc())
{
return result;
}
return std::nullopt;
}
template <typename T>
inline T toNumeric(std::string_view s, T defaultValue)
{
if (auto numeric = toNumeric<T>(s))
{
return *numeric;
}
return defaultValue;
}
// support for std::from_chars as of 2023-02-27
// - Visual Studio 2019 version 16.4 (1924)
// - GCC 11
// - Clang does not support floating points yet
// - Apples Clang does not support floating points yet
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
template <>
inline std::optional<float> toNumeric<float>(std::string_view s)
{
if (!s.empty())
{
std::istringstream iss(s.data());
iss.imbue(std::locale::classic());
float value;
if (iss >> value)
{
return value;
}
}
return std::nullopt;
}
template <>
inline std::optional<double> toNumeric<double>(std::string_view s)
{
if (!s.empty())
{
std::istringstream iss(s.data());
iss.imbue(std::locale::classic());
double value;
if (iss >> value)
{
return value;
}
}
return std::nullopt;
}
#endif
}
#endif // COMPONENTS_MISC_STRINGS_CONVERSION_H
#endif // COMPONENTS_MISC_STRINGS_CONVERSION_H

@ -10,6 +10,7 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/pathhelpers.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/nifosg/nifloader.hpp>
#include <components/sceneutil/keyframe.hpp>
#include <components/sceneutil/osgacontroller.hpp>
@ -184,7 +185,7 @@ namespace Resource
size_t spacePos = line.find_last_of(' ');
double time = 0.0;
if (spacePos != std::string::npos && spacePos + 1 < line.size())
time = std::stod(line.substr(spacePos + 1));
time = Misc::StringUtils::toNumeric<double>(line.substr(spacePos + 1), time);
return time;
}

@ -29,6 +29,7 @@
#include <components/misc/osguservalues.hpp>
#include <components/misc/pathhelpers.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/vfs/manager.hpp>
@ -308,8 +309,8 @@ namespace Resource
if (descriptionParts.at(0) == "alphatest")
{
osg::AlphaFunc::ComparisonFunction mode = getTestMode(descriptionParts.at(1));
osg::ref_ptr<osg::AlphaFunc> alphaFunc(
new osg::AlphaFunc(mode, std::stod(descriptionParts.at(2))));
osg::ref_ptr<osg::AlphaFunc> alphaFunc(new osg::AlphaFunc(
mode, Misc::StringUtils::toNumeric<float>(descriptionParts.at(2), 0.0f)));
node.getStateSet()->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
}
}

@ -1,43 +1,84 @@
#include "settings.hpp"
#include "parser.hpp"
#include <cerrno>
#include <charconv>
#include <filesystem>
#include <sstream>
#include <system_error>
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
#include <cerrno>
#include <ios>
#include <locale>
#endif
#include <components/files/configurationmanager.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
namespace Settings
{
namespace
{
template <class T>
auto parseIntegralNumber(const std::string& value, std::string_view setting, std::string_view category)
T parseNumberFromSetting(const std::string& value, std::string_view setting, std::string_view category)
{
T number{};
const auto result = std::from_chars(value.data(), value.data() + value.size(), number);
if (result.ec != std::errc())
{
throw std::system_error(std::make_error_code(result.ec),
"Failed to parse number from setting [" + std::string(category) + "] " + std::string(setting)
+ " value \"" + value + "\"");
}
return number;
}
template <class T>
auto parseFloatingPointNumber(const std::string& value, std::string_view setting, std::string_view category)
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
template <>
float parseNumberFromSetting<float>(
const std::string& value, std::string_view setting, std::string_view category)
{
std::stringstream stream(value);
T number{};
stream >> number;
if (stream.bad())
std::istringstream iss(value);
iss.imbue(std::locale::classic());
float floatValue = 0.0f;
if (!(iss >> floatValue))
{
throw std::system_error(errno, std::generic_category(),
"Failed to parse number from setting [" + std::string(category) + "] " + std::string(setting)
+ " value \"" + value + "\"");
return number;
}
return floatValue;
}
template <>
double parseNumberFromSetting<double>(
const std::string& value, std::string_view setting, std::string_view category)
{
std::istringstream iss(value);
iss.imbue(std::locale::classic());
double doubleValue = 0.0;
if (!(iss >> doubleValue))
{
throw std::system_error(errno, std::generic_category(),
"Failed to parse number from setting [" + std::string(category) + "] " + std::string(setting)
+ " value \"" + value + "\"");
}
return doubleValue;
}
#endif
}
CategorySettingValueMap Manager::mDefaultSettings = CategorySettingValueMap();
@ -139,27 +180,27 @@ namespace Settings
float Manager::getFloat(std::string_view setting, std::string_view category)
{
return parseFloatingPointNumber<float>(getString(setting, category), setting, category);
return parseNumberFromSetting<float>(getString(setting, category), setting, category);
}
double Manager::getDouble(std::string_view setting, std::string_view category)
{
return parseFloatingPointNumber<double>(getString(setting, category), setting, category);
return parseNumberFromSetting<double>(getString(setting, category), setting, category);
}
int Manager::getInt(std::string_view setting, std::string_view category)
{
return parseIntegralNumber<int>(getString(setting, category), setting, category);
return parseNumberFromSetting<int>(getString(setting, category), setting, category);
}
std::uint64_t Manager::getUInt64(std::string_view setting, std::string_view category)
{
return parseIntegralNumber<std::uint64_t>(getString(setting, category), setting, category);
return parseNumberFromSetting<uint64_t>(getString(setting, category), setting, category);
}
std::size_t Manager::getSize(std::string_view setting, std::string_view category)
{
return parseIntegralNumber<std::size_t>(getString(setting, category), setting, category);
return parseNumberFromSetting<size_t>(getString(setting, category), setting, category);
}
bool Manager::getBool(std::string_view setting, std::string_view category)
@ -171,23 +212,44 @@ namespace Settings
osg::Vec2f Manager::getVector2(std::string_view setting, std::string_view category)
{
const std::string& value = getString(setting, category);
std::stringstream stream(value);
float x, y;
stream >> x >> y;
if (stream.fail())
throw std::runtime_error(std::string("Can't parse 2d vector: " + value));
return { x, y };
std::vector<std::string> components;
Misc::StringUtils::split(value, components);
if (components.size() == 2)
{
auto x = Misc::StringUtils::toNumeric<float>(components[0]);
auto y = Misc::StringUtils::toNumeric<float>(components[1]);
if (x && y)
{
return { x.value(), y.value() };
}
}
throw std::runtime_error(std::string("Can't parse 2d vector: " + value));
}
osg::Vec3f Manager::getVector3(std::string_view setting, std::string_view category)
{
const std::string& value = getString(setting, category);
std::stringstream stream(value);
float x, y, z;
stream >> x >> y >> z;
if (stream.fail())
throw std::runtime_error(std::string("Can't parse 3d vector: " + value));
return { x, y, z };
std::vector<std::string> components;
Misc::StringUtils::split(value, components);
if (components.size() == 3)
{
auto x = Misc::StringUtils::toNumeric<float>(components[0]);
auto y = Misc::StringUtils::toNumeric<float>(components[1]);
auto z = Misc::StringUtils::toNumeric<float>(components[2]);
if (x && y && z)
{
return { x.value(), y.value(), z.value() };
}
}
throw std::runtime_error(std::string("Can't parse 3d vector: " + value));
}
void Manager::setString(std::string_view setting, std::string_view category, const std::string& value)

@ -5,6 +5,7 @@
#include <components/debug/debuglog.hpp>
#include <components/files/conversion.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/format.hpp>
#include <components/settings/settings.hpp>
#include <filesystem>
@ -90,7 +91,7 @@ namespace Shader
size_t lineNumberStart = lineDirectivePosition + std::string("#line ").length();
size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
std::string lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
lineNumber = std::stoi(lineNumberString) - 1;
lineNumber = Misc::StringUtils::toNumeric<int>(lineNumberString, 2) - 1;
}
else
{
@ -159,7 +160,7 @@ namespace Shader
size_t lineNumberStart = lineDirectivePosition + std::string("#line ").length();
size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
std::string lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
lineNumber = std::stoi(lineNumberString) - 1;
lineNumber = Misc::StringUtils::toNumeric<int>(lineNumberString, 2) - 1;
}
else
{
@ -239,7 +240,7 @@ namespace Shader
size_t lineNumberStart = lineDirectivePosition + std::string("#line ").length();
size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
std::string lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
lineNumber = std::stoi(lineNumberString);
lineNumber = Misc::StringUtils::toNumeric<int>(lineNumberString, 2);
}
else
{

@ -2,6 +2,8 @@
#include "numericeditbox.hpp"
#include <components/misc/strings/conversion.hpp>
namespace Gui
{
@ -22,27 +24,25 @@ namespace Gui
void NumericEditBox::onEditTextChange(MyGUI::EditBox* sender)
{
std::string newCaption = sender->getCaption();
const std::string newCaption = sender->getCaption();
if (newCaption.empty())
{
return;
}
try
if (const auto conversion = Misc::StringUtils::toNumeric<int>(newCaption))
{
mValue = std::stoi(newCaption);
int capped = std::clamp(mValue, mMinValue, mMaxValue);
mValue = conversion.value();
const int capped = std::clamp(mValue, mMinValue, mMaxValue);
if (capped != mValue)
{
mValue = capped;
setCaption(MyGUI::utility::toString(mValue));
}
}
catch (const std::invalid_argument&)
{
setCaption(MyGUI::utility::toString(mValue));
}
catch (const std::out_of_range&)
else
{
setCaption(MyGUI::utility::toString(mValue));
}

Loading…
Cancel
Save