mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 13:41:32 +00:00
Revert format change and ensure string_view args are null-terminated
This commit is contained in:
parent
1d21330fcc
commit
4e2e5ad002
3 changed files with 17 additions and 10 deletions
|
@ -168,7 +168,8 @@ namespace MWGui
|
||||||
// ask for confirmation
|
// ask for confirmation
|
||||||
mSpellToDelete = spellId;
|
mSpellToDelete = spellId;
|
||||||
ConfirmationDialog* dialog = windowManager->getConfirmationDialog();
|
ConfirmationDialog* dialog = windowManager->getConfirmationDialog();
|
||||||
std::string question = Misc::StringUtils::format(windowManager->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"), spell->mName);
|
std::string question{windowManager->getGameSettingString("sQuestionDeleteSpell", "Delete %s?")};
|
||||||
|
question = Misc::StringUtils::format(question, spell->mName);
|
||||||
dialog->askForConfirmation(question);
|
dialog->askForConfirmation(question);
|
||||||
dialog->eventOkClicked.clear();
|
dialog->eventOkClicked.clear();
|
||||||
dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
|
||||||
|
|
|
@ -267,8 +267,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
||||||
/// \todo check if character is the player, if levelling is ever implemented for NPCs
|
/// \todo check if character is the player, if levelling is ever implemented for NPCs
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("skillraise");
|
MWBase::Environment::get().getWindowManager()->playSound("skillraise");
|
||||||
|
|
||||||
std::string message = Misc::StringUtils::format(MWBase::Environment::get().getWindowManager()->getGameSettingString("sNotifyMessage39", {}),
|
std::string message{MWBase::Environment::get().getWindowManager()->getGameSettingString("sNotifyMessage39", {})};
|
||||||
("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast<int>(base));
|
message = Misc::StringUtils::format(message, ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), static_cast<int>(base));
|
||||||
|
|
||||||
if (readBook)
|
if (readBook)
|
||||||
message = "#{sBookSkillMessage}\n" + message;
|
message = "#{sBookSkillMessage}\n" + message;
|
||||||
|
|
|
@ -7,11 +7,14 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Misc::StringUtils
|
namespace Misc::StringUtils
|
||||||
{
|
{
|
||||||
namespace Details
|
struct Details
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> mMemorySafety;
|
||||||
|
|
||||||
// Allow to convert complex arguments to C-style strings for format() function
|
// Allow to convert complex arguments to C-style strings for format() function
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T argument(T value) noexcept
|
T argument(T value) noexcept
|
||||||
|
@ -22,7 +25,9 @@ namespace Misc::StringUtils
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T const * argument(std::basic_string_view<T> const & value) noexcept
|
T const * argument(std::basic_string_view<T> const & value) noexcept
|
||||||
{
|
{
|
||||||
return value.data();
|
// TODO: switch to a format function that doesn't require null termination
|
||||||
|
auto& inserted = mMemorySafety.emplace_back(value);
|
||||||
|
return inserted.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -30,7 +35,7 @@ namespace Misc::StringUtils
|
||||||
{
|
{
|
||||||
return value.c_str();
|
return value.c_str();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Requires some C++11 features:
|
// Requires some C++11 features:
|
||||||
// 1. std::string needs to be contiguous
|
// 1. std::string needs to be contiguous
|
||||||
|
@ -39,21 +44,22 @@ namespace Misc::StringUtils
|
||||||
template <typename ... Args>
|
template <typename ... Args>
|
||||||
std::string format(const char* fmt, Args const & ... args)
|
std::string format(const char* fmt, Args const & ... args)
|
||||||
{
|
{
|
||||||
const int size = std::snprintf(nullptr, 0, fmt, Details::argument(args) ...);
|
Details details;
|
||||||
|
const int size = std::snprintf(nullptr, 0, fmt, details.argument(args) ...);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
throw std::runtime_error(std::string("Failed to compute resulting string size: ") + std::strerror(errno));
|
throw std::runtime_error(std::string("Failed to compute resulting string size: ") + std::strerror(errno));
|
||||||
// Note: sprintf also writes a trailing null character. We should remove it.
|
// Note: sprintf also writes a trailing null character. We should remove it.
|
||||||
std::string ret(static_cast<std::size_t>(size) + 1, '\0');
|
std::string ret(static_cast<std::size_t>(size) + 1, '\0');
|
||||||
if (std::sprintf(ret.data(), fmt, Details::argument(args) ...) < 0)
|
if (std::sprintf(ret.data(), fmt, details.argument(args) ...) < 0)
|
||||||
throw std::runtime_error(std::string("Failed to format string: ") + std::strerror(errno));
|
throw std::runtime_error(std::string("Failed to format string: ") + std::strerror(errno));
|
||||||
ret.erase(static_cast<std::size_t>(size));
|
ret.erase(static_cast<std::size_t>(size));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ... Args>
|
template <typename ... Args>
|
||||||
std::string format(std::string_view fmt, Args const & ... args)
|
std::string format(const std::string& fmt, Args const & ... args)
|
||||||
{
|
{
|
||||||
return format(fmt.data(), args ...);
|
return format(fmt.c_str(), args ...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue