diff --git a/src/CLI.cpp b/src/CLI.cpp
index 895aedfc8..59cf6702f 100644
--- a/src/CLI.cpp
+++ b/src/CLI.cpp
@@ -251,6 +251,9 @@ void CLI::initialize (int argc, const char** argv)
{
// Clean what needs to be cleaned. Everything in this case.
_original_args.clear ();
+ _id_ranges.clear ();
+ _uuid_list.clear ();
+
for (int i = 0; i < argc; ++i)
_original_args.push_back (argv[i]);
@@ -275,6 +278,8 @@ void CLI::analyze (bool parse /* = true */)
{
// Clean what needs to be cleaned. Most in this case.
_args.clear ();
+ _id_ranges.clear ();
+ _uuid_list.clear ();
for (int i = 0; i < _original_args.size (); ++i)
{
@@ -318,8 +323,9 @@ void CLI::analyze (bool parse /* = true */)
desugarAttributes ();
desugarAttributeModifiers ();
desugarPatterns ();
- desugarIDs ();
- desugarUUIDs ();
+ findIDs ();
+ findUUIDs ();
+ insertIDExpr ();
findOperators ();
insertJunctions ();
desugarPlainArgs ();
@@ -995,9 +1001,8 @@ void CLI::desugarPatterns ()
// a range: 5-10
// or a combination: 1,3,5-10 12
//
-void CLI::desugarIDs ()
+void CLI::findIDs ()
{
- std::vector reconstructed;
std::vector ::iterator a;
for (a = _args.begin (); a != _args.end (); ++a)
{
@@ -1016,7 +1021,7 @@ void CLI::desugarIDs ()
std::vector elements;
split (elements, raw, ',');
- bool not_an_id = false;
+ bool is_an_id = true;
std::vector ::iterator e;
for (e = elements.begin (); e != elements.end (); ++e)
{
@@ -1028,7 +1033,7 @@ void CLI::desugarIDs ()
{
if (! digitsOnly (terms[0]))
{
- not_an_id = true;
+ is_an_id = false;
break;
}
@@ -1041,7 +1046,7 @@ void CLI::desugarIDs ()
}
else
{
- not_an_id = true;
+ is_an_id = false;
break;
}
}
@@ -1050,7 +1055,7 @@ void CLI::desugarIDs ()
if (! digitsOnly (terms[0]) ||
! digitsOnly (terms[1]))
{
- not_an_id = true;
+ is_an_id = false;
break;
}
@@ -1070,135 +1075,39 @@ void CLI::desugarIDs ()
}
else
{
- not_an_id = true;
+ is_an_id = false;
break;
}
}
else
{
- not_an_id = true;
+ is_an_id = false;
break;
}
}
- if (! not_an_id)
+ if (is_an_id)
{
- // Now convert the ranges into an infix expression.
- A openParen ("argSeq", "(");
- openParen.tag ("FILTER");
- openParen.tag ("OP");
- reconstructed.push_back (openParen);
+ a->tag ("ID");
+ // Save the ranges.
std::vector >::iterator r;
for (r = ranges.begin (); r != ranges.end (); ++r)
- {
- if (r != ranges.begin ())
- {
- A opOp ("argSeq", "or");
- opOp.tag ("FILTER");
- opOp.tag ("OP");
- reconstructed.push_back (opOp);
- }
-
- if (r->first == r->second)
- {
- A id ("argSeq", "id");
- id.tag ("FILTER");
- id.tag ("ATTRIBUTE");
- reconstructed.push_back (id);
-
- A equal ("argSeq", "==");
- equal.tag ("FILTER");
- equal.tag ("OP");
- reconstructed.push_back (equal);
-
- A value ("argSeq", r->first);
- value.tag ("FILTER");
- value.tag ("LITERAL");
- value.tag ("NUMBER");
- reconstructed.push_back (value);
- }
- else
- {
- A rangeOpenParen ("argSeq", "(");
- rangeOpenParen.tag ("FILTER");
- rangeOpenParen.tag ("OP");
- reconstructed.push_back (rangeOpenParen);
-
- A startId ("argSeq", "id");
- startId.tag ("FILTER");
- startId.tag ("ATTRIBUTE");
- reconstructed.push_back (startId);
-
- A gte ("argSeq", ">=");
- gte.tag ("FILTER");
- gte.tag ("OP");
- reconstructed.push_back (gte);
-
- A startValue ("argSeq", r->first);
- startValue.tag ("FILTER");
- startValue.tag ("LITERAL");
- startValue.tag ("NUMBER");
- reconstructed.push_back (startValue);
-
- A andOp ("argSeq", "and");
- andOp.tag ("FILTER");
- andOp.tag ("OP");
- reconstructed.push_back (andOp);
-
- A endId ("argSeq", "id");
- endId.tag ("FILTER");
- endId.tag ("ATTRIBUTE");
- reconstructed.push_back (endId);
-
- A lte ("argSeq", "<=");
- lte.tag ("FILTER");
- lte.tag ("OP");
- reconstructed.push_back (lte);
-
- A endValue ("argSeq", r->second);
- endValue.tag ("FILTER");
- endValue.tag ("LITERAL");
- endValue.tag ("NUMBER");
- reconstructed.push_back (endValue);
-
- A rangeCloseParen ("argSeq", ")");
- rangeCloseParen.tag ("FILTER");
- rangeCloseParen.tag ("OP");
- reconstructed.push_back (rangeCloseParen);
- }
- }
-
- A closeParen ("argSeq", ")");
- closeParen.tag ("FILTER");
- closeParen.tag ("OP");
- reconstructed.push_back (closeParen);
-
- found = true;
+ _id_ranges.push_back (*r);
}
}
-
- if (!found)
- reconstructed.push_back (*a);
}
- else
- reconstructed.push_back (*a);
}
-
- _args = reconstructed;
}
////////////////////////////////////////////////////////////////////////////////
-void CLI::desugarUUIDs ()
+void CLI::findUUIDs ()
{
- std::vector reconstructed;
std::vector ::iterator a;
for (a = _args.begin (); a != _args.end (); ++a)
{
if (a->hasTag ("FILTER"))
{
- bool found = false;
-
// UUIDs have a limited character set.
std::string raw = a->attribute ("raw");
if (raw.find_first_not_of ("0123456789abcdefABCDEF-,") == std::string::npos)
@@ -1222,51 +1131,140 @@ void CLI::desugarUUIDs ()
if (n.depleted ())
{
- A openParen ("argSeq", "(");
- openParen.tag ("FILTER");
- openParen.tag ("OP");
- reconstructed.push_back (openParen);
-
- std::vector ::iterator u;
- for (u = uuidList.begin (); u != uuidList.end (); ++u)
- {
- if (u != uuidList.begin ())
- {
- A openParen ("argSeq", "or");
- openParen.tag ("FILTER");
- openParen.tag ("OP");
- reconstructed.push_back (openParen);
- }
-
- A uuid ("argSeq", "uuid");
- uuid.tag ("FILTER");
- uuid.tag ("ATTRIBUTE");
- reconstructed.push_back (uuid);
-
- A equal ("argSeq", "=");
- equal.tag ("FILTER");
- equal.tag ("OP");
- reconstructed.push_back (equal);
-
- A value ("argSeq", "'" + *u + "'");
- value.tag ("FILTER");
- value.tag ("LITERAL");
- value.tag ("STRING");
- reconstructed.push_back (value);
- }
-
- A closeParen ("argSeq", ")");
- closeParen.tag ("FILTER");
- closeParen.tag ("OP");
- reconstructed.push_back (closeParen);
-
- found = true;
+ _uuid_list = uuidList;
+ a->tag ("UUID");
}
}
}
+ }
+ }
+}
- if (!found)
- reconstructed.push_back (*a);
+////////////////////////////////////////////////////////////////////////////////
+void CLI::insertIDExpr ()
+{
+ // Iterate over all args. The first ID/UUID arg found will be replaced by
+ // the combined ID clause. All other ID/UUID args are removed.
+ bool foundID = false;
+ std::vector reconstructed;
+ std::vector ::iterator a;
+ for (a = _args.begin (); a != _args.end (); ++a)
+ {
+ if (a->hasTag ("FILTER") &&
+ (a->hasTag ("ID") ||
+ a->hasTag ("UUID")))
+ {
+ if (! foundID)
+ {
+ foundID = true;
+
+ // Construct a single sequence that represents all _id_ranges and
+ // _uuid_list in one clause. This is essentially converting this:
+ //
+ // 1,2-3 uuid,uuid uuid 4
+ //
+ // into:
+ //
+ // (
+ // ( id == 1 )
+ // or ( ( id >= 2 ) and ( id <= 3 ) )
+ // or ( id == 4 )
+ // or ( uuid = $UUID )
+ // or ( uuid = $UUID )
+ // )
+
+ A openParen ("argSeq", "("); openParen.tag ("FILTER"); openParen.tag ("OP");
+ A closeParen ("argSeq", ")"); closeParen.tag ("FILTER"); closeParen.tag ("OP");
+ A opOr ("argSeq", "or"); opOr.tag ("FILTER"); opOr.tag ("OP");
+ A opAnd ("argSeq", "and"); opAnd.tag ("FILTER"); opAnd.tag ("OP");
+ A opSimilar ("argSeq", "="); opSimilar.tag ("FILTER"); opSimilar.tag ("OP");
+ A opEqual ("argSeq", "=="); opEqual.tag ("FILTER"); opEqual.tag ("OP");
+ A opGTE ("argSeq", ">="); opGTE.tag ("FILTER"); opGTE.tag ("OP");
+ A opLTE ("argSeq", "<="); opLTE.tag ("FILTER"); opLTE.tag ("OP");
+
+ A argID ("argSeq", "id");
+ argID.tag ("FILTER");
+ argID.tag ("ATTRIBUTE");
+ argID.tag ("OP");
+
+ A argUUID ("argSeq", "uuid");
+ argUUID.tag ("FILTER");
+ argUUID.tag ("ATTRIBUTE");
+ argUUID.tag ("OP");
+
+ reconstructed.push_back (openParen);
+
+ // Add all ID ranges.
+ std::vector >::iterator r;
+ for (r = _id_ranges.begin (); r != _id_ranges.end (); ++r)
+ {
+ if (r != _id_ranges.begin ())
+ reconstructed.push_back (opOr);
+
+ if (r->first == r->second)
+ {
+ reconstructed.push_back (openParen);
+ reconstructed.push_back (argID);
+ reconstructed.push_back (opEqual);
+
+ A value ("argSeq", r->first);
+ value.tag ("FILTER");
+ value.tag ("LITERAL");
+ value.tag ("NUMBER");
+ reconstructed.push_back (value);
+
+ reconstructed.push_back (closeParen);
+ }
+ else
+ {
+ reconstructed.push_back (openParen);
+ reconstructed.push_back (argID);
+ reconstructed.push_back (opGTE);
+
+ A startValue ("argSeq", r->first);
+ startValue.tag ("FILTER");
+ startValue.tag ("LITERAL");
+ startValue.tag ("NUMBER");
+ reconstructed.push_back (startValue);
+
+ reconstructed.push_back (opAnd);
+ reconstructed.push_back (argID);
+ reconstructed.push_back (opLTE);
+
+ A endValue ("argSeq", r->second);
+ endValue.tag ("FILTER");
+ endValue.tag ("LITERAL");
+ endValue.tag ("NUMBER");
+ reconstructed.push_back (endValue);
+
+ reconstructed.push_back (closeParen);
+ }
+ }
+
+ // Add all UUID list items.
+ std::vector ::iterator u;
+ for (u = _uuid_list.begin (); u != _uuid_list.end (); ++u)
+ {
+ if (u != _uuid_list.begin ())
+ reconstructed.push_back (opOr);
+
+ reconstructed.push_back (openParen);
+ reconstructed.push_back (argUUID);
+ reconstructed.push_back (opSimilar);
+
+ A value ("argSeq", "'" + *u + "'");
+ value.tag ("FILTER");
+ value.tag ("LITERAL");
+ value.tag ("STRING");
+ reconstructed.push_back (value);
+
+ reconstructed.push_back (closeParen);
+ }
+
+ reconstructed.push_back (closeParen);
+ }
+
+ // No 'else' which cause all other ID/UUID args to be eaten.
}
else
reconstructed.push_back (*a);
diff --git a/src/CLI.h b/src/CLI.h
index 2854b4def..2ebadc31f 100644
--- a/src/CLI.h
+++ b/src/CLI.h
@@ -85,8 +85,9 @@ private:
void desugarAttributes ();
void desugarAttributeModifiers ();
void desugarPatterns ();
- void desugarIDs ();
- void desugarUUIDs ();
+ void findIDs ();
+ void findUUIDs ();
+ void insertIDExpr ();
void desugarPlainArgs ();
void findOperators ();
void insertJunctions ();
@@ -100,6 +101,9 @@ public:
std::map _aliases;
std::vector _original_args;
std::vector _args;
+
+ std::vector > _id_ranges;
+ std::vector _uuid_list;
};
#endif