Improve handling of braces

This commit is contained in:
Ted John 2020-11-21 18:16:56 +00:00
parent 9173ec2111
commit ec03ce5317
5 changed files with 61 additions and 3 deletions

View file

@ -824,6 +824,13 @@ static void ttf_process_string_literal(rct_drawpixelinfo* dpi, const std::string
#endif // NO_TTF
}
static void ttf_process_string_codepoint(rct_drawpixelinfo* dpi, codepoint_t codepoint, text_draw_info* info)
{
char buffer[8]{};
utf8_write_codepoint(buffer, codepoint);
ttf_process_string_literal(dpi, buffer, info);
}
static void ttf_process_string(rct_drawpixelinfo* dpi, std::string_view text, text_draw_info* info)
{
FmtString fmt(text);
@ -833,6 +840,11 @@ static void ttf_process_string(rct_drawpixelinfo* dpi, std::string_view text, te
{
ttf_process_string_literal(dpi, token.text, info);
}
else if (token.IsCodepoint())
{
auto codepoint = token.GetCodepoint();
ttf_process_string_codepoint(dpi, codepoint, info);
}
else
{
ttf_process_format_code(dpi, token, info);

View file

@ -17,6 +17,7 @@ enum class FormatToken
{
Unknown,
Literal,
Escaped,
Newline,
NewlineSmall,

View file

@ -62,6 +62,21 @@ namespace OpenRCT2
return kind == FormatToken::Literal;
}
bool FmtString::token::IsCodepoint() const
{
return kind == FormatToken::Escaped;
}
codepoint_t FmtString::token::GetCodepoint() const
{
if (kind == FormatToken::Escaped)
{
// Assume text is only "{{" or "}}" for now
return text[0];
}
return 0;
}
FmtString::iterator::iterator(std::string_view s, size_t i)
: str(s)
, index(i)
@ -82,6 +97,14 @@ namespace OpenRCT2
{
i++;
}
else if (str[i] == '{' && i + 1 < str.size() && str[i + 1] == '{')
{
i += 2;
}
else if (str[i] == '}' && i + 1 < str.size() && str[i + 1] == '}')
{
i += 2;
}
else if (str[i] == '{' && i + 1 < str.size() && str[i + 1] != '{')
{
// Move to end brace
@ -130,7 +153,7 @@ namespace OpenRCT2
do
{
i++;
} while (i < str.size() && str[i] != '{' && str[i] != '\n' && str[i] != '\r');
} while (i < str.size() && str[i] != '{' && str[i] != '}' && str[i] != '\n' && str[i] != '\r');
}
current = CreateToken(i - index);
}
@ -148,7 +171,12 @@ namespace OpenRCT2
FmtString::token FmtString::iterator::CreateToken(size_t len)
{
std::string_view sztoken = str.substr(index, len);
if (sztoken.size() >= 2 && sztoken[0] == '{' && sztoken[1] != '{')
if (sztoken.size() >= 2 && ((sztoken[0] == '{' && sztoken[1] == '{') || (sztoken[0] == '}' && sztoken[1] == '}')))
{
return token(FormatToken::Escaped, sztoken);
}
else if (sztoken.size() >= 2 && sztoken[0] == '{' && sztoken[1] != '{')
{
auto kind = FormatTokenFromString(sztoken.substr(1, len - 2));
return token(kind, sztoken);

View file

@ -41,6 +41,8 @@ namespace OpenRCT2
token() = default;
token(FormatToken k, std::string_view s, uint32_t p = 0);
bool IsLiteral() const;
bool IsCodepoint() const;
codepoint_t GetCodepoint() const;
};
struct iterator

View file

@ -39,7 +39,20 @@ TEST_F(FmtStringTests, iteration)
actual += String::StdFormat("[%d:%s]", t.kind, std::string(t.text).c_str());
}
ASSERT_EQ("[28:{BLACK}][1:Guests: ][7:{INT32}]", actual);
ASSERT_EQ("[29:{BLACK}][1:Guests: ][8:{INT32}]", actual);
}
TEST_F(FmtStringTests, iteration_escaped)
{
std::string actual;
auto fmt = FmtString("This is an {{ESCAPED}} string.");
for (const auto& t : fmt)
{
actual += String::StdFormat("[%d:%s]", t.kind, std::string(t.text).c_str());
}
ASSERT_EQ("[1:This is an ][2:{{][1:ESCAPED][2:}}][1: string.]", actual);
}
TEST_F(FmtStringTests, without_format_tokens)
@ -60,6 +73,8 @@ protected:
gOpenRCT2NoGraphics = true;
_context = CreateContext();
ASSERT_TRUE(_context->Initialise());
language_open(LANGUAGE_ENGLISH_UK);
}
static void TearDownTestCase()