aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-04-18 20:15:46 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-04-25 19:43:36 +0300
commit276f68ee4d55befa8922378199b4281c82d4fd93 (patch)
treeaf1c1b94fddec588feefe79a86e6463094ba2d8e /libbutl
parent7a1c91dbdbde1c4feeaa701592365bb4b7cf2562 (diff)
Add parse_manifest() and serialize_manifest() functions
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/manifest-parser.cxx42
-rw-r--r--libbutl/manifest-parser.ixx17
-rw-r--r--libbutl/manifest-parser.mxx47
-rw-r--r--libbutl/manifest-serializer.cxx21
-rw-r--r--libbutl/manifest-serializer.mxx13
5 files changed, 129 insertions, 11 deletions
diff --git a/libbutl/manifest-parser.cxx b/libbutl/manifest-parser.cxx
index 697273a..49b9ee0 100644
--- a/libbutl/manifest-parser.cxx
+++ b/libbutl/manifest-parser.cxx
@@ -10,6 +10,7 @@
#ifndef __cpp_lib_modules
#include <string>
+#include <vector>
#include <cstdint>
#include <utility>
#include <stdexcept>
@@ -28,6 +29,7 @@ module butl.manifest_parser;
import std.core;
import std.io;
#endif
+import butl.optional;
import butl.char_scanner;
import butl.manifest_types;
#endif
@@ -481,4 +483,44 @@ namespace butl
line (0), column (0), description (d)
{
}
+
+ // parse_manifest
+ //
+ static bool
+ try_parse_manifest (manifest_parser& p,
+ vector<manifest_name_value>& r,
+ bool allow_eos)
+ {
+ // Read the format version or eos pair. Note that the version is verified
+ // by the parser.
+ //
+ manifest_name_value nv (p.next ());
+
+ // Bail out if eos is reached and is allowed.
+ //
+ if (nv.empty () && allow_eos)
+ return false;
+
+ if (!nv.name.empty () || nv.empty ())
+ throw manifest_parsing (p.name (),
+ nv.value_line, nv.value_column,
+ "start of manifest expected");
+
+ for (nv = p.next (); !nv.empty (); nv = p.next ())
+ r.push_back (move (nv));
+
+ return true;
+ }
+
+ bool
+ try_parse_manifest (manifest_parser& p, vector<manifest_name_value>& r)
+ {
+ return try_parse_manifest (p, r, true /* allow_eos */);
+ }
+
+ void
+ parse_manifest (manifest_parser& p, std::vector<manifest_name_value>& r)
+ {
+ try_parse_manifest (p, r, false /* allow_eos */);
+ }
}
diff --git a/libbutl/manifest-parser.ixx b/libbutl/manifest-parser.ixx
index 4ffe3c5..1dbdcd5 100644
--- a/libbutl/manifest-parser.ixx
+++ b/libbutl/manifest-parser.ixx
@@ -11,4 +11,21 @@ namespace butl
do { parse_next (r); } while (filter_ && !filter_ (r));
return r;
}
+
+ inline optional<std::vector<manifest_name_value>>
+ try_parse_manifest (manifest_parser& p)
+ {
+ std::vector<manifest_name_value> r;
+ return try_parse_manifest (p, r)
+ ? optional<std::vector<manifest_name_value>> (move (r))
+ : nullopt;
+ }
+
+ inline std::vector<manifest_name_value>
+ parse_manifest (manifest_parser& p)
+ {
+ std::vector<manifest_name_value> r;
+ parse_manifest (p, r);
+ return r;
+ }
}
diff --git a/libbutl/manifest-parser.mxx b/libbutl/manifest-parser.mxx
index f39c9d2..a23d64f 100644
--- a/libbutl/manifest-parser.mxx
+++ b/libbutl/manifest-parser.mxx
@@ -10,6 +10,7 @@
#ifndef __cpp_lib_modules
#include <string>
+#include <vector>
#include <iosfwd>
#include <cstdint> // uint64_t
#include <utility> // pair, move()
@@ -25,9 +26,11 @@ export module butl.manifest_parser;
import std.core;
import std.io;
#endif
+import butl.optional;
import butl.char_scanner;
import butl.manifest_types;
#else
+#include <libbutl/optional.mxx>
#include <libbutl/char-scanner.mxx>
#include <libbutl/manifest-types.mxx>
#endif
@@ -72,16 +75,15 @@ LIBBUTL_MODEXPORT namespace butl
const std::string&
name () const {return name_;}
- // The first returned pair is special "start-of-manifest" with
- // empty name and value being the format version: {"", "<ver>"}.
- // After that we have a sequence of ordinary pairs which are
- // the manifest. At the end of the manifest we have the special
- // "end-of-manifest" pair with empty name and value: {"", ""}.
- // After that we can either get another start-of-manifest pair
- // (in which case the whole sequence repeats from the beginning)
- // or we get another end-of-manifest pair which signals the end
- // of stream (aka EOF). To put it another way, the parse sequence
- // always has the following form:
+ // The first returned pair is special "start-of-manifest" with empty name
+ // and value being the format version: {"", "<ver>"}. After that we have a
+ // sequence of ordinary pairs which are the manifest. At the end of the
+ // manifest we have the special "end-of-manifest" pair with empty name and
+ // value: {"", ""}. After that we can either get another start-of-manifest
+ // pair (in which case the whole sequence repeats from the beginning) or
+ // we get another end-of-manifest-like pair which signals the end of
+ // stream (aka EOF) and which we will call the end-of-stream pair. To put
+ // it another way, the parse sequence always has the following form:
//
// ({"", "<ver>"} {"<name>", "<value>"}* {"", ""})* {"", ""}
//
@@ -120,6 +122,31 @@ LIBBUTL_MODEXPORT namespace butl
enum {start, body, end} s_ = start;
std::string version_; // Current format version.
};
+
+ // Parse and return a single manifest. Throw manifest_parsing in case of an
+ // error.
+ //
+ // Note that the returned manifest doesn't contain the format version nor
+ // the end-of-manifest/stream pairs.
+ //
+ LIBBUTL_SYMEXPORT std::vector<manifest_name_value>
+ parse_manifest (manifest_parser&);
+
+ // As above but append the manifest values to an existing list.
+ //
+ LIBBUTL_SYMEXPORT void
+ parse_manifest (manifest_parser&, std::vector<manifest_name_value>&);
+
+ // As above but return nullopt if eos is reached before reading any values.
+ //
+ LIBBUTL_SYMEXPORT optional<std::vector<manifest_name_value>>
+ try_parse_manifest (manifest_parser&);
+
+ // As above but append the manifest values to an existing list returning
+ // false if eos is reached before reading any values.
+ //
+ LIBBUTL_SYMEXPORT bool
+ try_parse_manifest (manifest_parser&, std::vector<manifest_name_value>&);
}
#include <libbutl/manifest-parser.ixx>
diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx
index 059c374..4284ec6 100644
--- a/libbutl/manifest-serializer.cxx
+++ b/libbutl/manifest-serializer.cxx
@@ -10,6 +10,7 @@
#ifndef __cpp_lib_modules
#include <string>
+#include <vector>
#include <cstddef>
#include <stdexcept>
@@ -27,7 +28,7 @@ module butl.manifest_serializer;
import std.core;
import std.io;
#endif
-import butl.char_scanner;
+import butl.manifest_types;
#endif
#endif
@@ -319,4 +320,22 @@ namespace butl
: runtime_error (format (n, d)), name (n), description (d)
{
}
+
+ // serialize_manifest
+ //
+ void
+ serialize_manifest (manifest_serializer& s,
+ const vector<manifest_name_value>& nvs,
+ bool eos)
+ {
+ s.next ("", "1"); // Start of manifest.
+
+ for (const manifest_name_value& nv: nvs)
+ s.next (nv.name, nv.value);
+
+ s.next ("", ""); // End of manifest.
+
+ if (eos)
+ s.next ("", ""); // End of stream.
+ }
}
diff --git a/libbutl/manifest-serializer.mxx b/libbutl/manifest-serializer.mxx
index 1b3ace8..2a8d32e 100644
--- a/libbutl/manifest-serializer.mxx
+++ b/libbutl/manifest-serializer.mxx
@@ -10,6 +10,7 @@
#ifndef __cpp_lib_modules
#include <string>
+#include <vector>
#include <iosfwd>
#include <cstddef> // size_t
#include <stdexcept> // runtime_error
@@ -24,6 +25,9 @@ export module butl.manifest_serializer;
import std.core;
import std.io;
#endif
+import butl.manifest_types;
+#else
+#include <libbutl/manifest-types.mxx>
#endif
#include <libbutl/export.hxx>
@@ -136,6 +140,15 @@ LIBBUTL_MODEXPORT namespace butl
bool long_lines_;
const std::function<filter_function> filter_;
};
+
+ // Serialize a manifest to a stream adding the leading format version pair
+ // and the trailing end-of-manifest pair. Unless eos is false, then also
+ // write the end-of-stream pair.
+ //
+ LIBBUTL_SYMEXPORT void
+ serialize_manifest (manifest_serializer&,
+ const std::vector<manifest_name_value>&,
+ bool eos = true);
}
#include <libbutl/manifest-serializer.ixx>