aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-06-01 23:22:43 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-06-01 23:22:43 +0300
commita32378a9aedd61c51166432ecd26a6a5dd405ebb (patch)
tree39c11d2f1a852fce90b4b3dd3d9b35a0cde2bd61
parent1d53d806a603044a08e359369eec72b02ba884e3 (diff)
Treat CR specially by manifest serializer
-rw-r--r--libbutl/char-scanner.cxx2
-rw-r--r--libbutl/manifest-serializer.cxx14
-rw-r--r--tests/manifest-serializer/driver.cxx11
3 files changed, 22 insertions, 5 deletions
diff --git a/libbutl/char-scanner.cxx b/libbutl/char-scanner.cxx
index a2baaf3..a97ed48 100644
--- a/libbutl/char-scanner.cxx
+++ b/libbutl/char-scanner.cxx
@@ -34,7 +34,7 @@ namespace butl
if (v == xchar::traits_type::eof ())
eos_ = true;
- else if (crlf_ && v == 0x0D)
+ else if (crlf_ && v == '\r')
{
get_ ();
int_type v1 (peek_ ());
diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx
index 35f2d72..adb7f13 100644
--- a/libbutl/manifest-serializer.cxx
+++ b/libbutl/manifest-serializer.cxx
@@ -66,6 +66,11 @@ namespace butl
{
os_ << ' ';
+ // Consider both \r and \n characters as line separators, and the
+ // \r\n characters sequence as a single line separator.
+ //
+ auto nl = [&v] (size_t p = 0) {return v.find_first_of ("\r\n", p);};
+
// Use the multi-line mode in any of the following cases:
//
// - name is too long (say longer than 37 (78/2 - 2) characters;
@@ -74,8 +79,7 @@ namespace butl
// - value contains newlines
// - value contains leading/trailing whitespaces
//
- if (n.size () > 37 ||
- v.find ('\n') != string::npos ||
+ if (n.size () > 37 || nl () != string::npos ||
v.front () == ' ' || v.front () == '\t' ||
v.back () == ' ' || v.back () == '\t')
{
@@ -83,7 +87,7 @@ namespace butl
// Chunk the value into fragments separated by newlines.
//
- for (size_t i (0), p (v.find ('\n')); ; p = v.find ('\n', i))
+ for (size_t i (0), p (nl ()); ; p = nl (i))
{
if (p == string::npos)
{
@@ -95,7 +99,8 @@ namespace butl
write_value (0, v.c_str () + i, p - i);
os_ << endl;
- i = p + 1;
+
+ i = p + (v[p] == '\r' && v[p + 1] == '\n' ? 2 : 1);
}
os_ << endl << "\\"; // Multi-line mode terminator.
@@ -140,6 +145,7 @@ namespace butl
{
case ' ':
case '\t':
+ case '\r':
case '\n': throw serialization (name_, "name contains whitespace");
case ':': throw serialization (name_, "name contains ':'");
default: break;
diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx
index 3a8aef8..69c1c71 100644
--- a/tests/manifest-serializer/driver.cxx
+++ b/tests/manifest-serializer/driver.cxx
@@ -184,6 +184,17 @@ main ()
assert (test ({{"","1"},{"a"," x "},{"",""},{"",""}},
": 1\na: \\\n x \n\\\n"));
+ // Carriage return character.
+ //
+ assert (test ({{"","1"},{"a","x\ry"},{"",""},{"",""}},
+ ": 1\na: \\\nx\ny\n\\\n"));
+ assert (test ({{"","1"},{"a","x\r"},{"",""},{"",""}},
+ ": 1\na: \\\nx\n\n\\\n"));
+ assert (test ({{"","1"},{"a","x\r\ny"},{"",""},{"",""}},
+ ": 1\na: \\\nx\ny\n\\\n"));
+ assert (test ({{"","1"},{"a","x\r\n"},{"",""},{"",""}},
+ ": 1\na: \\\nx\n\n\\\n"));
+
// Extra three x's are for the leading name part ("a: ") that we
// don't have.
//