aboutsummaryrefslogtreecommitdiff
path: root/libbutl
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 /libbutl
parentf23282939c77bd1973457569aa3e002fef0559e3 (diff)
Implement manifest parsing/serialization
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/manifest-serializer.bash.in8
-rw-r--r--libbutl/manifest.cxx114
2 files changed, 105 insertions, 17 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;
}