Commit b5eb6ed9 by zhanyong.wan

Makes gtest print string literals correctly when it contains \x escape…

Makes gtest print string literals correctly when it contains \x escape sequences. Contributed by Yair Chuchem.
parent 42bf979c
......@@ -1462,6 +1462,9 @@ inline bool IsSpace(char ch) {
inline bool IsUpper(char ch) {
return isupper(static_cast<unsigned char>(ch)) != 0;
}
inline bool IsXDigit(char ch) {
return isxdigit(static_cast<unsigned char>(ch)) != 0;
}
inline char ToLower(char ch) {
return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
......
......@@ -194,25 +194,25 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
return kSpecialEscape;
}
// Prints a char as if it's part of a string literal, escaping it when
// necessary.
static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
break;
return kAsIs;
case L'"':
*os << "\\\"";
break;
return kSpecialEscape;
default:
PrintAsCharLiteralTo<wchar_t>(c, os);
return PrintAsCharLiteralTo<wchar_t>(c, os);
}
}
// Prints a char as if it's part of a string literal, escaping it when
// necessary.
static void PrintAsNarrowStringLiteralTo(char c, ostream* os) {
PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
}
// Prints a wide or narrow character c and its code. '\0' is printed
......@@ -263,8 +263,16 @@ void PrintTo(wchar_t wc, ostream* os) {
// and may not be null-terminated.
static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
*os << "\"";
bool is_previous_hex = false;
for (size_t index = 0; index < len; ++index) {
PrintAsNarrowStringLiteralTo(begin[index], os);
const char cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) {
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
*os << "\" \"";
}
is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
}
*os << "\"";
}
......@@ -280,8 +288,17 @@ void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
ostream* os) {
*os << "L\"";
bool is_previous_hex = false;
for (size_t index = 0; index < len; ++index) {
PrintAsWideStringLiteralTo(begin[index], os);
const wchar_t cur = begin[index];
if (is_previous_hex && 0 <= cur && cur < 128 &&
IsXDigit(static_cast<char>(cur))) {
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
*os << "\" L\"";
}
is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
}
*os << "\"";
}
......
......@@ -658,6 +658,20 @@ TEST(PrintStringTest, StringInStdNamespace) {
Print(str));
}
TEST(PrintStringTest, StringAmbiguousHex) {
// "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
// '\x6', '\x6B', or '\x6BA'.
// a hex escaping sequence following by a decimal digit
EXPECT_EQ("\"0\\x12\" \"3\"", Print(::std::string("0\x12" "3")));
// a hex escaping sequence following by a hex digit (lower-case)
EXPECT_EQ("\"mm\\x6\" \"bananas\"", Print(::std::string("mm\x6" "bananas")));
// a hex escaping sequence following by a hex digit (upper-case)
EXPECT_EQ("\"NOM\\x6\" \"BANANA\"", Print(::std::string("NOM\x6" "BANANA")));
// a hex escaping sequence following by a non-xdigit
EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
}
// Tests printing ::wstring and ::std::wstring.
#if GTEST_HAS_GLOBAL_WSTRING
......@@ -680,6 +694,16 @@ TEST(PrintWideStringTest, StringInStdNamespace) {
"\\xD3\\x576\\x8D3\\xC74D a\\0\"",
Print(str));
}
TEST(PrintWideStringTest, StringAmbiguousHex) {
// same for wide strings.
EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12" L"3")));
EXPECT_EQ("L\"mm\\x6\" L\"bananas\"",
Print(::std::wstring(L"mm\x6" L"bananas")));
EXPECT_EQ("L\"NOM\\x6\" L\"BANANA\"",
Print(::std::wstring(L"NOM\x6" L"BANANA")));
EXPECT_EQ("L\"!\\x5-!\"", Print(::std::wstring(L"!\x5-!")));
}
#endif // GTEST_HAS_STD_WSTRING
// Tests printing types that support generic streaming (i.e. streaming
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment