mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-22 11:23:27 -04:00
Bring messagebox format parsing more in line with printf/vanilla
This commit is contained in:
parent
14d9be7885
commit
06ef34cbdf
@ -481,7 +481,7 @@ namespace Compiler
|
||||
}
|
||||
|
||||
void GetArgumentsFromMessageFormat::visitedPlaceholder(
|
||||
Placeholder placeholder, char /*padding*/, int /*width*/, int /*precision*/, Notation /*notation*/)
|
||||
Placeholder placeholder, int /*flags*/, int /*width*/, int /*precision*/, Notation /*notation*/)
|
||||
{
|
||||
switch (placeholder)
|
||||
{
|
||||
|
@ -88,7 +88,7 @@ namespace Compiler
|
||||
|
||||
protected:
|
||||
void visitedPlaceholder(
|
||||
Placeholder placeholder, char padding, int width, int precision, Notation notation) override;
|
||||
Placeholder placeholder, int flags, int width, int precision, Notation notation) override;
|
||||
void visitedCharacter(char c) override {}
|
||||
|
||||
public:
|
||||
|
@ -2,8 +2,7 @@
|
||||
#define INTERPRETER_MISCOPCODES_H_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -23,78 +22,79 @@ namespace Interpreter
|
||||
|
||||
protected:
|
||||
void visitedPlaceholder(
|
||||
Placeholder placeholder, char padding, int width, int precision, Notation notation) override
|
||||
Placeholder placeholder, int flags, int width, int precision, Notation notation) override
|
||||
{
|
||||
std::ostringstream out;
|
||||
out.fill(padding);
|
||||
if (width != -1)
|
||||
out.width(width);
|
||||
if (precision != -1)
|
||||
out.precision(precision);
|
||||
std::string formatString;
|
||||
|
||||
switch (placeholder)
|
||||
if (placeholder == StringPlaceholder)
|
||||
{
|
||||
case StringPlaceholder:
|
||||
{
|
||||
int index = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
int index = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
|
||||
out << mRuntime.getStringLiteral(index);
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
break;
|
||||
case IntegerPlaceholder:
|
||||
std::string_view value = mRuntime.getStringLiteral(index);
|
||||
if (precision >= 0)
|
||||
value = value.substr(0, static_cast<std::size_t>(precision));
|
||||
if (width < 0)
|
||||
mFormattedMessage += value;
|
||||
else
|
||||
{
|
||||
Type_Integer value = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
|
||||
out << value;
|
||||
mFormattedMessage += out.str();
|
||||
formatString = "{:";
|
||||
if (flags & PrependZero)
|
||||
formatString += '0';
|
||||
if (flags & AlignLeft)
|
||||
formatString += '<';
|
||||
else
|
||||
formatString += '>';
|
||||
formatString += "{}}";
|
||||
mFormattedMessage += std::vformat(formatString, std::make_format_args(value, width));
|
||||
}
|
||||
break;
|
||||
case FloatPlaceholder:
|
||||
}
|
||||
else
|
||||
{
|
||||
formatString = "{:";
|
||||
if (flags & AlignLeft)
|
||||
formatString += '<';
|
||||
if (flags & PositiveSign)
|
||||
formatString += '+';
|
||||
else if (flags & PositiveSpace)
|
||||
formatString += ' ';
|
||||
if (flags & AlternateForm)
|
||||
formatString += '#';
|
||||
if (flags & PrependZero)
|
||||
formatString += '0';
|
||||
if (width >= 0)
|
||||
formatString += "{}";
|
||||
if (placeholder == FloatPlaceholder)
|
||||
{
|
||||
if (precision >= 0)
|
||||
formatString += ".{}";
|
||||
formatString += static_cast<char>(notation);
|
||||
}
|
||||
else
|
||||
precision = -1;
|
||||
formatString += '}';
|
||||
const auto appendMessage = [&](auto value) {
|
||||
if (width >= 0 && precision >= 0)
|
||||
mFormattedMessage += std::vformat(formatString, std::make_format_args(value, width, precision));
|
||||
else if (width >= 0)
|
||||
mFormattedMessage += std::vformat(formatString, std::make_format_args(value, width));
|
||||
else if (precision >= 0)
|
||||
mFormattedMessage += std::vformat(formatString, std::make_format_args(value, precision));
|
||||
else
|
||||
mFormattedMessage += std::vformat(formatString, std::make_format_args(value));
|
||||
};
|
||||
if (placeholder == FloatPlaceholder)
|
||||
{
|
||||
float value = mRuntime[0].mFloat;
|
||||
mRuntime.pop();
|
||||
|
||||
if (notation == Notation::Fixed)
|
||||
{
|
||||
out << std::fixed << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
else if (notation == Notation::Shortest)
|
||||
{
|
||||
out << value;
|
||||
std::string standard = out.str();
|
||||
|
||||
out.str(std::string());
|
||||
out.clear();
|
||||
|
||||
out << std::scientific << value;
|
||||
std::string scientific = out.str();
|
||||
|
||||
mFormattedMessage += standard.length() < scientific.length() ? standard : scientific;
|
||||
}
|
||||
// TODO switch to std::format so the precision argument applies to these two
|
||||
else if (notation == Notation::HexLower)
|
||||
{
|
||||
out << std::hexfloat << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
else if (notation == Notation::HexUpper)
|
||||
{
|
||||
out << std::uppercase << std::hexfloat << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
out << std::scientific << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
appendMessage(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Type_Integer value = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
appendMessage(value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,58 +27,71 @@ namespace Misc
|
||||
{
|
||||
for (std::size_t i = 0; i < m.size(); ++i)
|
||||
{
|
||||
if (m[i] == '%')
|
||||
{
|
||||
if (++i < m.size())
|
||||
{
|
||||
if (m[i] == '%')
|
||||
visitedCharacter('%');
|
||||
else
|
||||
{
|
||||
char pad = ' ';
|
||||
if (m[i] == '0' || m[i] == ' ')
|
||||
{
|
||||
pad = m[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
int width = parseNumber(i, m, -1);
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
int precision = -1;
|
||||
if (m[i] == '.')
|
||||
{
|
||||
++i;
|
||||
precision = parseNumber(i, m, 0);
|
||||
}
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
if (m[i] == 'S' || m[i] == 's')
|
||||
visitedPlaceholder(StringPlaceholder, pad, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'd' || m[i] == 'i')
|
||||
visitedPlaceholder(IntegerPlaceholder, pad, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'f' || m[i] == 'F')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'e' || m[i] == 'E')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Scientific);
|
||||
else if (m[i] == 'g' || m[i] == 'G')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Shortest);
|
||||
else if (m[i] == 'a')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexLower);
|
||||
else if (m[i] == 'A')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexUpper);
|
||||
else
|
||||
visitedCharacter(m[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (m[i] != '%')
|
||||
{
|
||||
visitedCharacter(m[i]);
|
||||
continue;
|
||||
}
|
||||
if (++i == m.size())
|
||||
break;
|
||||
if (m[i] == '%')
|
||||
{
|
||||
visitedCharacter('%');
|
||||
continue;
|
||||
}
|
||||
|
||||
int flags = None;
|
||||
while (i < m.size())
|
||||
{
|
||||
if (m[i] == '-')
|
||||
flags |= AlignLeft;
|
||||
else if (m[i] == '+')
|
||||
flags |= PositiveSign;
|
||||
else if (m[i] == ' ')
|
||||
flags |= PositiveSpace;
|
||||
else if (m[i] == '0')
|
||||
flags |= PrependZero;
|
||||
else if (m[i] == '#')
|
||||
flags |= AlternateForm;
|
||||
else
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
|
||||
int width = parseNumber(i, m, -1);
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
int precision = -1;
|
||||
if (m[i] == '.')
|
||||
{
|
||||
++i;
|
||||
precision = parseNumber(i, m, 0);
|
||||
}
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
if (m[i] == 'S' || m[i] == 's')
|
||||
visitedPlaceholder(StringPlaceholder, flags, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'd' || m[i] == 'i')
|
||||
visitedPlaceholder(IntegerPlaceholder, flags, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'f' || m[i] == 'F')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::Fixed);
|
||||
else if (m[i] == 'e')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::ScientificLower);
|
||||
else if (m[i] == 'E')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::ScientificUpper);
|
||||
else if (m[i] == 'g')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::ShortestLower);
|
||||
else if (m[i] == 'G')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::ShortestUpper);
|
||||
else if (m[i] == 'a')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::HexLower);
|
||||
else if (m[i] == 'A')
|
||||
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::HexUpper);
|
||||
else
|
||||
visitedCharacter(m[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,17 +15,28 @@ namespace Misc
|
||||
FloatPlaceholder
|
||||
};
|
||||
|
||||
enum class Notation
|
||||
enum Flags
|
||||
{
|
||||
Fixed,
|
||||
Scientific,
|
||||
Shortest,
|
||||
HexUpper,
|
||||
HexLower
|
||||
None = 0,
|
||||
PositiveSpace = 1,
|
||||
PositiveSign = 2,
|
||||
AlignLeft = 4,
|
||||
PrependZero = 8,
|
||||
AlternateForm = 16
|
||||
};
|
||||
|
||||
virtual void visitedPlaceholder(
|
||||
Placeholder placeholder, char padding, int width, int precision, Notation notation)
|
||||
enum class Notation : char
|
||||
{
|
||||
Fixed = 'f',
|
||||
ScientificUpper = 'E',
|
||||
ScientificLower = 'e',
|
||||
ShortestUpper = 'G',
|
||||
ShortestLower = 'g',
|
||||
HexUpper = 'A',
|
||||
HexLower = 'a'
|
||||
};
|
||||
|
||||
virtual void visitedPlaceholder(Placeholder placeholder, int flags, int width, int precision, Notation notation)
|
||||
= 0;
|
||||
virtual void visitedCharacter(char c) = 0;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user