mirror of
https://github.com/shadps4-emu/ext-fmt.git
synced 2024-11-24 10:19:46 +00:00
Implement an escape mechanism.
This commit is contained in:
parent
6caa750a00
commit
31a507034e
23
format.cc
23
format.cc
@ -23,9 +23,15 @@ enum { PLUS_FLAG = 1, ZERO_FLAG = 2, HEX_PREFIX_FLAG = 4 };
|
||||
// FormatError reporting unmatched '{'. The idea is that unmatched '{'
|
||||
// should override other errors.
|
||||
void ReportError(const char *s, const std::string &message) {
|
||||
while (*s && *s != '}')
|
||||
++s;
|
||||
throw fmt::FormatError(*s ? message : std::string("unmatched '{' in format"));
|
||||
for (int num_open_braces = 1; *s; ++s) {
|
||||
if (*s == '{') {
|
||||
++num_open_braces;
|
||||
} else if (*s == '}') {
|
||||
if (--num_open_braces == 0)
|
||||
throw fmt::FormatError(message);
|
||||
}
|
||||
}
|
||||
throw fmt::FormatError("unmatched '{' in format");
|
||||
}
|
||||
|
||||
void ReportUnknownType(char code, const char *type) {
|
||||
@ -225,8 +231,15 @@ void fmt::Formatter::Format() {
|
||||
const char *start = format_;
|
||||
const char *s = start;
|
||||
while (*s) {
|
||||
if (*s++ != '{') continue;
|
||||
// TODO: handle escape sequence
|
||||
char c = *s++;
|
||||
if (c != '{' && c != '}') continue;
|
||||
if (*s == c) {
|
||||
buffer_.insert(buffer_.end(), start, s);
|
||||
start = ++s;
|
||||
continue;
|
||||
}
|
||||
if (c == '}')
|
||||
throw FormatError("unmatched '}' in format");
|
||||
buffer_.insert(buffer_.end(), start, s - 1);
|
||||
|
||||
// Parse argument index.
|
||||
|
25
format.h
25
format.h
@ -78,7 +78,7 @@ class Formatter {
|
||||
: type(CUSTOM), custom_value(value), format(f) {}
|
||||
};
|
||||
|
||||
std::vector<Arg> args_;
|
||||
std::vector<Arg> args_; // Format arguments.
|
||||
|
||||
const char *format_; // Format string.
|
||||
|
||||
@ -94,7 +94,7 @@ class Formatter {
|
||||
template <typename T>
|
||||
void FormatInt(T value, unsigned flags, int width, char type);
|
||||
|
||||
// Formats a floating point number.
|
||||
// Formats a floating point number (double or long double).
|
||||
template <typename T>
|
||||
void FormatDouble(
|
||||
T value, unsigned flags, int width, int precision, char type);
|
||||
@ -127,6 +127,16 @@ class ArgFormatter {
|
||||
private:
|
||||
friend class Formatter;
|
||||
|
||||
// This method is private to disallow formatting of arbitrary pointers.
|
||||
// If you want to output a pointer cast it to void*. Do not implement!
|
||||
template <typename T>
|
||||
ArgFormatter &operator<<(const T *value);
|
||||
|
||||
// This method is private to disallow formatting of wide characters.
|
||||
// If you want to output a wide character cast it to integer type.
|
||||
// Do not implement!
|
||||
ArgFormatter &operator<<(wchar_t value);
|
||||
|
||||
protected:
|
||||
mutable Formatter *formatter_;
|
||||
|
||||
@ -211,17 +221,6 @@ class ArgFormatter {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// This method contains a deliberate error to disallow formatting
|
||||
// arbitrary pointers. If you want to output a pointer cast it to void*.
|
||||
template <typename T>
|
||||
ArgFormatter &operator<<(const T *value) {
|
||||
"Formatting arbitrary pointers is not allowed" = value;
|
||||
}
|
||||
|
||||
// This method is not implemented intentionally to disallow formatting
|
||||
// wide characters.
|
||||
ArgFormatter &operator<<(wchar_t value);
|
||||
|
||||
template <typename T>
|
||||
ArgFormatter &operator<<(T *value) {
|
||||
const T *const_value = value;
|
||||
|
@ -66,8 +66,28 @@ class TestString {
|
||||
}
|
||||
};
|
||||
|
||||
TEST(FormatterTest, Escape) {
|
||||
EXPECT_EQ("{", str(Format("{{")));
|
||||
EXPECT_EQ("before {", str(Format("before {{")));
|
||||
EXPECT_EQ("{ after", str(Format("{{ after")));
|
||||
EXPECT_EQ("before { after", str(Format("before {{ after")));
|
||||
|
||||
EXPECT_EQ("}", str(Format("}}")));
|
||||
EXPECT_EQ("before }", str(Format("before }}")));
|
||||
EXPECT_EQ("} after", str(Format("}} after")));
|
||||
EXPECT_EQ("before } after", str(Format("before }} after")));
|
||||
|
||||
EXPECT_EQ("{}", str(Format("{{}}")));
|
||||
EXPECT_EQ("{42}", str(Format("{{{0}}}") << 42));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, UnmatchedBraces) {
|
||||
EXPECT_THROW_MSG(Format("{"), FormatError, "unmatched '{' in format");
|
||||
EXPECT_THROW_MSG(Format("}"), FormatError, "unmatched '}' in format");
|
||||
EXPECT_THROW_MSG(Format("{0{}"), FormatError, "unmatched '{' in format");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, NoArgs) {
|
||||
EXPECT_EQ("abracadabra", str(Format("{0}{1}{0}") << "abra" << "cad"));
|
||||
EXPECT_EQ("test", str(Format("test")));
|
||||
}
|
||||
|
||||
@ -77,7 +97,8 @@ TEST(FormatterTest, ArgsInDifferentPositions) {
|
||||
EXPECT_EQ("42 after", str(Format("{0} after") << 42));
|
||||
EXPECT_EQ("before 42 after", str(Format("before {0} after") << 42));
|
||||
EXPECT_EQ("answer = 42", str(Format("{0} = {1}") << "answer" << 42));
|
||||
EXPECT_EQ("42 is the answer", str(Format("{1} is the {0}") << "answer" << 42));
|
||||
EXPECT_EQ("42 is the answer",
|
||||
str(Format("{1} is the {0}") << "answer" << 42));
|
||||
EXPECT_EQ("abracadabra", str(Format("{0}{1}{0}") << "abra" << "cad"));
|
||||
}
|
||||
|
||||
@ -424,5 +445,3 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
|
||||
<< 1.234 << 42 << 3.13 << "str"
|
||||
<< reinterpret_cast<void*>(1000) << 'X'));
|
||||
}
|
||||
|
||||
// TODO: more tests
|
||||
|
Loading…
Reference in New Issue
Block a user