aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-01-08 15:30:40 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-01-08 15:31:29 +0300
commit6ac4f3bcc0bd1306bf1a8dd1bebae1a00081c6b7 (patch)
tree18557b6da8fafbdc511a0c0f505137ca9317d5ef /libbutl
parent6876fd23ef84487c016e7be46d3deb7d1e695cef (diff)
Add support for filtering during manifest parsing and serialization
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/manifest-parser.cxx25
-rw-r--r--libbutl/manifest-parser.ixx14
-rw-r--r--libbutl/manifest-parser.mxx28
-rw-r--r--libbutl/manifest-serializer.cxx2
-rw-r--r--libbutl/manifest-serializer.ixx13
-rw-r--r--libbutl/manifest-serializer.mxx30
6 files changed, 92 insertions, 20 deletions
diff --git a/libbutl/manifest-parser.cxx b/libbutl/manifest-parser.cxx
index 20932e3..9aa35b7 100644
--- a/libbutl/manifest-parser.cxx
+++ b/libbutl/manifest-parser.cxx
@@ -41,13 +41,17 @@ namespace butl
using parsing = manifest_parsing;
using name_value = manifest_name_value;
- name_value manifest_parser::
- next ()
+ void manifest_parser::
+ parse_next (name_value& r)
{
if (s_ == end)
- return name_value {
+ {
+ r = name_value {
"", "", line, column, line, column, position, position, position};
+ return;
+ }
+
auto clp (skip_spaces ());
xchar c (clp.first);
uint64_t start_pos (clp.second);
@@ -67,15 +71,18 @@ namespace butl
{
s_ = start;
- return name_value {"", "",
- c.line, c.column, c.line, c.column,
- start_pos, c.position, c.position};
+ r = name_value {"", "",
+ c.line, c.column, c.line, c.column,
+ start_pos, c.position, c.position};
+ return;
}
+ r.name.clear ();
+ r.value.clear ();
+
// Regardless of the state, what should come next is a name,
// potentially the special empty one.
//
- name_value r;
r.start_pos = start_pos;
parse_name (r);
@@ -98,7 +105,7 @@ namespace butl
r.value_column = r.name_column;
r.colon_pos = r.start_pos;
r.end_pos = r.start_pos;
- return r;
+ return;
}
if (c != ':')
@@ -162,8 +169,6 @@ namespace butl
//
assert (!r.name.empty ());
}
-
- return r;
}
pair<string, string> manifest_parser::
diff --git a/libbutl/manifest-parser.ixx b/libbutl/manifest-parser.ixx
new file mode 100644
index 0000000..b308264
--- /dev/null
+++ b/libbutl/manifest-parser.ixx
@@ -0,0 +1,14 @@
+// file : libbutl/manifest-parser.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+namespace butl
+{
+ inline manifest_name_value manifest_parser::
+ next ()
+ {
+ manifest_name_value r;
+ do { parse_next (r); } while (filter_ && !filter_ (r));
+ return r;
+ }
+}
diff --git a/libbutl/manifest-parser.mxx b/libbutl/manifest-parser.mxx
index 7fc4ee3..0289d6f 100644
--- a/libbutl/manifest-parser.mxx
+++ b/libbutl/manifest-parser.mxx
@@ -11,9 +11,10 @@
#ifndef __cpp_lib_modules
#include <string>
#include <iosfwd>
-#include <cstdint> // uint64_t
-#include <utility> // pair
-#include <stdexcept> // runtime_error
+#include <cstdint> // uint64_t
+#include <utility> // pair, move()
+#include <stdexcept> // runtime_error
+#include <functional>
#endif
// Other includes.
@@ -52,8 +53,19 @@ LIBBUTL_MODEXPORT namespace butl
class LIBBUTL_SYMEXPORT manifest_parser: protected butl::char_scanner
{
public:
- manifest_parser (std::istream& is, const std::string& name)
- : char_scanner (is), name_ (name) {}
+ // The filter, if specified, is called by next() prior to returning the
+ // pair to the caller. If the filter returns false, then the pair is
+ // discarded.
+ //
+ // Note that the filter should handle the end-of-manifest pairs (see
+ // below) carefully, so next() doesn't end up with an infinite cycle.
+ //
+ using filter_function = bool (manifest_name_value&);
+
+ manifest_parser (std::istream& is,
+ const std::string& name,
+ std::function<filter_function> filter = {})
+ : char_scanner (is), name_ (name), filter_ (std::move (filter)) {}
const std::string&
name () const {return name_;}
@@ -83,6 +95,9 @@ LIBBUTL_MODEXPORT namespace butl
private:
void
+ parse_next (manifest_name_value&);
+
+ void
parse_name (manifest_name_value&);
void
@@ -98,8 +113,11 @@ LIBBUTL_MODEXPORT namespace butl
private:
const std::string name_;
+ const std::function<filter_function> filter_;
enum {start, body, end} s_ = start;
std::string version_; // Current format version.
};
}
+
+#include <libbutl/manifest-parser.ixx>
diff --git a/libbutl/manifest-serializer.cxx b/libbutl/manifest-serializer.cxx
index 2d2e722..dfbd9e1 100644
--- a/libbutl/manifest-serializer.cxx
+++ b/libbutl/manifest-serializer.cxx
@@ -39,7 +39,7 @@ namespace butl
using serialization = manifest_serialization;
void manifest_serializer::
- next (const string& n, const string& v)
+ write_next (const string& n, const string& v)
{
switch (s_)
{
diff --git a/libbutl/manifest-serializer.ixx b/libbutl/manifest-serializer.ixx
new file mode 100644
index 0000000..1108ba1
--- /dev/null
+++ b/libbutl/manifest-serializer.ixx
@@ -0,0 +1,13 @@
+// file : libbutl/manifest-serializer.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+namespace butl
+{
+ inline void manifest_serializer::
+ next (const std::string& n, const std::string& v)
+ {
+ if (!filter_ || filter_ (n, v))
+ write_next (n, v);
+ }
+}
diff --git a/libbutl/manifest-serializer.mxx b/libbutl/manifest-serializer.mxx
index 66ca398..6a87656 100644
--- a/libbutl/manifest-serializer.mxx
+++ b/libbutl/manifest-serializer.mxx
@@ -11,8 +11,9 @@
#ifndef __cpp_lib_modules
#include <string>
#include <iosfwd>
-#include <cstddef> // size_t
-#include <stdexcept> // runtime_error
+#include <cstddef> // size_t
+#include <stdexcept> // runtime_error
+#include <functional>
#endif
// Other includes.
@@ -42,8 +43,23 @@ LIBBUTL_MODEXPORT namespace butl
class LIBBUTL_SYMEXPORT manifest_serializer
{
public:
- manifest_serializer (std::ostream& os, const std::string& name)
- : os_ (os), name_ (name) {}
+ // The filter, if specified, is called by next() prior to serializing the
+ // pair into the stream. If the filter returns false, then the pair is
+ // discarded.
+ //
+ // Note that currently there is no way for the filter to modify the name
+ // or value. If we ever need this functionality, then we can add an
+ // "extended" filter alternative with two "receiving" arguments:
+ //
+ // bool (..., optional<string>& n, optional<string>& v);
+ //
+ using filter_function = bool (const std::string& name,
+ const std::string& value);
+
+ manifest_serializer (std::ostream& os,
+ const std::string& name,
+ std::function<filter_function> filter = {})
+ : os_ (os), name_ (name), filter_ (std::move (filter)) {}
const std::string&
name () const {return name_;}
@@ -77,6 +93,9 @@ LIBBUTL_MODEXPORT namespace butl
private:
friend class manifest_rewriter;
+ void
+ write_next (const std::string& name, const std::string& value);
+
// Validate and write a name.
//
void
@@ -105,5 +124,8 @@ LIBBUTL_MODEXPORT namespace butl
private:
std::ostream& os_;
const std::string name_;
+ const std::function<filter_function> filter_;
};
}
+
+#include <libbutl/manifest-serializer.ixx>