From 405dfa3e28ab71d4f6b5210faba0e3600070a0f3 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 23 Nov 2021 19:24:00 +0300 Subject: Add support for new-fashioned multi-line manifest value introducer --- libbutl/manifest-parser.cxx | 35 ++++++++++++++++- libbutl/manifest-parser.hxx | 4 +- libbutl/manifest-serializer.cxx | 3 ++ libbutl/manifest-serializer.hxx | 10 ++++- tests/manifest-roundtrip/buildfile | 3 +- tests/manifest-roundtrip/driver.cxx | 26 ++++++++++++- tests/manifest-roundtrip/manifest | 32 --------------- tests/manifest-roundtrip/testscript | 78 +++++++++++++++++++++++++++++++++++++ 8 files changed, 150 insertions(+), 41 deletions(-) delete mode 100644 tests/manifest-roundtrip/manifest create mode 100644 tests/manifest-roundtrip/testscript diff --git a/libbutl/manifest-parser.cxx b/libbutl/manifest-parser.cxx index 1cb0ec7..ae0d43d 100644 --- a/libbutl/manifest-parser.cxx +++ b/libbutl/manifest-parser.cxx @@ -222,7 +222,8 @@ namespace butl string& v (r.value); string::size_type n (0); // Size of last non-space character (simple mode). - // Detect the multi-line mode introducer. + // Detect the old-fashioned multi-line mode introducer (like in + // 'foo:\'). // bool ml (false); if (c == '\\') @@ -245,6 +246,38 @@ namespace butl unget (c); } + // Detect the new-fashioned multi-line mode introducer (like in + // 'foo:\'). + // + if (!ml && c == '\n') + { + get (); + xchar p1 (peek ()); + + if (p1 == '\\') + { + get (); + xchar p2 (peek ()); + + if (p2 == '\n') + { + get (); // Newline is not part of the value so skip it. + c = peek (); + ml = true; + } + else if (eos (p2)) + { + c = p2; // Set to EOF. + ml = true; + } + else + unget (p1); // Unget '\\'. Note: '\n' will be ungot below. + } + + if (!ml) + unget (c); // Unget '\n'. + } + // Multi-line value starts from the line that follows the name. // if (ml) diff --git a/libbutl/manifest-parser.hxx b/libbutl/manifest-parser.hxx index d53eb42..601fb2d 100644 --- a/libbutl/manifest-parser.hxx +++ b/libbutl/manifest-parser.hxx @@ -37,7 +37,7 @@ namespace butl }; class LIBBUTL_SYMEXPORT manifest_parser: - protected char_scanner + protected char_scanner { public: // The filter, if specified, is called by next() prior to returning the @@ -83,7 +83,7 @@ namespace butl split_comment (const std::string&); private: - using base = char_scanner; + using base = char_scanner; void parse_next (manifest_name_value&); diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx index 5875052..b0d0324 100644 --- a/libbutl/manifest-serializer.cxx +++ b/libbutl/manifest-serializer.cxx @@ -297,6 +297,9 @@ namespace butl v.back () == ' ' || v.back () == '\t') { + if (multiline_v2_) + os_ << endl; + os_ << "\\" << endl; // Multi-line mode introducer. // Chunk the value into fragments separated by newlines. diff --git a/libbutl/manifest-serializer.hxx b/libbutl/manifest-serializer.hxx index 43924e7..2159901 100644 --- a/libbutl/manifest-serializer.hxx +++ b/libbutl/manifest-serializer.hxx @@ -45,14 +45,19 @@ namespace butl // Unless long_lines is true, break lines in values (including multi-line) // so that their length does not exceed 78 codepoints (including '\n'). // + // Note that the multiline_v2 flag is temporary and should not be used + // except by the implementation for testing. + // manifest_serializer (std::ostream& os, const std::string& name, bool long_lines = false, - std::function filter = {}) + std::function filter = {}, + bool multiline_v2 = false) : os_ (os), name_ (name), long_lines_ (long_lines), - filter_ (std::move (filter)) + filter_ (std::move (filter)), + multiline_v2_ (multiline_v2) { } @@ -123,6 +128,7 @@ namespace butl const std::string name_; bool long_lines_; const std::function filter_; + bool multiline_v2_; }; // Serialize a manifest to a stream adding the leading format version pair diff --git a/tests/manifest-roundtrip/buildfile b/tests/manifest-roundtrip/buildfile index 8056f64..7ddcc1f 100644 --- a/tests/manifest-roundtrip/buildfile +++ b/tests/manifest-roundtrip/buildfile @@ -3,5 +3,4 @@ import libs = libbutl%lib{butl} -exe{driver}: {hxx cxx}{*} $libs -exe{driver}: manifest: test.roundtrip = true +exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/manifest-roundtrip/driver.cxx b/tests/manifest-roundtrip/driver.cxx index 4cf35e9..5dc5862 100644 --- a/tests/manifest-roundtrip/driver.cxx +++ b/tests/manifest-roundtrip/driver.cxx @@ -15,17 +15,39 @@ using namespace std; using namespace butl; +// Usage: argv[0] [-m] +// +// Round-trip a manifest reading it from stdin and printing to stdout. +// +// -m +// Serialize multi-line manifest values using the v2 form. +// int -main () +main (int argc, const char* argv[]) try { + bool multiline_v2 (false); + + for (int i (1); i != argc; ++i) + { + string v (argv[i]); + + if (v == "-m") + multiline_v2 = true; + } + // Read/write in binary mode. // stdin_fdmode (fdstream_mode::binary); stdout_fdmode (fdstream_mode::binary); manifest_parser p (cin, "stdin"); - manifest_serializer s (cout, "stdout"); + + manifest_serializer s (cout, + "stdout", + false /* long_lines */, + {} /* filter */, + multiline_v2); for (bool eom (true), eos (false); !eos; ) { diff --git a/tests/manifest-roundtrip/manifest b/tests/manifest-roundtrip/manifest deleted file mode 100644 index 4926e29..0000000 --- a/tests/manifest-roundtrip/manifest +++ /dev/null @@ -1,32 +0,0 @@ -: 1 -name: libbpkg -version: 1.0.1 -summary: build2 package manager library -license: MIT -tags: c++, package, manager, bpkg -description: A very very very very very very very very very very very very\ - very very very very very very very very very very very very very very very\ - very very long description. -changes:\ -1.0.1 - - Fixed a very very very very very very very very very very very very very\ - very annoying bug. -1.0.0 - - Firts public release - - Lots of really cool features -\ -url: http://www.codesynthesis.com/projects/libstudxml/ -email: build-users@codesynthesis.com; Public mailing list, posts by\ - non-members are allowed but moderated. -package-email: boris@codesynthesis.com; Direct email to the author. -depends: libbutl -depends: * build2 -depends: ?* bpkg -requires: ?* linux | windows -requires: c++11 -: -path: c:\windows\\ -path:\ - -c:\windows\\ -\ diff --git a/tests/manifest-roundtrip/testscript b/tests/manifest-roundtrip/testscript new file mode 100644 index 0000000..91db8b5 --- /dev/null +++ b/tests/manifest-roundtrip/testscript @@ -0,0 +1,78 @@ +# file : tests/manifest-roundtrip/testscript +# license : MIT; see accompanying LICENSE file + +: basics +: +$* <>EOF + : 1 + name: libbpkg + version: 1.0.1 + summary: build2 package manager library + license: MIT + tags: c++, package, manager, bpkg + description: A very very very very very very very very very very very very\ + very very very very very very very very very very very very very very very\ + very very long description. + changes:\ + 1.0.1 + - Fixed a very very very very very very very very very very very very very\ + very annoying bug. + 1.0.0 + - Firts public release + - Lots of really cool features + \ + url: http://www.codesynthesis.com/projects/libstudxml/ + email: build-users@codesynthesis.com; Public mailing list, posts by\ + non-members are allowed but moderated. + package-email: boris@codesynthesis.com; Direct email to the author. + depends: libbutl + depends: * build2 + depends: ?* bpkg + requires: ?* linux | windows + requires: c++11 + : + path: c:\windows\\ + path:\ + + c:\windows\\ + \ + EOF + +: multiline-v2 +: +$* -m <>EOF + : 1 + name: libbpkg + version: 1.0.1 + summary: build2 package manager library + license: MIT + tags: c++, package, manager, bpkg + description: A very very very very very very very very very very very very\ + very very very very very very very very very very very very very very very\ + very very long description. + changes: + \ + 1.0.1 + - Fixed a very very very very very very very very very very very very very\ + very annoying bug. + 1.0.0 + - Firts public release + - Lots of really cool features + \ + url: http://www.codesynthesis.com/projects/libstudxml/ + email: build-users@codesynthesis.com; Public mailing list, posts by\ + non-members are allowed but moderated. + package-email: boris@codesynthesis.com; Direct email to the author. + depends: libbutl + depends: * build2 + depends: ?* bpkg + requires: ?* linux | windows + requires: c++11 + : + path: c:\windows\\ + path: + \ + + c:\windows\\ + \ + EOF -- cgit v1.1