From a16982956c5e87d9b2f238522d902df177ece98e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 6 Apr 2019 23:47:48 +0300 Subject: Add support for manifest_serializer long lines mode --- libbutl/manifest-rewriter.cxx | 7 ++++--- libbutl/manifest-rewriter.mxx | 6 +++++- libbutl/manifest-serializer.cxx | 12 +++++++++--- libbutl/manifest-serializer.mxx | 12 +++++++++++- tests/manifest-serializer/driver.cxx | 30 +++++++++++++++++++++++++----- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/libbutl/manifest-rewriter.cxx b/libbutl/manifest-rewriter.cxx index 2be53f1..e5b4eae 100644 --- a/libbutl/manifest-rewriter.cxx +++ b/libbutl/manifest-rewriter.cxx @@ -41,8 +41,9 @@ using namespace std; namespace butl { manifest_rewriter:: - manifest_rewriter (path p) + manifest_rewriter (path p, bool long_lines) : path_ (move (p)), + long_lines_ (long_lines), fd_ (fdopen (path_, fdopen_mode::in | fdopen_mode::out | @@ -99,7 +100,7 @@ namespace butl { os << ' '; - manifest_serializer s (os, path_.string ()); + manifest_serializer s (os, path_.string (), long_lines_); s.write_value (nv.value, static_cast (nv.colon_pos - nv.start_pos + 2)); @@ -127,7 +128,7 @@ namespace butl ofdstream os (move (fd_)); os << '\n'; - manifest_serializer s (os, path_.string ()); + manifest_serializer s (os, path_.string (), long_lines_); s.write_name (nv.name); os << ':'; diff --git a/libbutl/manifest-rewriter.mxx b/libbutl/manifest-rewriter.mxx index 6cba682..8ad22b3 100644 --- a/libbutl/manifest-rewriter.mxx +++ b/libbutl/manifest-rewriter.mxx @@ -50,7 +50,10 @@ LIBBUTL_MODEXPORT namespace butl class LIBBUTL_SYMEXPORT manifest_rewriter { public: - manifest_rewriter (path); + // Unless long_lines is true, break lines in values (see + // manifest_serializer for details). + // + manifest_rewriter (path, bool long_lines = false); // Replace the existing value at the specified position (specifically, // between colon_pos and end_pos) with the specified new value. The new @@ -70,6 +73,7 @@ LIBBUTL_MODEXPORT namespace butl private: path path_; + bool long_lines_; auto_fd fd_; }; } diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx index 2098551..059c374 100644 --- a/libbutl/manifest-serializer.cxx +++ b/libbutl/manifest-serializer.cxx @@ -182,7 +182,6 @@ namespace butl { char pc (c); c = *s; - bool br (false); // 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 @@ -190,8 +189,10 @@ namespace butl // backslash would be escaped. So we delay breaking till the next // non-backslash character. // - if (pc != '\\') + if (pc != '\\' && !long_lines_) { + bool br (false); // Break the line. + // If this is a whitespace, see if it's a good place to break the // line. // @@ -238,7 +239,7 @@ namespace butl os_ << c; } - // What comes next is always a newline. I the last character that + // What comes next is always a newline. If the last character that // we have written is a backslash, escape it. // if (c == '\\') @@ -261,6 +262,11 @@ namespace butl // - value contains newlines // - value contains leading/trailing whitespaces // + // Should we use the multi-line mode for large column offsets if the long + // lines flag is set? Probably yes, as this improves the manifest + // readability, still allowing the user to easily copy the value which + // seems to be the main reason for using the flag. + // if (cl > 39 || nl () != string::npos || v.front () == ' ' || v.front () == '\t' || v.back () == ' ' || v.back () == '\t') diff --git a/libbutl/manifest-serializer.mxx b/libbutl/manifest-serializer.mxx index 7df78d5..1b3ace8 100644 --- a/libbutl/manifest-serializer.mxx +++ b/libbutl/manifest-serializer.mxx @@ -56,10 +56,19 @@ LIBBUTL_MODEXPORT namespace butl using filter_function = bool (const std::string& name, const std::string& value); + // Unless long_lines is true, break lines in values (including multi-line) + // so that their length does not exceed 78 characters (including '\n'). + // manifest_serializer (std::ostream& os, const std::string& name, + bool long_lines = false, std::function filter = {}) - : os_ (os), name_ (name), filter_ (std::move (filter)) {} + : os_ (os), + name_ (name), + long_lines_ (long_lines), + filter_ (std::move (filter)) + { + } const std::string& name () const {return name_;} @@ -124,6 +133,7 @@ LIBBUTL_MODEXPORT namespace butl private: std::ostream& os_; const std::string name_; + bool long_lines_; const std::function filter_; }; } diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx index d6e538d..4cddb57 100644 --- a/tests/manifest-serializer/driver.cxx +++ b/tests/manifest-serializer/driver.cxx @@ -32,6 +32,7 @@ using pairs = vector>; static bool test (const pairs& manifest, const string& expected, + bool long_lines = false, manifest_serializer::filter_function f = {}); static bool @@ -178,7 +179,6 @@ main () assert (test ({{"","1"},{"a",l4},{"",""},{"",""}}, ": 1\na: " + e4 + "\n")); assert (test ({{"","1"},{"a",l5},{"",""},{"",""}}, ": 1\na: " + e5 + "\n")); - // Multi-line value. // string n ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); @@ -199,6 +199,20 @@ main () assert (test ({{"","1"},{"a"," x "},{"",""},{"",""}}, ": 1\na: \\\n x \n\\\n")); + // The long lines mode. + // + assert (test ({{"","1"},{"a",l1},{"",""},{"",""}}, + ": 1\na: " + l1 + "\n", + true /* long_lines */)); + + assert (test ({{"","1"},{"a", " abc\n" + l1 + "\ndef"},{"",""},{"",""}}, + ": 1\na: \\\n abc\n" + l1 + "\ndef\n\\\n", + true /* long_lines */)); + + assert (test ({{"","1"},{n,l1},{"",""},{"",""}}, + ": 1\n" + n + ": \\\n" + l1 + "\n\\\n", + true /* long_lines */)); + // Carriage return character. // assert (test ({{"","1"},{"a","x\ry"},{"",""},{"",""}}, @@ -241,15 +255,18 @@ main () // assert (test ({{"","1"},{"a","abc"},{"b","bca"},{"c","cab"},{"",""},{"",""}}, ": 1\na: abc\nc: cab\n", + false /* long_lines */, [] (const string& n, const string&) {return n != "b";})); } static string -serialize (const pairs& m, manifest_serializer::filter_function f = {}) +serialize (const pairs& m, + bool long_lines = false, + manifest_serializer::filter_function f = {}) { ostringstream os; os.exceptions (istream::failbit | istream::badbit); - manifest_serializer s (os, "", f); + manifest_serializer s (os, "", long_lines, f); for (const auto& p: m) { @@ -263,9 +280,12 @@ serialize (const pairs& m, manifest_serializer::filter_function f = {}) } static bool -test (const pairs& m, const string& e, manifest_serializer::filter_function f) +test (const pairs& m, + const string& e, + bool long_lines, + manifest_serializer::filter_function f) { - string r (serialize (m, f)); + string r (serialize (m, long_lines, f)); if (r != e) { -- cgit v1.1