aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-07-21 22:15:29 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-07-27 14:30:27 +0300
commit258835fb4cd7338f9a0f9a758860cf1a368987dc (patch)
tree5ce1b92d1efb927c9428bf441d55031191326da3
parentf23282939c77bd1973457569aa3e002fef0559e3 (diff)
Implement manifest parsing/serialization
-rw-r--r--libbutl/manifest-serializer.bash.in8
-rw-r--r--libbutl/manifest.cxx114
-rw-r--r--tests/manifest-parser/testscript107
-rw-r--r--tests/manifest-serializer/driver.in2
-rw-r--r--tests/manifest-serializer/testscript108
5 files changed, 282 insertions, 57 deletions
diff --git a/libbutl/manifest-serializer.bash.in b/libbutl/manifest-serializer.bash.in
index 24eac65..5b91eed 100644
--- a/libbutl/manifest-serializer.bash.in
+++ b/libbutl/manifest-serializer.bash.in
@@ -17,13 +17,7 @@ fi
#
function butl_serialize_manifest ()
{
- # @@ TODO
- #"$(butl_path)/manifest" serialize
-
- local n v
- while IFS=: read -r -d '' n v; do
- printf "$n: $v\n"
- done
+ "$(butl_path)/manifest" serialize
}
# Start the manifest serialization co-process setting the following "return"
diff --git a/libbutl/manifest.cxx b/libbutl/manifest.cxx
index 9319b71..4c85b57 100644
--- a/libbutl/manifest.cxx
+++ b/libbutl/manifest.cxx
@@ -2,30 +2,80 @@
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+#include <ios> // ios::failure, ios::*bit
#include <string>
+#include <cassert>
+#include <cstddef> // size_t
#include <iostream>
+#include <stdexcept> // invalid_argument
#include <libbutl/utility.mxx>
+#include <libbutl/fdstream.mxx>
#include <libbutl/manifest-parser.mxx>
#include <libbutl/manifest-serializer.mxx>
using namespace std;
using namespace butl;
+// Set the binary translation mode for stdout. Throw ios::failure on error.
+// Noop on POSIX.
+//
+// Note that it makes sense to set the binary mode for stdout not to litter
+// the resulting manifest representation with the carriage return characters
+// on Windows.
+//
+static void
+stdout_binary ()
+{
+ try
+ {
+ stdout_fdmode (fdstream_mode::binary);
+ }
+ catch (const invalid_argument&)
+ {
+ assert (false); // No reason to happen.
+ }
+}
+
static int
cmd_parse ()
{
- //@@ TODO
+ using parser = manifest_parser;
+ using parsing = manifest_parsing;
+ using name_value = manifest_name_value;
+
+ // Parse the manifest list and write its binary representation.
+ //
+ try
+ {
+ stdout_binary ();
+
+ cin.exceptions (ios::badbit | ios::failbit);
+ cout.exceptions (ios::badbit | ios::failbit);
- const char m[] =
- ":1\0"
- "name:foo\0"
- "version:1.2.3\0"
- "description:foo\nexecutable\0"
- "depends:libfoo\0"
- "depends:libbar"; // Last \0 will be added.
+ parser p (cin, "stdin");
- cout.write (m, sizeof (m));
+ // Iterate over manifests in the list.
+ //
+ for (name_value nv (p.next ()); !nv.empty (); nv = p.next ())
+ {
+ // Iterate over manifest name/values.
+ //
+ for (; !nv.empty (); nv = p.next ())
+ cout << nv.name << ':' << nv.value << '\0' << flush;
+ }
+ }
+ catch (const parsing& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+ catch (const ios::failure& e)
+ {
+ cerr << "error: unable to read from stdin or write to stdout: " << e
+ << endl;
+ return 1;
+ }
return 0;
}
@@ -33,7 +83,51 @@ cmd_parse ()
static int
cmd_serialize ()
{
- //@@ TODO
+ using serializer = manifest_serializer;
+ using serialization = manifest_serialization;
+
+ try
+ {
+ stdout_binary ();
+
+ // Don't throw when failbit is set (getline() failed to extract any
+ // characters).
+ //
+ cin.exceptions (ios::badbit);
+
+ cout.exceptions (ios::badbit | ios::failbit);
+
+ serializer s (cout, "stdout");
+
+ for (string l; !eof (getline (cin, l, '\0')); )
+ {
+ size_t p (l.find (':'));
+
+ if (p == string::npos)
+ throw serialization (s.name (), "':' expected after name");
+
+ string n (l, 0, p);
+ string v (l, p + 1);
+
+ // Validates the name. Expects the first pair to be the format version.
+ // Ends current and starts next manifest for the start-of-manifest pair.
+ //
+ s.next (n, v);
+ }
+
+ s.next ("", ""); // End of manifest list.
+ }
+ catch (const serialization& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+ catch (const ios::failure& e)
+ {
+ cerr << "error: unable to read from stdin or write to stdout: " << e
+ << endl;
+ return 1;
+ }
return 0;
}
diff --git a/tests/manifest-parser/testscript b/tests/manifest-parser/testscript
index 154b107..78f4160 100644
--- a/tests/manifest-parser/testscript
+++ b/tests/manifest-parser/testscript
@@ -2,24 +2,101 @@
# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
# license : MIT; see accompanying LICENSE file
-$* >>EOO
-1
+: stdin
+:
+{
+ $* <<EOI >>EOO
+ : 1
+ name: foo
+ version: 1.2.3
+ description: \
+ foo
+ executable
+ \
+ depends: libfoo
+ depends: libbar
+ EOI
+ 1
-name
-foo
+ name
+ foo
-version
-1.2.3
+ version
+ 1.2.3
-description
-foo
-executable
+ description
+ foo
+ executable
-depends
-libfoo
+ depends
+ libfoo
-depends
-libbar
-EOO
+ depends
+ libbar
+ EOO
+}
-#@@ TODO: test reading from file instead of stdin.
+: file
+:
+{
+ cat <<EOI >=file;
+ : 1
+ name: foo
+ version: 1.2.3
+ EOI
+
+ $* file >>EOO
+ 1
+
+ name
+ foo
+
+ version
+ 1.2.3
+ EOO
+}
+
+: list
+:
+{
+ $* <<EOI >>EOO
+ : 1
+ name: foo
+ :
+ version: 1.2.3
+ EOI
+ 1
+
+ name
+ foo
+ 1
+
+ version
+ 1.2.3
+ EOO
+}
+
+: version
+:
+{
+ : absent
+ :
+ $* <<EOI 2>'stdin:1:1: error: format version pair expected' != 0
+ name: foo
+ EOI
+
+ : unsupported
+ :
+ $* <<EOI >- 2>'stdin:3:3: error: unsupported format version 2' != 0
+ : 1
+ name: foo
+ : 2
+ version: 1.2.3
+ EOI
+}
+
+: empty
+:
+{
+ $* <:'' >:''
+}
diff --git a/tests/manifest-serializer/driver.in b/tests/manifest-serializer/driver.in
index 9e619e5..4ee31a7 100644
--- a/tests/manifest-serializer/driver.in
+++ b/tests/manifest-serializer/driver.in
@@ -14,7 +14,6 @@ butl_manifest_serializer_start "$@"
fd="$butl_manifest_serializer_ifd"
while read -r n; do
-
printf "%s:" "$n" >&"$fd"
f=true
@@ -31,7 +30,6 @@ while read -r n; do
printf "%s" "$v" >&"$fd"
fi
done
-
done
butl_manifest_serializer_finish
diff --git a/tests/manifest-serializer/testscript b/tests/manifest-serializer/testscript
index af96cc0..f305342 100644
--- a/tests/manifest-serializer/testscript
+++ b/tests/manifest-serializer/testscript
@@ -2,34 +2,96 @@
# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
# license : MIT; see accompanying LICENSE file
-$* <<EOI >>EOO
+: stdout
+{
+ $* <<EOI >>EOO
-1
+ 1
-name
-foo
+ name
+ foo
-version
-1.2.3
+ version
+ 1.2.3
-description
-foo
-executable
+ description
+ foo
+ executable
-depends
-libfoo
+ depends
+ libfoo
-depends
-libbar
+ depends
+ libbar
-EOI
-: 1
-name: foo
-version: 1.2.3
-description: foo
-executable
-depends: libfoo
-depends: libbar
-EOO
+ EOI
+ : 1
+ name: foo
+ version: 1.2.3
+ description: \
+ foo
+ executable
+ \
+ depends: libfoo
+ depends: libbar
+ EOO
+}
-#@@ TODO: test writing to file instead of stdout.
+: file
+{
+ $* <<EOI >=file;
+
+ 1
+
+ name
+ foo
+
+ version
+ 1.2.3
+ EOI
+
+ cat file >>EOE
+ : 1
+ name: foo
+ version: 1.2.3
+ EOE
+}
+
+: list
+{
+ $* <<EOI >>EOO
+
+ 1
+
+ name
+ foo
+
+
+ 1
+
+ version
+ 1.2.3
+ EOI
+ : 1
+ name: foo
+ :
+ version: 1.2.3
+ EOO
+}
+
+: version
+:
+{
+ : absent
+ :
+ $* <<EOI 2>'stdout: error: format version pair expected' != 0
+ name
+ foo
+ EOI
+}
+
+: empty
+:
+{
+ $* <:'' >:''
+}