diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 38b0446efc..b25d6e3dae 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -201,7 +201,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen) 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())); } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 4ae96f982a..d9c82d89e7 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -46,7 +46,7 @@ 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") return "#{OMWEngine:TextureFilteringDisabled}"; @@ -65,9 +65,9 @@ namespace return "#{OMWEngine:TextureFilteringOther}"; } - std::string lightingMethodToStr(SceneUtil::LightingMethod method) + MyGUI::UString lightingMethodToStr(SceneUtil::LightingMethod method) { - std::string result; + std::string_view result; switch (method) { case SceneUtil::LightingMethod::FFP: @@ -82,18 +82,7 @@ namespace break; } - return MyGUI::LanguageManager::getInstance().replaceTags(result); - } - - void parseResolution(int& x, int& y, const std::string& str) - { - std::vector 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]); + return MyGUI::LanguageManager::getInstance().replaceTags(MyGUI::UString(result)); } bool sortResolutions(std::pair left, std::pair right) @@ -368,10 +357,10 @@ namespace MWGui std::sort(resolutions.begin(), resolutions.end(), sortResolutions); for (std::pair& 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) - mResolutionList->addItem(str); + mResolutionList->addItem(str, resolution); } highlightCurrentResolution(); @@ -493,14 +482,14 @@ namespace MWGui void SettingsWindow::onResolutionAccept() { - const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); - int resX, resY; - parseResolution(resX, resY, resStr); + auto resolution = mResolutionList->getItemDataAt>(mResolutionList->getIndexSelected()); + if (resolution) + { + Settings::video().mResolutionX.set(resolution->first); + Settings::video().mResolutionY.set(resolution->second); - Settings::video().mResolutionX.set(resX); - Settings::video().mResolutionY.set(resY); - - apply(); + apply(); + } } void SettingsWindow::onResolutionCancel() @@ -517,10 +506,8 @@ namespace MWGui for (size_t i = 0; i < mResolutionList->getItemCount(); ++i) { - int resX, resY; - parseResolution(resX, resY, mResolutionList->getItemNameAt(i)); - - if (resX == currentX && resY == currentY) + auto resolution = mResolutionList->getItemDataAt>(i); + if (resolution && resolution->first == currentX && resolution->second == currentY) { mResolutionList->setIndexSelected(i); break; @@ -853,7 +840,7 @@ namespace MWGui void SettingsWindow::updateLightSettings() { auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod(); - std::string lightingMethodStr = lightingMethodToStr(lightingMethod); + MyGUI::UString lightingMethodStr = lightingMethodToStr(lightingMethod); mLightingMethodButton->removeAllItems(); @@ -886,28 +873,31 @@ namespace MWGui // check if this resolution is supported in fullscreen if (mResolutionList->getIndexSelected() != MyGUI::ITEM_NONE) { - const std::string& resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected()); - int resX, resY; - parseResolution(resX, resY, resStr); - Settings::video().mResolutionX.set(resX); - Settings::video().mResolutionY.set(resY); + auto resolution + = mResolutionList->getItemDataAt>(mResolutionList->getIndexSelected()); + if (resolution) + { + Settings::video().mResolutionX.set(resolution->first); + Settings::video().mResolutionY.set(resolution->second); + } } bool supported = false; int fallbackX = 0, fallbackY = 0; for (size_t i = 0; i < mResolutionList->getItemCount(); ++i) { - const std::string& resStr = mResolutionList->getItemNameAt(i); - int resX, resY; - parseResolution(resX, resY, resStr); + auto resolution = mResolutionList->getItemDataAt>(i); + if (!resolution) + continue; if (i == 0) { - fallbackX = resX; - fallbackY = resY; + fallbackX = resolution->first; + 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; } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index fe8cadd703..4a4137170a 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -20,6 +19,7 @@ #include #include +#include #include #include #include @@ -78,7 +78,7 @@ namespace DetourNavigator 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( @@ -90,9 +90,8 @@ namespace DetourNavigator if (settings.mEnableRecastMeshFileNameRevision) revision = makeRevision(recastMesh.getVersion()); writeToFile(recastMesh, - Misc::StringUtils::format( - "%s%d.%d.", settings.mRecastMeshPathPrefix, tilePosition.x(), tilePosition.y()), - revision, settings.mRecast); + std::format("{}{}.{}.", settings.mRecastMeshPathPrefix, tilePosition.x(), tilePosition.y()), revision, + settings.mRecast); } void writeDebugNavMesh( diff --git a/components/detournavigator/navmeshdb.cpp b/components/detournavigator/navmeshdb.cpp index 76f0811f16..bfc6dd5ecb 100644 --- a/components/detournavigator/navmeshdb.cpp +++ b/components/detournavigator/navmeshdb.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -11,6 +10,7 @@ #include #include +#include #include #include @@ -148,7 +148,7 @@ namespace DetourNavigator 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) throw std::runtime_error("Failed set max page count: " + std::string(sqlite3_errmsg(&db))); } diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp index 6a51a2cddf..be6d7d1adf 100644 --- a/components/interpreter/interpreter.cpp +++ b/components/interpreter/interpreter.cpp @@ -1,6 +1,7 @@ #include "interpreter.hpp" #include +#include #include #include @@ -9,27 +10,36 @@ 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); - 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 - auto& getDispatcher(const T& segment, unsigned int seg, int opcode) - { - auto it = segment.find(opcode); - if (it == segment.end()) + [[noreturn]] void abortUnknownCode(int segment, int opcode) { - 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 + 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) diff --git a/components/interpreter/interpreter.hpp b/components/interpreter/interpreter.hpp index 381cb5dd6b..6ad7a9dc96 100644 --- a/components/interpreter/interpreter.hpp +++ b/components/interpreter/interpreter.hpp @@ -4,13 +4,9 @@ #include #include #include -#include #include -#include - #include "opcodes.hpp" -#include "program.hpp" #include "runtime.hpp" #include "types.hpp" @@ -34,12 +30,13 @@ namespace Interpreter void end(); + [[noreturn]] void abortDuplicateInstruction(std::string_view name, int code); + template void installSegment(auto& segment, std::string_view name, int code, Args&&... args) { if (segment.find(code) != segment.end()) - throw std::invalid_argument(Misc::StringUtils::format( - "Duplicated interpreter instruction code in segment %s: 0x%x", name, code)); + abortDuplicateInstruction(name, code); segment.emplace(code, std::make_unique(std::forward(args)...)); } diff --git a/components/lua/configuration.cpp b/components/lua/configuration.cpp index 858137ab73..cbec2e4abc 100644 --- a/components/lua/configuration.cpp +++ b/components/lua/configuration.cpp @@ -3,10 +3,10 @@ #include #include #include +#include #include #include -#include #include namespace LuaUtil @@ -187,16 +187,16 @@ namespace LuaUtil line = line.substr(0, line.size() - 1); if (!Misc::StringUtils::ciEndsWith(line, ".lua")) - throw std::runtime_error(Misc::StringUtils::format( - "Lua script should have suffix '.lua', got: %s", std::string(line.substr(0, 300)))); + throw std::runtime_error( + std::format("Lua script should have suffix '.lua', got: {}", line.substr(0, 300))); // Split tags and script path size_t semicolonPos = line.find(':'); - if (semicolonPos == std::string::npos) - throw std::runtime_error(Misc::StringUtils::format("No flags found in: %s", std::string(line))); + if (semicolonPos == std::string_view::npos) + throw std::runtime_error(std::format("No flags found in: {}", line)); std::string_view tagsStr = line.substr(0, semicolonPos); std::string_view scriptPath = line.substr(semicolonPos + 1); - while (isSpace(scriptPath[0])) + while (!scriptPath.empty() && isSpace(scriptPath[0])) scriptPath = scriptPath.substr(1); ESM::LuaScriptCfg& script = cfg.mScripts.emplace_back(); @@ -222,8 +222,7 @@ namespace LuaUtil else if (typesIt != typeTagsByName.end()) script.mTypes.push_back(typesIt->second); else - throw std::runtime_error( - Misc::StringUtils::format("Unknown tag '%s' in: %s", std::string(tagName), std::string(line))); + throw std::runtime_error(std::format("Unknown tag '{}' in: {}", tagName, line)); } } } diff --git a/components/lua/inputactions.cpp b/components/lua/inputactions.cpp index b0c7fe2e9f..c220bdf331 100644 --- a/components/lua/inputactions.cpp +++ b/components/lua/inputactions.cpp @@ -4,7 +4,6 @@ #include #include -#include #include "luastate.hpp" @@ -116,14 +115,14 @@ namespace LuaUtil void Registry::insert(const Info& info) { 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()) throw std::domain_error("Action key can't be an empty string"); if (info.mL10n.empty()) throw std::domain_error("Localization context can't be empty"); if (!validateActionValue(info.mDefaultValue, info.mType)) - throw std::logic_error(Misc::StringUtils::format( - "Invalid value: \"%s\" for action \"%s\"", LuaUtil::toString(info.mDefaultValue), info.mKey)); + throw std::logic_error("Invalid value: \"" + LuaUtil::toString(info.mDefaultValue) + "\" for action \"" + + info.mKey + "\""); Id id = mBindingTree.insert(); mKeys.push_back(info.mKey); mIds[std::string(info.mKey)] = id; @@ -156,7 +155,7 @@ namespace LuaUtil { auto iter = mIds.find(key); 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; } @@ -182,9 +181,16 @@ namespace LuaUtil Id id = safeIdByKey(key); Info info = mInfo[id]; if (info.mType != type) - throw std::logic_error( - Misc::StringUtils::format("Attempt to get value of type \"%s\" from action \"%s\" with type \"%s\"", - typeName(type), key, typeName(info.mType))); + { + std::string message("Attempt to get value of type \""); + message += typeName(type); + message += "\" from action \""; + message += key; + message += "\" with type \""; + message += typeName(info.mType); + message += "\""; + throw std::logic_error(message); + } return mValues[id]; } @@ -210,10 +216,9 @@ namespace LuaUtil catch (std::exception& e) { if (!validateActionValue(newValue, mInfo[node].mType)) - Log(Debug::Error) << Misc::StringUtils::format( - "Error due to invalid value of action \"%s\"(\"%s\"): ", mKeys[node], - LuaUtil::toString(newValue)) - << e.what(); + Log(Debug::Error) + << "Error due to invalid value of action \"" << mKeys[node] + << "\"(\"" << LuaUtil::toString(newValue) << "\"): " << e.what(); else Log(Debug::Error) << "Error in callback: " << e.what(); } @@ -222,8 +227,8 @@ namespace LuaUtil bindings.end()); if (!validateActionValue(newValue, mInfo[node].mType)) - Log(Debug::Error) << Misc::StringUtils::format( - "Invalid value of action \"%s\": %s", mKeys[node], LuaUtil::toString(newValue)); + Log(Debug::Error) << "Invalid value of action \"" << mKeys[node] + << "\": " << LuaUtil::toString(newValue); if (mValues[node] != newValue) { mValues[node] = sol::object(newValue); @@ -270,14 +275,14 @@ namespace LuaUtil { auto it = mIds.find(key); 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; } void Registry::insert(const Info& info) { 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()) throw std::domain_error("Trigger key can't be an empty string"); if (info.mL10n.empty()) diff --git a/components/lua/utf8.cpp b/components/lua/utf8.cpp index 11c4cbc1e8..4c2813b1bc 100644 --- a/components/lua/utf8.cpp +++ b/components/lua/utf8.cpp @@ -1,7 +1,7 @@ -#include - #include "utf8.hpp" +#include + namespace { 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; if (!arg.is()) - throw std::runtime_error(Misc::StringUtils::format("bad argument #%i to '%s' (number expected, got %s)", n, - name, sol::type_name(arg.lua_state(), arg.get_type()))); + throw std::runtime_error(std::format("bad argument #{} to '{}' (number expected, got {})", n, name, + sol::type_name(arg.lua_state(), arg.get_type()))); if (std::modf(arg, &integer) != 0) 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(integer); } @@ -127,8 +127,7 @@ namespace LuaUtf8 { int64_t codepoint = getInteger(args[i], (i + 1), "char"); if (codepoint < 0 || codepoint > MAXUNICODE) - throw std::runtime_error( - "bad argument #" + std::to_string(i + 1) + " to 'char' (value out of range)"); + throw std::runtime_error(std::format("bad argument #{} to 'char' (value out of range)", i + 1)); codepointToUTF8(static_cast(codepoint), result); } @@ -142,8 +141,7 @@ namespace LuaUtf8 { const auto pair = decodeNextUTF8Character(s, posByte); if (pair.second == -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 pair; } @@ -202,7 +200,7 @@ namespace LuaUtf8 { codepoints.push_back(decodeNextUTF8Character(s, posByte).second); 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)); diff --git a/components/lua/yamlloader.cpp b/components/lua/yamlloader.cpp index df83af6253..e271f7c428 100644 --- a/components/lua/yamlloader.cpp +++ b/components/lua/yamlloader.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -13,8 +14,7 @@ #include -#include -#include +#include namespace LuaUtil { @@ -213,10 +213,10 @@ namespace LuaUtil } case ScalarType::Boolean: { - if (Misc::StringUtils::lowerCase(value) == "true") + if (Misc::StringUtils::ciEqual(value, "true")) return sol::make_object(lua, true); - if (Misc::StringUtils::lowerCase(value) == "false") + if (Misc::StringUtils::ciEqual(value, "false")) return sol::make_object(lua, false); 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) { const auto& mark = node.Mark(); - std::string error = Misc::StringUtils::format( - " at line=%d column=%d position=%d", mark.line + 1, mark.column + 1, mark.pos + 1); + std::string error + = std::format(" at line={} column={} position={}", mark.line + 1, mark.column + 1, mark.pos + 1); throw std::runtime_error(message + error); } } diff --git a/components/misc/display.cpp b/components/misc/display.cpp index ee78b2a0c9..2a7c5a4688 100644 --- a/components/misc/display.cpp +++ b/components/misc/display.cpp @@ -1,13 +1,12 @@ #include "display.hpp" +#include #include #include -#include - 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); if (gcd == 0) @@ -77,6 +76,6 @@ namespace Misc if (flipped) std::swap(xaspect, yaspect); - return Misc::StringUtils::format(format, x, y, xaspect, yaspect); + return std::format("{} × {} ({}:{})", x, y, xaspect, yaspect); } } diff --git a/components/misc/display.hpp b/components/misc/display.hpp index 82037661c8..6f60a48cda 100644 --- a/components/misc/display.hpp +++ b/components/misc/display.hpp @@ -5,7 +5,7 @@ namespace Misc { - std::string getResolutionText(int x, int y, const std::string& format); + std::string getResolutionText(int x, int y); } #endif diff --git a/components/sceneutil/animblendrules.cpp b/components/sceneutil/animblendrules.cpp index c285988f40..a67de075b2 100644 --- a/components/sceneutil/animblendrules.cpp +++ b/components/sceneutil/animblendrules.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -68,8 +67,7 @@ namespace SceneUtil if (!root.IsDefined() || root.IsNull() || root.IsScalar()) { - Log(Debug::Error) << Misc::StringUtils::format( - "Can't parse file '%s'. Check that it's a valid YAML/JSON file.", configPath); + Log(Debug::Error) << "Can't parse file '" << configPath << "'. Check that it's a valid YAML/JSON file."; return nullptr; } @@ -105,11 +103,11 @@ namespace SceneUtil else { 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 (rules.size() == 0) + if (rules.empty()) return nullptr; return new AnimBlendRules(rules); diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 84e53e7317..f44c8f475d 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -3,44 +3,47 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include +#include #include -#include -#include #include #include #include #include +#include +#include + +#include +#include +#include +#include +#include +#include + namespace { 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; - if (ext == ".frag") + if (ext == "frag") return osg::Shader::FRAGMENT; - if (ext == ".geom") + if (ext == "geom") return osg::Shader::GEOMETRY; - if (ext == ".comp") + if (ext == "comp") return osg::Shader::COMPUTE; - if (ext == ".tese") + if (ext == "tese") return osg::Shader::TESSEVALUATION; - if (ext == ".tesc") + if (ext == "tesc") return osg::Shader::TESSCONTROL; 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")) return "lib"; @@ -48,8 +51,26 @@ namespace return "compatibility"; else if (path.starts_with("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(lineNumberString, 2) + offset; + } 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) break; - size_t lineDirectivePosition = source.rfind("#line", foundPos); - 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(lineNumberString, 2) - 1; - } - else - { - lineDirectivePosition = 0; - lineNumber = 1; - } - lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'); + int lineNumber = getLineNumber(source, foundPos, 1, -1); - source.replace(foundPos, 0, "#line " + std::to_string(lineNumber) + "\n"); + source.replace(foundPos, 0, std::format("#line {}\n", lineNumber)); position = foundPos; } @@ -154,21 +161,7 @@ namespace Shader std::filesystem::path includePath = shaderPath / includeFilename; // 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; - 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(lineNumberString, 2) - 1; - } - else - { - lineDirectivePosition = 0; - lineNumber = 0; - } - lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'); + int lineNumber = getLineNumber(source, foundPos, 0, -1); // Include the file recursively std::ifstream includeFstream; @@ -202,7 +195,8 @@ namespace Shader 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); if (iterNameEnd == std::string::npos) { @@ -218,46 +212,32 @@ namespace Shader Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; return false; } - std::string list = source.substr(listStart, listEnd - listStart); + std::string_view list = std::string_view(source).substr(listStart, listEnd - listStart); std::vector listElements; - if (list != "") + if (!list.empty()) Misc::StringUtils::split(list, listElements, ","); 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) { Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; 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; - 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(lineNumberString, 2); - } - else - { - lineDirectivePosition = 0; - lineNumber = 2; - } - lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + overallEnd, '\n'); + int lineNumber = getLineNumber(source, overallEnd, 2, 0); std::string replacement; - for (std::vector::const_iterator element = listElements.cbegin(); element != listElements.cend(); - element++) + for (const std::string& element : listElements) { - std::string contentInstance = content; + std::string contentInstance(content); size_t foundIterator; while ((foundIterator = contentInstance.find(iteratorName)) != std::string::npos) - contentInstance.replace(foundIterator, iteratorName.length(), *element); + contentInstance.replace(foundIterator, iteratorName.length(), element); replacement += contentInstance; } replacement += "\n#line " + std::to_string(lineNumber); @@ -327,7 +307,7 @@ namespace Shader Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF"; 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 (!parseForeachDirective(source, templateName, foundPos)) @@ -574,7 +554,7 @@ namespace Shader // Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently. // Append shader source filename for debugging. static unsigned int counter = 0; - shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName)); + shader->setName(std::format("{} {}", counter++, templateName)); mHotReloadManager->addShaderFiles(templateName, defines); diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 827fef7e88..bdcd8622dd 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -2,6 +2,7 @@ #define OPENMW_COMPONENTS_SHADERMANAGER_H #include +#include #include #include #include @@ -9,11 +10,9 @@ #include #include -#include - -#include #include #include +#include namespace osgViewer {