aboutsummaryrefslogtreecommitdiff
path: root/libbbot/manifest.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbbot/manifest.cxx')
-rw-r--r--libbbot/manifest.cxx150
1 files changed, 103 insertions, 47 deletions
diff --git a/libbbot/manifest.cxx b/libbbot/manifest.cxx
index 56c5f1d..dae6e3e 100644
--- a/libbbot/manifest.cxx
+++ b/libbbot/manifest.cxx
@@ -4,6 +4,7 @@
#include <libbbot/manifest.hxx>
+#include <regex>
#include <vector>
#include <string>
#include <cctype> // isxdigit()
@@ -14,6 +15,7 @@
#include <cstdint> // uint64_t
#include <stdexcept> // invalid_argument
+#include <libbutl/regex.hxx>
#include <libbutl/base64.hxx>
#include <libbutl/utility.hxx> // digit()
#include <libbutl/tab-parser.hxx>
@@ -33,8 +35,6 @@ namespace bbot
using serialization = manifest_serialization;
using name_value = manifest_name_value;
- using strings = vector<string>;
-
// result_status
//
string
@@ -390,6 +390,57 @@ namespace bbot
if (nv.value != "1")
bad_value ("unsupported format version");
+ // Parse value represented as a whitespace-separated list of quoted
+ // strings (quoting is validated and preserved) and validate each string
+ // with the function specified.
+ //
+ auto parse_tab = [&bad_value] (
+ const string& value,
+ const function<void (const string&)>& check,
+ const string& what) -> strings
+ {
+ strings r;
+
+ // Note that when reporting errors we combine the manifest value
+ // position with the respective field and error positions.
+ //
+ try
+ {
+ istringstream is (value);
+ tab_parser parser (is, "");
+
+ // Here we naturally support multiline value manifest.
+ //
+ tab_fields tl;
+ while (!(tl = parser.next ()).empty ())
+ {
+ for (auto& tf: tl)
+ {
+ try
+ {
+ check (tf.value);
+ }
+ catch (const invalid_argument& e)
+ {
+ bad_value (string ("invalid task ") + what + ": " + e.what (),
+ tf.column - 1,
+ tl.line - 1);
+ }
+
+ r.emplace_back (move (tf.value));
+ }
+ }
+ }
+ catch (const tab_parsing& e)
+ {
+ bad_value ("invalid task " + what + ": " + e.description,
+ e.column - 1,
+ e.line - 1);
+ }
+
+ return r;
+ };
+
// Parse the task manifest.
//
for (nv = p.next (); !nv.empty (); nv = p.next ())
@@ -483,46 +534,21 @@ namespace bbot
if (!config.empty ())
bad_name ("task configuration redefinition");
- // Note that when reporting errors we combine the manifest value
- // position with the respective field and error positions.
- //
- try
- {
- istringstream is (v);
- tab_parser parser (is, "");
-
- // Here we naturally support multiline config manifest.
- //
- tab_fields tl;
- while (!(tl = parser.next ()).empty ())
- {
- for (auto& tf: tl)
- {
- try
- {
- check_config (tf.value);
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid task configuration: ") + e.what (),
- tf.column - 1,
- tl.line - 1);
- }
-
- config.emplace_back (move (tf.value));
- }
- }
- }
- catch (const tab_parsing& e)
- {
- bad_value ("invalid task configuration: " + e.description,
- e.column - 1,
- e.line - 1);
- }
+ config = parse_tab (v, check_config, "configuration");
if (config.empty ())
bad_value ("empty task configuration");
}
+ else if (n == "warning-regex")
+ {
+ if (!warning_regex.empty ())
+ bad_name ("task warning regex redefinition");
+
+ warning_regex = parse_tab (v, check_regex, "warning regex");
+
+ if (warning_regex.empty ())
+ bad_value ("empty task warning regex");
+ }
else if (!iu)
bad_name ("unknown name '" + n + "' in task manifest");
}
@@ -561,21 +587,28 @@ namespace bbot
if (target)
s.next ("target", target->string ());
- // Recompose config string as a space-separated variable list,
+ // Serialize an optional value of the strings type as a space-separated
+ // string list.
//
- if (!config.empty ())
+ auto serialize_list = [&s] (const char* name, const strings& value)
{
- string v;
- for (auto b (config.cbegin ()), i (b), e (config.cend ()); i != e; ++i)
+ if (!value.empty ())
{
- if (i != b)
- v += ' ';
+ string v;
+ for (auto b (value.cbegin ()), i (b), e (value.cend ()); i != e; ++i)
+ {
+ if (i != b)
+ v += ' ';
- v += *i;
+ v += *i;
+ }
+
+ s.next (name, v);
}
+ };
- s.next ("config", v);
- }
+ serialize_list ("config", config);
+ serialize_list ("warning-regex", warning_regex);
s.next ("", ""); // End of manifest.
}
@@ -586,6 +619,12 @@ namespace bbot
return string_parser::unquote (config);
}
+ strings task_manifest::
+ unquoted_warning_regex () const
+ {
+ return string_parser::unquote (warning_regex);
+ }
+
void task_manifest::
check_config (const string& s)
{
@@ -609,6 +648,23 @@ namespace bbot
throw invalid_argument ("no variable value");
}
+ void task_manifest::
+ check_regex (const string& s)
+ {
+ try
+ {
+ regex re (string_parser::unquote (s));
+ }
+ catch (const regex_error& e)
+ {
+ // Print regex_error description if meaningful (no space).
+ //
+ ostringstream os;
+ os << "invalid regex" << e;
+ throw invalid_argument (os.str ());
+ }
+ }
+
// task_response_manifest
//
task_response_manifest::