mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-23 03:47:34 -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(
|
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)
|
switch (placeholder)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ namespace Compiler
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void visitedPlaceholder(
|
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 {}
|
void visitedCharacter(char c) override {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
#define INTERPRETER_MISCOPCODES_H_INCLUDED
|
#define INTERPRETER_MISCOPCODES_H_INCLUDED
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <format>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -23,78 +22,79 @@ namespace Interpreter
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void visitedPlaceholder(
|
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;
|
std::string formatString;
|
||||||
out.fill(padding);
|
|
||||||
if (width != -1)
|
|
||||||
out.width(width);
|
|
||||||
if (precision != -1)
|
|
||||||
out.precision(precision);
|
|
||||||
|
|
||||||
switch (placeholder)
|
if (placeholder == StringPlaceholder)
|
||||||
{
|
|
||||||
case StringPlaceholder:
|
|
||||||
{
|
{
|
||||||
int index = mRuntime[0].mInteger;
|
int index = mRuntime[0].mInteger;
|
||||||
mRuntime.pop();
|
mRuntime.pop();
|
||||||
|
|
||||||
out << mRuntime.getStringLiteral(index);
|
std::string_view value = mRuntime.getStringLiteral(index);
|
||||||
mFormattedMessage += out.str();
|
if (precision >= 0)
|
||||||
|
value = value.substr(0, static_cast<std::size_t>(precision));
|
||||||
|
if (width < 0)
|
||||||
|
mFormattedMessage += value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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 IntegerPlaceholder:
|
|
||||||
{
|
|
||||||
Type_Integer value = mRuntime[0].mInteger;
|
|
||||||
mRuntime.pop();
|
|
||||||
|
|
||||||
out << value;
|
|
||||||
mFormattedMessage += out.str();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 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
|
else
|
||||||
{
|
{
|
||||||
out << std::scientific << value;
|
formatString = "{:";
|
||||||
mFormattedMessage += out.str();
|
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();
|
||||||
|
appendMessage(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Type_Integer value = mRuntime[0].mInteger;
|
||||||
|
mRuntime.pop();
|
||||||
|
appendMessage(value);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,18 +27,34 @@ namespace Misc
|
|||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < m.size(); ++i)
|
for (std::size_t i = 0; i < m.size(); ++i)
|
||||||
{
|
{
|
||||||
|
if (m[i] != '%')
|
||||||
|
{
|
||||||
|
visitedCharacter(m[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (++i == m.size())
|
||||||
|
break;
|
||||||
if (m[i] == '%')
|
if (m[i] == '%')
|
||||||
{
|
{
|
||||||
if (++i < m.size())
|
|
||||||
{
|
|
||||||
if (m[i] == '%')
|
|
||||||
visitedCharacter('%');
|
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
|
else
|
||||||
{
|
break;
|
||||||
char pad = ' ';
|
|
||||||
if (m[i] == '0' || m[i] == ' ')
|
|
||||||
{
|
|
||||||
pad = m[i];
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,30 +72,27 @@ namespace Misc
|
|||||||
if (i < m.size())
|
if (i < m.size())
|
||||||
{
|
{
|
||||||
if (m[i] == 'S' || m[i] == 's')
|
if (m[i] == 'S' || m[i] == 's')
|
||||||
visitedPlaceholder(StringPlaceholder, pad, width, precision, Notation::Fixed);
|
visitedPlaceholder(StringPlaceholder, flags, width, precision, Notation::Fixed);
|
||||||
else if (m[i] == 'd' || m[i] == 'i')
|
else if (m[i] == 'd' || m[i] == 'i')
|
||||||
visitedPlaceholder(IntegerPlaceholder, pad, width, precision, Notation::Fixed);
|
visitedPlaceholder(IntegerPlaceholder, flags, width, precision, Notation::Fixed);
|
||||||
else if (m[i] == 'f' || m[i] == 'F')
|
else if (m[i] == 'f' || m[i] == 'F')
|
||||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Fixed);
|
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::Fixed);
|
||||||
else if (m[i] == 'e' || m[i] == 'E')
|
else if (m[i] == 'e')
|
||||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Scientific);
|
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::ScientificLower);
|
||||||
else if (m[i] == 'g' || m[i] == 'G')
|
else if (m[i] == 'E')
|
||||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::Shortest);
|
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')
|
else if (m[i] == 'a')
|
||||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexLower);
|
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::HexLower);
|
||||||
else if (m[i] == 'A')
|
else if (m[i] == 'A')
|
||||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision, Notation::HexUpper);
|
visitedPlaceholder(FloatPlaceholder, flags, width, precision, Notation::HexUpper);
|
||||||
else
|
else
|
||||||
visitedCharacter(m[i]);
|
visitedCharacter(m[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
visitedCharacter(m[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,17 +15,28 @@ namespace Misc
|
|||||||
FloatPlaceholder
|
FloatPlaceholder
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Notation
|
enum Flags
|
||||||
{
|
{
|
||||||
Fixed,
|
None = 0,
|
||||||
Scientific,
|
PositiveSpace = 1,
|
||||||
Shortest,
|
PositiveSign = 2,
|
||||||
HexUpper,
|
AlignLeft = 4,
|
||||||
HexLower
|
PrependZero = 8,
|
||||||
|
AlternateForm = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void visitedPlaceholder(
|
enum class Notation : char
|
||||||
Placeholder placeholder, char padding, int width, int precision, Notation notation)
|
{
|
||||||
|
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;
|
= 0;
|
||||||
virtual void visitedCharacter(char c) = 0;
|
virtual void visitedCharacter(char c) = 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user