1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[YAML] Quote multiline string scalars

Summary:
Otherwise, the YAML parser breaks when trying to read them back in
'key: multiline_string_value' cases.

This patch fixes a problem when serializing structs which contain multi-line strings.
E.g., if we try to serialize  the following struct
```
{ "key1": "first line\nsecond line",
  "key2": "another string" }`
```

Before this patch, we got the YAML output that failed to parse:
```
key1: first line
second line
key2: another string
```

After the patch, we get:
```
key1: 'first line
second line'
key2: another string
```

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D47468

llvm-svn: 333527
This commit is contained in:
Ilya Biryukov 2018-05-30 10:40:11 +00:00
parent a00817e988
commit 5f75f2e3a7
2 changed files with 73 additions and 2 deletions

View File

@ -540,11 +540,14 @@ inline QuotingType needsQuotes(StringRef S) {
case '.':
case ',':
case ' ':
// TAB (0x9), LF (0xA), CR (0xD) and NEL (0x85) are allowed.
// TAB (0x9) is allowed in unquoted strings.
case 0x9:
continue;
// LF(0xA) and CR(0xD) may delimit values and so require at least single
// quotes.
case 0xA:
case 0xD:
case 0x85:
MaxQuotingNeeded = QuotingType::Single;
continue;
// DEL (0x7F) are excluded from the allowed character range.
case 0x7F:

View File

@ -13,6 +13,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/YAMLTraits.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using llvm::yaml::Input;
@ -25,6 +26,7 @@ using llvm::yaml::Hex8;
using llvm::yaml::Hex16;
using llvm::yaml::Hex32;
using llvm::yaml::Hex64;
using ::testing::StartsWith;
@ -249,6 +251,72 @@ TEST(YAMLIO, TestGivenFilename) {
EXPECT_TRUE(!!yin.error());
}
struct WithStringField {
std::string str1;
std::string str2;
std::string str3;
};
namespace llvm {
namespace yaml {
template <> struct MappingTraits<WithStringField> {
static void mapping(IO &io, WithStringField &fb) {
io.mapRequired("str1", fb.str1);
io.mapRequired("str2", fb.str2);
io.mapRequired("str3", fb.str3);
}
};
} // namespace yaml
} // namespace llvm
TEST(YAMLIO, MultilineStrings) {
WithStringField Original;
Original.str1 = "a multiline string\nfoobarbaz";
Original.str2 = "another one\rfoobarbaz";
Original.str3 = "a one-line string";
std::string Serialized;
{
llvm::raw_string_ostream OS(Serialized);
Output YOut(OS);
YOut << Original;
}
auto Expected = "---\n"
"str1: 'a multiline string\n"
"foobarbaz'\n"
"str2: 'another one\r"
"foobarbaz'\n"
"str3: a one-line string\n"
"...\n";
ASSERT_EQ(Serialized, Expected);
// Also check it parses back without the errors.
WithStringField Deserialized;
{
Input YIn(Serialized);
YIn >> Deserialized;
ASSERT_FALSE(YIn.error())
<< "Parsing error occurred during deserialization. Serialized string:\n"
<< Serialized;
}
EXPECT_EQ(Original.str1, Deserialized.str1);
EXPECT_EQ(Original.str2, Deserialized.str2);
EXPECT_EQ(Original.str3, Deserialized.str3);
}
TEST(YAMLIO, NoQuotesForTab) {
WithStringField WithTab;
WithTab.str1 = "aba\tcaba";
std::string Serialized;
{
llvm::raw_string_ostream OS(Serialized);
Output YOut(OS);
YOut << WithTab;
}
auto ExpectedPrefix = "---\n"
"str1: aba\tcaba\n";
EXPECT_THAT(Serialized, StartsWith(ExpectedPrefix));
}
//===----------------------------------------------------------------------===//
// Test built-in types