Merge branch 'formatcomponents' into 'master'

Remove StringUtils::format from components

See merge request OpenMW/openmw!4880
This commit is contained in:
psi29a 2025-08-31 17:59:35 +00:00
commit 0ab79c4370
15 changed files with 174 additions and 200 deletions

View File

@ -201,7 +201,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
return result; return result;
} }
auto str = Misc::getResolutionText(mode.w, mode.h, "%i × %i (%i:%i)"); auto str = Misc::getResolutionText(mode.w, mode.h);
result.append(QString(str.c_str())); result.append(QString(str.c_str()));
} }

View File

@ -46,7 +46,7 @@
namespace namespace
{ {
std::string textureFilteringToStr(const std::string& mipFilter, const std::string& magFilter) std::string_view textureFilteringToStr(const std::string& mipFilter, const std::string& magFilter)
{ {
if (mipFilter == "none") if (mipFilter == "none")
return "#{OMWEngine:TextureFilteringDisabled}"; return "#{OMWEngine:TextureFilteringDisabled}";
@ -65,9 +65,9 @@ namespace
return "#{OMWEngine:TextureFilteringOther}"; return "#{OMWEngine:TextureFilteringOther}";
} }
std::string lightingMethodToStr(SceneUtil::LightingMethod method) MyGUI::UString lightingMethodToStr(SceneUtil::LightingMethod method)
{ {
std::string result; std::string_view result;
switch (method) switch (method)
{ {
case SceneUtil::LightingMethod::FFP: case SceneUtil::LightingMethod::FFP:
@ -82,18 +82,7 @@ namespace
break; break;
} }
return MyGUI::LanguageManager::getInstance().replaceTags(result); return MyGUI::LanguageManager::getInstance().replaceTags(MyGUI::UString(result));
}
void parseResolution(int& x, int& y, const std::string& str)
{
std::vector<std::string> split;
Misc::StringUtils::split(str, split, "@(x");
assert(split.size() >= 2);
Misc::StringUtils::trim(split[0]);
Misc::StringUtils::trim(split[1]);
x = MyGUI::utility::parseInt(split[0]);
y = MyGUI::utility::parseInt(split[1]);
} }
bool sortResolutions(std::pair<int, int> left, std::pair<int, int> right) bool sortResolutions(std::pair<int, int> left, std::pair<int, int> right)
@ -368,10 +357,10 @@ namespace MWGui
std::sort(resolutions.begin(), resolutions.end(), sortResolutions); std::sort(resolutions.begin(), resolutions.end(), sortResolutions);
for (std::pair<int, int>& resolution : resolutions) for (std::pair<int, int>& resolution : resolutions)
{ {
std::string str = Misc::getResolutionText(resolution.first, resolution.second, "%i x %i (%i:%i)"); std::string str = Misc::getResolutionText(resolution.first, resolution.second);
if (mResolutionList->findItemIndexWith(str) == MyGUI::ITEM_NONE) if (mResolutionList->findItemIndexWith(str) == MyGUI::ITEM_NONE)
mResolutionList->addItem(str); mResolutionList->addItem(str, resolution);
} }
highlightCurrentResolution(); highlightCurrentResolution();
@ -493,14 +482,14 @@ namespace MWGui
void SettingsWindow::onResolutionAccept() void SettingsWindow::onResolutionAccept()
{ {
const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); auto resolution = mResolutionList->getItemDataAt<std::pair<int, int>>(mResolutionList->getIndexSelected());
int resX, resY; if (resolution)
parseResolution(resX, resY, resStr); {
Settings::video().mResolutionX.set(resolution->first);
Settings::video().mResolutionY.set(resolution->second);
Settings::video().mResolutionX.set(resX); apply();
Settings::video().mResolutionY.set(resY); }
apply();
} }
void SettingsWindow::onResolutionCancel() void SettingsWindow::onResolutionCancel()
@ -517,10 +506,8 @@ namespace MWGui
for (size_t i = 0; i < mResolutionList->getItemCount(); ++i) for (size_t i = 0; i < mResolutionList->getItemCount(); ++i)
{ {
int resX, resY; auto resolution = mResolutionList->getItemDataAt<std::pair<int, int>>(i);
parseResolution(resX, resY, mResolutionList->getItemNameAt(i)); if (resolution && resolution->first == currentX && resolution->second == currentY)
if (resX == currentX && resY == currentY)
{ {
mResolutionList->setIndexSelected(i); mResolutionList->setIndexSelected(i);
break; break;
@ -853,7 +840,7 @@ namespace MWGui
void SettingsWindow::updateLightSettings() void SettingsWindow::updateLightSettings()
{ {
auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod(); auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod();
std::string lightingMethodStr = lightingMethodToStr(lightingMethod); MyGUI::UString lightingMethodStr = lightingMethodToStr(lightingMethod);
mLightingMethodButton->removeAllItems(); mLightingMethodButton->removeAllItems();
@ -886,28 +873,31 @@ namespace MWGui
// check if this resolution is supported in fullscreen // check if this resolution is supported in fullscreen
if (mResolutionList->getIndexSelected() != MyGUI::ITEM_NONE) if (mResolutionList->getIndexSelected() != MyGUI::ITEM_NONE)
{ {
const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); auto resolution
int resX, resY; = mResolutionList->getItemDataAt<std::pair<int, int>>(mResolutionList->getIndexSelected());
parseResolution(resX, resY, resStr); if (resolution)
Settings::video().mResolutionX.set(resX); {
Settings::video().mResolutionY.set(resY); Settings::video().mResolutionX.set(resolution->first);
Settings::video().mResolutionY.set(resolution->second);
}
} }
bool supported = false; bool supported = false;
int fallbackX = 0, fallbackY = 0; int fallbackX = 0, fallbackY = 0;
for (size_t i = 0; i < mResolutionList->getItemCount(); ++i) for (size_t i = 0; i < mResolutionList->getItemCount(); ++i)
{ {
const std::string& resStr = mResolutionList->getItemNameAt(i); auto resolution = mResolutionList->getItemDataAt<std::pair<int, int>>(i);
int resX, resY; if (!resolution)
parseResolution(resX, resY, resStr); continue;
if (i == 0) if (i == 0)
{ {
fallbackX = resX; fallbackX = resolution->first;
fallbackY = resY; fallbackY = resolution->second;
} }
if (resX == Settings::video().mResolutionX && resY == Settings::video().mResolutionY) if (resolution->first == Settings::video().mResolutionX
&& resolution->second == Settings::video().mResolutionY)
supported = true; supported = true;
} }

View File

@ -10,7 +10,6 @@
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/strings/conversion.hpp> #include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/format.hpp>
#include <components/misc/thread.hpp> #include <components/misc/thread.hpp>
#include <DetourNavMesh.h> #include <DetourNavMesh.h>
@ -20,6 +19,7 @@
#include <boost/geometry.hpp> #include <boost/geometry.hpp>
#include <algorithm> #include <algorithm>
#include <format>
#include <optional> #include <optional>
#include <set> #include <set>
#include <tuple> #include <tuple>
@ -78,7 +78,7 @@ namespace DetourNavigator
std::string makeRevision(const Version& version) std::string makeRevision(const Version& version)
{ {
return Misc::StringUtils::format(".%zu.%zu", version.mGeneration, version.mRevision); return std::format(".{}.{}", version.mGeneration, version.mRevision);
} }
void writeDebugRecastMesh( void writeDebugRecastMesh(
@ -90,9 +90,8 @@ namespace DetourNavigator
if (settings.mEnableRecastMeshFileNameRevision) if (settings.mEnableRecastMeshFileNameRevision)
revision = makeRevision(recastMesh.getVersion()); revision = makeRevision(recastMesh.getVersion());
writeToFile(recastMesh, writeToFile(recastMesh,
Misc::StringUtils::format( std::format("{}{}.{}.", settings.mRecastMeshPathPrefix, tilePosition.x(), tilePosition.y()), revision,
"%s%d.%d.", settings.mRecastMeshPathPrefix, tilePosition.x(), tilePosition.y()), settings.mRecast);
revision, settings.mRecast);
} }
void writeDebugNavMesh( void writeDebugNavMesh(

View File

@ -2,7 +2,6 @@
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/compression.hpp> #include <components/misc/compression.hpp>
#include <components/misc/strings/format.hpp>
#include <components/sqlite3/db.hpp> #include <components/sqlite3/db.hpp>
#include <components/sqlite3/request.hpp> #include <components/sqlite3/request.hpp>
@ -11,6 +10,7 @@
#include <sqlite3.h> #include <sqlite3.h>
#include <cstddef> #include <cstddef>
#include <format>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -148,7 +148,7 @@ namespace DetourNavigator
void setMaxPageCount(sqlite3& db, std::uint64_t value) void setMaxPageCount(sqlite3& db, std::uint64_t value)
{ {
const auto query = Misc::StringUtils::format("pragma max_page_count = %lu;", value); const auto query = std::format("pragma max_page_count = {};", value);
if (const int ec = sqlite3_exec(&db, query.c_str(), nullptr, nullptr, nullptr); ec != SQLITE_OK) if (const int ec = sqlite3_exec(&db, query.c_str(), nullptr, nullptr, nullptr); ec != SQLITE_OK)
throw std::runtime_error("Failed set max page count: " + std::string(sqlite3_errmsg(&db))); throw std::runtime_error("Failed set max page count: " + std::string(sqlite3_errmsg(&db)));
} }

View File

@ -1,6 +1,7 @@
#include "interpreter.hpp" #include "interpreter.hpp"
#include <cassert> #include <cassert>
#include <format>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
@ -9,27 +10,36 @@
namespace Interpreter namespace Interpreter
{ {
[[noreturn]] static void abortUnknownCode(int segment, int opcode) namespace
{ {
const std::string error = "unknown opcode " + std::to_string(opcode) + " in segment " + std::to_string(segment); [[noreturn]] void abortUnknownCode(int segment, int opcode)
throw std::runtime_error(error);
}
[[noreturn]] static void abortUnknownSegment(Type_Code code)
{
const std::string error = "opcode outside of the allocated segment range: " + std::to_string(code);
throw std::runtime_error(error);
}
template <typename T>
auto& getDispatcher(const T& segment, unsigned int seg, int opcode)
{
auto it = segment.find(opcode);
if (it == segment.end())
{ {
abortUnknownCode(seg, opcode); const std::string error = std::format("unknown opcode {} in segment {}", opcode, segment);
throw std::runtime_error(error);
} }
return it->second;
[[noreturn]] void abortUnknownSegment(Type_Code code)
{
const std::string error = std::format("opcode outside of the allocated segment range: {}", code);
throw std::runtime_error(error);
}
template <typename T>
auto& getDispatcher(const T& segment, unsigned int seg, int opcode)
{
auto it = segment.find(opcode);
if (it == segment.end())
{
abortUnknownCode(seg, opcode);
}
return it->second;
}
}
[[noreturn]] void Interpreter::abortDuplicateInstruction(std::string_view name, int code)
{
throw std::invalid_argument(
std::format("Duplicated interpreter instruction code in segment {}: {:#x}", name, code));
} }
void Interpreter::execute(Type_Code code) void Interpreter::execute(Type_Code code)

View File

@ -4,13 +4,9 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <stack> #include <stack>
#include <stdexcept>
#include <utility> #include <utility>
#include <components/misc/strings/format.hpp>
#include "opcodes.hpp" #include "opcodes.hpp"
#include "program.hpp"
#include "runtime.hpp" #include "runtime.hpp"
#include "types.hpp" #include "types.hpp"
@ -34,12 +30,13 @@ namespace Interpreter
void end(); void end();
[[noreturn]] void abortDuplicateInstruction(std::string_view name, int code);
template <typename T, typename... Args> template <typename T, typename... Args>
void installSegment(auto& segment, std::string_view name, int code, Args&&... args) void installSegment(auto& segment, std::string_view name, int code, Args&&... args)
{ {
if (segment.find(code) != segment.end()) if (segment.find(code) != segment.end())
throw std::invalid_argument(Misc::StringUtils::format( abortDuplicateInstruction(name, code);
"Duplicated interpreter instruction code in segment %s: 0x%x", name, code));
segment.emplace(code, std::make_unique<T>(std::forward<Args>(args)...)); segment.emplace(code, std::make_unique<T>(std::forward<Args>(args)...));
} }

View File

@ -3,10 +3,10 @@
#include <algorithm> #include <algorithm>
#include <bitset> #include <bitset>
#include <cassert> #include <cassert>
#include <format>
#include <sstream> #include <sstream>
#include <components/misc/strings/algorithm.hpp> #include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/format.hpp>
#include <components/misc/strings/lower.hpp> #include <components/misc/strings/lower.hpp>
namespace LuaUtil namespace LuaUtil
@ -187,16 +187,16 @@ namespace LuaUtil
line = line.substr(0, line.size() - 1); line = line.substr(0, line.size() - 1);
if (!Misc::StringUtils::ciEndsWith(line, ".lua")) if (!Misc::StringUtils::ciEndsWith(line, ".lua"))
throw std::runtime_error(Misc::StringUtils::format( throw std::runtime_error(
"Lua script should have suffix '.lua', got: %s", std::string(line.substr(0, 300)))); std::format("Lua script should have suffix '.lua', got: {}", line.substr(0, 300)));
// Split tags and script path // Split tags and script path
size_t semicolonPos = line.find(':'); size_t semicolonPos = line.find(':');
if (semicolonPos == std::string::npos) if (semicolonPos == std::string_view::npos)
throw std::runtime_error(Misc::StringUtils::format("No flags found in: %s", std::string(line))); throw std::runtime_error(std::format("No flags found in: {}", line));
std::string_view tagsStr = line.substr(0, semicolonPos); std::string_view tagsStr = line.substr(0, semicolonPos);
std::string_view scriptPath = line.substr(semicolonPos + 1); std::string_view scriptPath = line.substr(semicolonPos + 1);
while (isSpace(scriptPath[0])) while (!scriptPath.empty() && isSpace(scriptPath[0]))
scriptPath = scriptPath.substr(1); scriptPath = scriptPath.substr(1);
ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back(); ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back();
@ -222,8 +222,7 @@ namespace LuaUtil
else if (typesIt != typeTagsByName.end()) else if (typesIt != typeTagsByName.end())
script.mTypes.push_back(typesIt->second); script.mTypes.push_back(typesIt->second);
else else
throw std::runtime_error( throw std::runtime_error(std::format("Unknown tag '{}' in: {}", tagName, line));
Misc::StringUtils::format("Unknown tag '%s' in: %s", std::string(tagName), std::string(line)));
} }
} }
} }

View File

@ -4,7 +4,6 @@
#include <set> #include <set>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/strings/format.hpp>
#include "luastate.hpp" #include "luastate.hpp"
@ -116,14 +115,14 @@ namespace LuaUtil
void Registry::insert(const Info& info) void Registry::insert(const Info& info)
{ {
if (mIds.find(info.mKey) != mIds.end()) if (mIds.find(info.mKey) != mIds.end())
throw std::domain_error(Misc::StringUtils::format("Action key \"%s\" is already in use", info.mKey)); throw std::domain_error("Action key \"" + info.mKey + "\" is already in use");
if (info.mKey.empty()) if (info.mKey.empty())
throw std::domain_error("Action key can't be an empty string"); throw std::domain_error("Action key can't be an empty string");
if (info.mL10n.empty()) if (info.mL10n.empty())
throw std::domain_error("Localization context can't be empty"); throw std::domain_error("Localization context can't be empty");
if (!validateActionValue(info.mDefaultValue, info.mType)) if (!validateActionValue(info.mDefaultValue, info.mType))
throw std::logic_error(Misc::StringUtils::format( throw std::logic_error("Invalid value: \"" + LuaUtil::toString(info.mDefaultValue) + "\" for action \""
"Invalid value: \"%s\" for action \"%s\"", LuaUtil::toString(info.mDefaultValue), info.mKey)); + info.mKey + "\"");
Id id = mBindingTree.insert(); Id id = mBindingTree.insert();
mKeys.push_back(info.mKey); mKeys.push_back(info.mKey);
mIds[std::string(info.mKey)] = id; mIds[std::string(info.mKey)] = id;
@ -156,7 +155,7 @@ namespace LuaUtil
{ {
auto iter = mIds.find(key); auto iter = mIds.find(key);
if (iter == mIds.end()) if (iter == mIds.end())
throw std::logic_error(Misc::StringUtils::format("Unknown action key: \"%s\"", key)); throw std::logic_error("Unknown action key: \"" + std::string(key) + "\"");
return iter->second; return iter->second;
} }
@ -182,9 +181,16 @@ namespace LuaUtil
Id id = safeIdByKey(key); Id id = safeIdByKey(key);
Info info = mInfo[id]; Info info = mInfo[id];
if (info.mType != type) if (info.mType != type)
throw std::logic_error( {
Misc::StringUtils::format("Attempt to get value of type \"%s\" from action \"%s\" with type \"%s\"", std::string message("Attempt to get value of type \"");
typeName(type), key, typeName(info.mType))); message += typeName(type);
message += "\" from action \"";
message += key;
message += "\" with type \"";
message += typeName(info.mType);
message += "\"";
throw std::logic_error(message);
}
return mValues[id]; return mValues[id];
} }
@ -210,10 +216,9 @@ namespace LuaUtil
catch (std::exception& e) catch (std::exception& e)
{ {
if (!validateActionValue(newValue, mInfo[node].mType)) if (!validateActionValue(newValue, mInfo[node].mType))
Log(Debug::Error) << Misc::StringUtils::format( Log(Debug::Error)
"Error due to invalid value of action \"%s\"(\"%s\"): ", mKeys[node], << "Error due to invalid value of action \"" << mKeys[node]
LuaUtil::toString(newValue)) << "\"(\"" << LuaUtil::toString(newValue) << "\"): " << e.what();
<< e.what();
else else
Log(Debug::Error) << "Error in callback: " << e.what(); Log(Debug::Error) << "Error in callback: " << e.what();
} }
@ -222,8 +227,8 @@ namespace LuaUtil
bindings.end()); bindings.end());
if (!validateActionValue(newValue, mInfo[node].mType)) if (!validateActionValue(newValue, mInfo[node].mType))
Log(Debug::Error) << Misc::StringUtils::format( Log(Debug::Error) << "Invalid value of action \"" << mKeys[node]
"Invalid value of action \"%s\": %s", mKeys[node], LuaUtil::toString(newValue)); << "\": " << LuaUtil::toString(newValue);
if (mValues[node] != newValue) if (mValues[node] != newValue)
{ {
mValues[node] = sol::object(newValue); mValues[node] = sol::object(newValue);
@ -270,14 +275,14 @@ namespace LuaUtil
{ {
auto it = mIds.find(key); auto it = mIds.find(key);
if (it == mIds.end()) if (it == mIds.end())
throw std::domain_error(Misc::StringUtils::format("Unknown trigger key \"%s\"", key)); throw std::domain_error("Unknown trigger key \"" + std::string(key) + "\"");
return it->second; return it->second;
} }
void Registry::insert(const Info& info) void Registry::insert(const Info& info)
{ {
if (mIds.find(info.mKey) != mIds.end()) if (mIds.find(info.mKey) != mIds.end())
throw std::domain_error(Misc::StringUtils::format("Trigger key \"%s\" is already in use", info.mKey)); throw std::domain_error("Trigger key \"" + info.mKey + "\" is already in use");
if (info.mKey.empty()) if (info.mKey.empty())
throw std::domain_error("Trigger key can't be an empty string"); throw std::domain_error("Trigger key can't be an empty string");
if (info.mL10n.empty()) if (info.mL10n.empty())

View File

@ -1,7 +1,7 @@
#include <components/misc/strings/format.hpp>
#include "utf8.hpp" #include "utf8.hpp"
#include <format>
namespace namespace
{ {
constexpr std::string_view UTF8PATT = "[%z\x01-\x7F\xC2-\xF4][\x80-\xBF]*"; // %z is deprecated in Lua5.2 constexpr std::string_view UTF8PATT = "[%z\x01-\x7F\xC2-\xF4][\x80-\xBF]*"; // %z is deprecated in Lua5.2
@ -17,12 +17,12 @@ namespace
{ {
double integer; double integer;
if (!arg.is<double>()) if (!arg.is<double>())
throw std::runtime_error(Misc::StringUtils::format("bad argument #%i to '%s' (number expected, got %s)", n, throw std::runtime_error(std::format("bad argument #{} to '{}' (number expected, got {})", n, name,
name, sol::type_name(arg.lua_state(), arg.get_type()))); sol::type_name(arg.lua_state(), arg.get_type())));
if (std::modf(arg, &integer) != 0) if (std::modf(arg, &integer) != 0)
throw std::runtime_error( throw std::runtime_error(
Misc::StringUtils::format("bad argument #%i to '%s' (number has no integer representation)", n, name)); std::format("bad argument #{} to '{}' (number has no integer representation)", n, name));
return static_cast<std::int64_t>(integer); return static_cast<std::int64_t>(integer);
} }
@ -127,8 +127,7 @@ namespace LuaUtf8
{ {
int64_t codepoint = getInteger(args[i], (i + 1), "char"); int64_t codepoint = getInteger(args[i], (i + 1), "char");
if (codepoint < 0 || codepoint > MAXUNICODE) if (codepoint < 0 || codepoint > MAXUNICODE)
throw std::runtime_error( throw std::runtime_error(std::format("bad argument #{} to 'char' (value out of range)", i + 1));
"bad argument #" + std::to_string(i + 1) + " to 'char' (value out of range)");
codepointToUTF8(static_cast<char32_t>(codepoint), result); codepointToUTF8(static_cast<char32_t>(codepoint), result);
} }
@ -142,8 +141,7 @@ namespace LuaUtf8
{ {
const auto pair = decodeNextUTF8Character(s, posByte); const auto pair = decodeNextUTF8Character(s, posByte);
if (pair.second == -1) if (pair.second == -1)
throw std::runtime_error( throw std::runtime_error(std::format("Invalid UTF-8 code at position {}", posByte.size()));
"Invalid UTF-8 code at position " + std::to_string(posByte.size()));
return pair; return pair;
} }
@ -202,7 +200,7 @@ namespace LuaUtf8
{ {
codepoints.push_back(decodeNextUTF8Character(s, posByte).second); codepoints.push_back(decodeNextUTF8Character(s, posByte).second);
if (codepoints.back() == -1) if (codepoints.back() == -1)
throw std::runtime_error("Invalid UTF-8 code at position " + std::to_string(posByte.size())); throw std::runtime_error(std::format("Invalid UTF-8 code at position {}", posByte.size()));
} }
return sol::as_returns(std::move(codepoints)); return sol::as_returns(std::move(codepoints));

View File

@ -2,6 +2,7 @@
#include <charconv> #include <charconv>
#include <cmath> #include <cmath>
#include <format>
#include <limits> #include <limits>
#include <regex> #include <regex>
#include <stdexcept> #include <stdexcept>
@ -13,8 +14,7 @@
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <components/misc/strings/format.hpp> #include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/lower.hpp>
namespace LuaUtil namespace LuaUtil
{ {
@ -213,10 +213,10 @@ namespace LuaUtil
} }
case ScalarType::Boolean: case ScalarType::Boolean:
{ {
if (Misc::StringUtils::lowerCase(value) == "true") if (Misc::StringUtils::ciEqual(value, "true"))
return sol::make_object<bool>(lua, true); return sol::make_object<bool>(lua, true);
if (Misc::StringUtils::lowerCase(value) == "false") if (Misc::StringUtils::ciEqual(value, "false"))
return sol::make_object<bool>(lua, false); return sol::make_object<bool>(lua, false);
nodeError(node, "Can not read a boolean value '" + value + "'"); nodeError(node, "Can not read a boolean value '" + value + "'");
@ -272,8 +272,8 @@ namespace LuaUtil
[[noreturn]] void nodeError(const YAML::Node& node, const std::string& message) [[noreturn]] void nodeError(const YAML::Node& node, const std::string& message)
{ {
const auto& mark = node.Mark(); const auto& mark = node.Mark();
std::string error = Misc::StringUtils::format( std::string error
" at line=%d column=%d position=%d", mark.line + 1, mark.column + 1, mark.pos + 1); = std::format(" at line={} column={} position={}", mark.line + 1, mark.column + 1, mark.pos + 1);
throw std::runtime_error(message + error); throw std::runtime_error(message + error);
} }
} }

View File

@ -1,13 +1,12 @@
#include "display.hpp" #include "display.hpp"
#include <format>
#include <numeric> #include <numeric>
#include <string> #include <string>
#include <components/misc/strings/format.hpp>
namespace Misc namespace Misc
{ {
std::string getResolutionText(int x, int y, const std::string& format) std::string getResolutionText(int x, int y)
{ {
int gcd = std::gcd(x, y); int gcd = std::gcd(x, y);
if (gcd == 0) if (gcd == 0)
@ -77,6 +76,6 @@ namespace Misc
if (flipped) if (flipped)
std::swap(xaspect, yaspect); std::swap(xaspect, yaspect);
return Misc::StringUtils::format(format, x, y, xaspect, yaspect); return std::format("{} × {} ({}:{})", x, y, xaspect, yaspect);
} }
} }

View File

@ -5,7 +5,7 @@
namespace Misc namespace Misc
{ {
std::string getResolutionText(int x, int y, const std::string& format); std::string getResolutionText(int x, int y);
} }
#endif #endif

View File

@ -4,7 +4,6 @@
#include <utility> #include <utility>
#include <components/misc/strings/algorithm.hpp> #include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/format.hpp>
#include <components/misc/strings/lower.hpp> #include <components/misc/strings/lower.hpp>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
@ -68,8 +67,7 @@ namespace SceneUtil
if (!root.IsDefined() || root.IsNull() || root.IsScalar()) if (!root.IsDefined() || root.IsNull() || root.IsScalar())
{ {
Log(Debug::Error) << Misc::StringUtils::format( Log(Debug::Error) << "Can't parse file '" << configPath << "'. Check that it's a valid YAML/JSON file.";
"Can't parse file '%s'. Check that it's a valid YAML/JSON file.", configPath);
return nullptr; return nullptr;
} }
@ -105,11 +103,11 @@ namespace SceneUtil
else else
{ {
throw std::domain_error( throw std::domain_error(
Misc::StringUtils::format("'blending_rules' object not found in '%s' file!", configPath)); "'blending_rules' object not found in '" + std::string(configPath.value()) + "' file!");
} }
// If no rules then dont allocate any instance // If no rules then dont allocate any instance
if (rules.size() == 0) if (rules.empty())
return nullptr; return nullptr;
return new AnimBlendRules(rules); return new AnimBlendRules(rules);

View File

@ -3,44 +3,47 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
#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> #include <filesystem>
#include <format>
#include <fstream> #include <fstream>
#include <osg/Program>
#include <osgViewer/Viewer>
#include <regex> #include <regex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <unordered_map> #include <unordered_map>
#include <osg/Program>
#include <osgViewer/Viewer>
#include <components/debug/debuglog.hpp>
#include <components/files/conversion.hpp>
#include <components/misc/pathhelpers.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/settings/settings.hpp>
namespace namespace
{ {
osg::Shader::Type getShaderType(const std::string& templateName) osg::Shader::Type getShaderType(const std::string& templateName)
{ {
auto ext = std::filesystem::path(templateName).extension(); std::string_view ext = Misc::getFileExtension(templateName);
if (ext == ".vert") if (ext == "vert")
return osg::Shader::VERTEX; return osg::Shader::VERTEX;
if (ext == ".frag") if (ext == "frag")
return osg::Shader::FRAGMENT; return osg::Shader::FRAGMENT;
if (ext == ".geom") if (ext == "geom")
return osg::Shader::GEOMETRY; return osg::Shader::GEOMETRY;
if (ext == ".comp") if (ext == "comp")
return osg::Shader::COMPUTE; return osg::Shader::COMPUTE;
if (ext == ".tese") if (ext == "tese")
return osg::Shader::TESSEVALUATION; return osg::Shader::TESSEVALUATION;
if (ext == ".tesc") if (ext == "tesc")
return osg::Shader::TESSCONTROL; return osg::Shader::TESSCONTROL;
throw std::runtime_error("unrecognized shader template name: " + templateName); throw std::runtime_error("unrecognized shader template name: " + templateName);
} }
std::string getRootPrefix(const std::string& path) std::string_view getRootPrefix(std::string_view path)
{ {
if (path.starts_with("lib")) if (path.starts_with("lib"))
return "lib"; return "lib";
@ -48,8 +51,26 @@ namespace
return "compatibility"; return "compatibility";
else if (path.starts_with("core")) else if (path.starts_with("core"))
return "core"; return "core";
return {};
}
int getLineNumber(std::string_view source, std::size_t foundPos, int lineNumber, int offset)
{
constexpr std::string_view tag = "#line";
std::size_t lineDirectivePosition = source.rfind(tag, foundPos);
if (lineDirectivePosition != std::string_view::npos)
{
std::size_t lineNumberStart = lineDirectivePosition + tag.size() + 1;
std::size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
std::string_view lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
lineNumber = Misc::StringUtils::toNumeric<int>(lineNumberString, 2) + offset;
}
else else
return ""; {
lineDirectivePosition = 0;
}
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n');
return lineNumber;
} }
} }
@ -85,23 +106,9 @@ namespace Shader
if (foundPos == std::string::npos) if (foundPos == std::string::npos)
break; break;
size_t lineDirectivePosition = source.rfind("#line", foundPos); int lineNumber = getLineNumber(source, foundPos, 1, -1);
int lineNumber;
if (lineDirectivePosition != std::string::npos)
{
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 = Misc::StringUtils::toNumeric<int>(lineNumberString, 2) - 1;
}
else
{
lineDirectivePosition = 0;
lineNumber = 1;
}
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n');
source.replace(foundPos, 0, "#line " + std::to_string(lineNumber) + "\n"); source.replace(foundPos, 0, std::format("#line {}\n", lineNumber));
position = foundPos; position = foundPos;
} }
@ -154,21 +161,7 @@ namespace Shader
std::filesystem::path includePath = shaderPath / includeFilename; std::filesystem::path includePath = shaderPath / includeFilename;
// Determine the line number that will be used for the #line directive following the included source // Determine the line number that will be used for the #line directive following the included source
size_t lineDirectivePosition = source.rfind("#line", foundPos); int lineNumber = getLineNumber(source, foundPos, 0, -1);
int lineNumber;
if (lineDirectivePosition != std::string::npos)
{
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 = Misc::StringUtils::toNumeric<int>(lineNumberString, 2) - 1;
}
else
{
lineDirectivePosition = 0;
lineNumber = 0;
}
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n');
// Include the file recursively // Include the file recursively
std::ifstream includeFstream; std::ifstream includeFstream;
@ -202,7 +195,8 @@ namespace Shader
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos) bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos)
{ {
size_t iterNameStart = foundPos + strlen("$foreach") + 1; constexpr std::string_view directiveStart = "$foreach";
size_t iterNameStart = foundPos + directiveStart.size() + 1;
size_t iterNameEnd = source.find_first_of(" \n\r()[].;,", iterNameStart); size_t iterNameEnd = source.find_first_of(" \n\r()[].;,", iterNameStart);
if (iterNameEnd == std::string::npos) if (iterNameEnd == std::string::npos)
{ {
@ -218,46 +212,32 @@ namespace Shader
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
return false; return false;
} }
std::string list = source.substr(listStart, listEnd - listStart); std::string_view list = std::string_view(source).substr(listStart, listEnd - listStart);
std::vector<std::string> listElements; std::vector<std::string> listElements;
if (list != "") if (!list.empty())
Misc::StringUtils::split(list, listElements, ","); Misc::StringUtils::split(list, listElements, ",");
size_t contentStart = source.find_first_not_of("\n\r", listEnd); size_t contentStart = source.find_first_not_of("\n\r", listEnd);
size_t contentEnd = source.find("$endforeach", contentStart); constexpr std::string_view directiveEnd = "$endforeach";
size_t contentEnd = source.find(directiveEnd, contentStart);
if (contentEnd == std::string::npos) if (contentEnd == std::string::npos)
{ {
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
return false; return false;
} }
std::string content = source.substr(contentStart, contentEnd - contentStart); std::string_view content = std::string_view(source).substr(contentStart, contentEnd - contentStart);
size_t overallEnd = contentEnd + std::string("$endforeach").length(); size_t overallEnd = contentEnd + directiveEnd.size();
size_t lineDirectivePosition = source.rfind("#line", overallEnd); int lineNumber = getLineNumber(source, overallEnd, 2, 0);
int lineNumber;
if (lineDirectivePosition != std::string::npos)
{
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 = Misc::StringUtils::toNumeric<int>(lineNumberString, 2);
}
else
{
lineDirectivePosition = 0;
lineNumber = 2;
}
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + overallEnd, '\n');
std::string replacement; std::string replacement;
for (std::vector<std::string>::const_iterator element = listElements.cbegin(); element != listElements.cend(); for (const std::string& element : listElements)
element++)
{ {
std::string contentInstance = content; std::string contentInstance(content);
size_t foundIterator; size_t foundIterator;
while ((foundIterator = contentInstance.find(iteratorName)) != std::string::npos) while ((foundIterator = contentInstance.find(iteratorName)) != std::string::npos)
contentInstance.replace(foundIterator, iteratorName.length(), *element); contentInstance.replace(foundIterator, iteratorName.length(), element);
replacement += contentInstance; replacement += contentInstance;
} }
replacement += "\n#line " + std::to_string(lineNumber); replacement += "\n#line " + std::to_string(lineNumber);
@ -327,7 +307,7 @@ namespace Shader
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
return false; return false;
} }
std::string directive = source.substr(foundPos + 1, endPos - (foundPos + 1)); std::string_view directive = std::string_view(source).substr(foundPos + 1, endPos - (foundPos + 1));
if (directive == "foreach") if (directive == "foreach")
{ {
if (!parseForeachDirective(source, templateName, foundPos)) if (!parseForeachDirective(source, templateName, foundPos))
@ -574,7 +554,7 @@ namespace Shader
// Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently. // Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently.
// Append shader source filename for debugging. // Append shader source filename for debugging.
static unsigned int counter = 0; static unsigned int counter = 0;
shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName)); shader->setName(std::format("{} {}", counter++, templateName));
mHotReloadManager->addShaderFiles(templateName, defines); mHotReloadManager->addShaderFiles(templateName, defines);

View File

@ -2,6 +2,7 @@
#define OPENMW_COMPONENTS_SHADERMANAGER_H #define OPENMW_COMPONENTS_SHADERMANAGER_H
#include <array> #include <array>
#include <filesystem>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -9,11 +10,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <osg/ref_ptr>
#include <filesystem>
#include <osg/Program> #include <osg/Program>
#include <osg/Shader> #include <osg/Shader>
#include <osg/ref_ptr>
namespace osgViewer namespace osgViewer
{ {