aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-08-01 16:42:22 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-08-02 01:01:41 +0300
commit6254448640530240dc9199bed60cd5568cbaf601 (patch)
tree4f859f61f1980bde1027fd3e22573157e9b5bd4b
parent12d0fb176edd8220f80f706d3fdc33431e178695 (diff)
Add manifest_parser::split_comment() and manifest_serializer::merge_comment()
-rw-r--r--libbutl/manifest-parser.cxx42
-rw-r--r--libbutl/manifest-parser.hxx8
-rw-r--r--libbutl/manifest-serializer.cxx25
-rw-r--r--libbutl/manifest-serializer.hxx7
-rw-r--r--tests/manifest-parser/driver.cxx17
-rw-r--r--tests/manifest-serializer/driver.cxx8
6 files changed, 107 insertions, 0 deletions
diff --git a/libbutl/manifest-parser.cxx b/libbutl/manifest-parser.cxx
index ae92d79..304815a 100644
--- a/libbutl/manifest-parser.cxx
+++ b/libbutl/manifest-parser.cxx
@@ -125,6 +125,48 @@ namespace butl
return r;
}
+ pair<string, string> manifest_parser::
+ split_comment (const string& v)
+ {
+ using iterator = string::const_iterator;
+
+ auto space = [] (char c) -> bool {return c == ' ' || c == '\t';};
+
+ iterator i (v.begin ());
+ iterator e (v.end ());
+
+ string r;
+ size_t n (0);
+ for (char c; i != e && (c = *i) != ';'; ++i)
+ {
+ // Unescape ';' character.
+ //
+ if (c == '\\' && i + 1 != e && *(i + 1) == ';')
+ c = *++i;
+
+ r += c;
+
+ if (!space (c))
+ n = r.size ();
+ }
+
+ // Strip the value trailing spaces.
+ //
+ if (r.size () != n)
+ r.resize (n);
+
+ // Find beginning of a comment (i).
+ //
+ if (i != e)
+ {
+ // Skip spaces.
+ //
+ for (++i; i != e && space (*i); ++i);
+ }
+
+ return make_pair (move (r), string (i, e));
+ }
+
void manifest_parser::
parse_name (name_value& r)
{
diff --git a/libbutl/manifest-parser.hxx b/libbutl/manifest-parser.hxx
index fd0cc4e..f84badd 100644
--- a/libbutl/manifest-parser.hxx
+++ b/libbutl/manifest-parser.hxx
@@ -8,6 +8,7 @@
#include <string>
#include <iosfwd>
#include <cstdint> // uint64_t
+#include <utility> // pair
#include <stdexcept> // runtime_error
#include <libbutl/export.hxx>
@@ -71,6 +72,13 @@ namespace butl
manifest_name_value
next ();
+ // Split the manifest value, optionally followed by ';' character and a
+ // comment into the value/comment pair. Note that ';' characters in the
+ // value must be escaped by the backslash.
+ //
+ static std::pair<std::string, std::string>
+ split_comment (const std::string&);
+
private:
void
parse_name (manifest_name_value&);
diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx
index adb7f13..d8f640b 100644
--- a/libbutl/manifest-serializer.cxx
+++ b/libbutl/manifest-serializer.cxx
@@ -133,6 +133,31 @@ namespace butl
os_ << endl;
}
+ string manifest_serializer::
+ merge_comment (const string& value, const string& comment)
+ {
+ string r;
+ for (char c: value)
+ {
+ // Escape ';' character.
+ //
+ if (c == ';')
+ r += '\\';
+
+ r += c;
+ }
+
+ // Add the comment.
+ //
+ if (!comment.empty ())
+ {
+ r += "; ";
+ r += comment;
+ }
+
+ return r;
+ }
+
void manifest_serializer::
check_name (const string& n)
{
diff --git a/libbutl/manifest-serializer.hxx b/libbutl/manifest-serializer.hxx
index 89c162c..d95ddf1 100644
--- a/libbutl/manifest-serializer.hxx
+++ b/libbutl/manifest-serializer.hxx
@@ -51,6 +51,13 @@ namespace butl
void
comment (const std::string&);
+ // Merge the manifest value and a comment into the single string, having
+ // the '<value>; <comment>' form. Escape ';' characters in the value with
+ // the backslash.
+ //
+ static std::string
+ merge_comment (const std::string& value, const std::string& comment);
+
private:
void
check_name (const std::string&);
diff --git a/tests/manifest-parser/driver.cxx b/tests/manifest-parser/driver.cxx
index e480508..037df96 100644
--- a/tests/manifest-parser/driver.cxx
+++ b/tests/manifest-parser/driver.cxx
@@ -130,6 +130,23 @@ main ()
{{"","1"},{"a","x\\"},{"b",""},{"",""},{"",""}}));
assert (test (":1\na:\\\nx\\\\\\\n\\\nb:",
{{"","1"},{"a","x\\\\"},{"b",""},{"",""},{"",""}}));
+
+ // Manifest value splitting (into the value/comment pair).
+ //
+ {
+ auto p (manifest_parser::split_comment ("value\\; text ; comment text"));
+ assert (p.first == "value; text" && p.second == "comment text");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("value"));
+ assert (p.first == "value" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("; comment"));
+ assert (p.first == "" && p.second == "comment");
+ }
}
static ostream&
diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx
index 69c1c71..dad96bd 100644
--- a/tests/manifest-serializer/driver.cxx
+++ b/tests/manifest-serializer/driver.cxx
@@ -213,6 +213,14 @@ main ()
": 1\na: c:\\\\\n"));
assert (test ({{"","1"},{"a","c:\\\nd:\\"},{"",""},{"",""}},
": 1\na: \\\nc:\\\\\nd:\\\\\n\\\n"));
+
+ // Manifest value/comment merging.
+ //
+ assert (manifest_serializer::merge_comment ("value; text", "comment") ==
+ "value\\; text; comment");
+
+ assert (manifest_serializer::merge_comment ("value text", "") ==
+ "value text");
}
static string