diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2021-11-23 19:24:00 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2021-11-24 13:59:15 +0300 |
commit | 405dfa3e28ab71d4f6b5210faba0e3600070a0f3 (patch) | |
tree | e2e1de8213968c8b299904b48a60d4914eb1487b /libbutl | |
parent | b90126986fbeec6f42d469e99574096c3f6abc22 (diff) |
Add support for new-fashioned multi-line manifest value introducer
Diffstat (limited to 'libbutl')
-rw-r--r-- | libbutl/manifest-parser.cxx | 35 | ||||
-rw-r--r-- | libbutl/manifest-parser.hxx | 4 | ||||
-rw-r--r-- | libbutl/manifest-serializer.cxx | 3 | ||||
-rw-r--r-- | libbutl/manifest-serializer.hxx | 10 |
4 files changed, 47 insertions, 5 deletions
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:\<newline>'). // bool ml (false); if (c == '\\') @@ -245,6 +246,38 @@ namespace butl unget (c); } + // Detect the new-fashioned multi-line mode introducer (like in + // 'foo:<newline>\<newline>'). + // + 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<utf8_validator> + protected char_scanner<utf8_validator, 2> { 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<utf8_validator>; + using base = char_scanner<utf8_validator, 2>; 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_function> filter = {}) + std::function<filter_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_function> filter_; + bool multiline_v2_; }; // Serialize a manifest to a stream adding the leading format version pair |