From 3da13703991d05ab97639e7db52a92846e68f31a Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 2 May 2017 00:14:47 +0300 Subject: Fix manifest serializer not to break line after backslash --- libbutl/manifest-serializer.cxx | 66 +++++++++++++++++++++--------------- tests/manifest-serializer/driver.cxx | 11 ++++++ 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx index b152882..96661df 100644 --- a/libbutl/manifest-serializer.cxx +++ b/libbutl/manifest-serializer.cxx @@ -158,49 +158,59 @@ namespace butl // for (const char* e (s + n); s != e; s++, cl++) { + char pc (c); c = *s; bool br (false); // Break the line. - // If this is a whitespace, see if it's a good place to break the - // line. + // Note that even the "hard" break (see below) is not that hard when it + // comes to breaking the line right after the backslash. Doing so would + // inject the redundant newline character, as the line-terminating + // backslash would be escaped. So we delay breaking till the next + // non-backslash character. // - if (c == ' ' || c == '\t') + if (pc != '\\') { - // Find the next whitespace (or the end) and see if it is a better - // place. + // If this is a whitespace, see if it's a good place to break the + // line. // - for (const char* w (s + 1); ; w++) + if (c == ' ' || c == '\t') { - if (w == e || *w == ' ' || *w == '\t') + // Find the next whitespace (or the end) and see if it is a better + // place. + // + for (const char* w (s + 1); ; w++) { - // Is this whitespace past where we need to break? Also see - // below the "hard" break case for why we use 78 at the end. - // - if (cl + static_cast (w - s) > (w != e ? 77 : 78)) + if (w == e || *w == ' ' || *w == '\t') { - // Only break if this whitespace is close enough to - // the end of the line. + // Is this whitespace past where we need to break? Also see + // below the "hard" break case for why we use 78 at the end. // - br = (cl > 57); - } + if (cl + static_cast (w - s) > (w != e ? 77 : 78)) + { + // Only break if this whitespace is close enough to + // the end of the line. + // + br = (cl > 57); + } - break; + break; + } } } - } - // Do we have to do a "hard" break (i.e., without a whitespace)? - // If there is just one character left, then instead of writing - // '\' and then the character on the next line, we might as well - // write it on this line. - // - if (cl == (s + 1 != e ? 77 : 78)) - br = true; + // Do we have to do a "hard" break (i.e., without a whitespace)? + // If there is just one character left, then instead of writing + // '\' and then the character on the next line, we might as well + // write it on this line. + // + if (cl >= (s + 1 != e ? 77 : 78)) + br = true; - if (br) - { - os_ << '\\' << endl; - cl = 0; + if (br) + { + os_ << '\\' << endl; + cl = 0; + } } os_ << c; diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx index 147ce48..d148f12 100644 --- a/tests/manifest-serializer/driver.cxx +++ b/tests/manifest-serializer/driver.cxx @@ -147,10 +147,21 @@ main () " Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); + // Hard break after the backslash/delayed hard break. + // + string l5 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\" + "Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + string e5 ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\Y\\\n" + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + assert (test ({{"","1"},{"a",l1},{"",""},{"",""}}, ": 1\na: " + e1 + "\n")); assert (test ({{"","1"},{"a",l2},{"",""},{"",""}}, ": 1\na: " + e2 + "\n")); assert (test ({{"","1"},{"a",l3},{"",""},{"",""}}, ": 1\na: " + e3 + "\n")); assert (test ({{"","1"},{"a",l4},{"",""},{"",""}}, ": 1\na: " + e4 + "\n")); + assert (test ({{"","1"},{"a",l5},{"",""},{"",""}}, ": 1\na: " + e5 + "\n")); // Multi-line value. -- cgit v1.1