forked from OSchip/llvm-project
[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:
parent
7a350207ae
commit
5413510e32
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue