Code

core, frontend: Added !=, !~, and NOT operators.
authorSebastian Harl <sh@tokkee.org>
Sun, 6 Apr 2014 17:42:43 +0000 (19:42 +0200)
committerSebastian Harl <sh@tokkee.org>
Sun, 6 Apr 2014 17:42:43 +0000 (19:42 +0200)
src/core/store_lookup.c
src/frontend/grammar.y
src/frontend/scanner.l
t/core/store_lookup_test.c

index d43b9e32c764c10e0a372dabd71a79d3d30668f2..7416800a2281dd398ee90af83b5942c3eaf3eb07 100644 (file)
@@ -514,6 +514,9 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                const char *op, const char *value)
 {
        int typ = -1;
+       int inv = 0;
+
+       sdb_store_matcher_t *m = NULL;
 
        const char *matcher = NULL;
        const char *matcher_re = NULL;
@@ -526,10 +529,20 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                typ = SDB_ATTRIBUTE;
 
        /* TODO: support other operators */
-       if (! strcasecmp(op, "="))
+       if (! strcasecmp(op, "=")) {
+               matcher = value;
+       }
+       else if (! strcasecmp(op, "!=")) {
                matcher = value;
-       else if (! strcasecmp(op, "=~"))
+               inv = 1;
+       }
+       else if (! strcasecmp(op, "=~")) {
                matcher_re = value;
+       }
+       else if (! strcasecmp(op, "!~")) {
+               matcher_re = value;
+               inv = 1;
+       }
        else
                return NULL;
 
@@ -537,17 +550,28 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                /* accept */
        }
        else if (typ == SDB_ATTRIBUTE)
-               return sdb_store_attr_matcher(attr, NULL, matcher, matcher_re);
+               m = sdb_store_attr_matcher(attr, NULL, matcher, matcher_re);
        else
                return NULL;
 
-       if (typ == SDB_HOST)
-               return sdb_store_host_matcher(matcher, matcher_re, NULL, NULL);
+       if (m) {
+               /* accept the attribute value matcher */
+       }
+       else if (typ == SDB_HOST)
+               m = sdb_store_host_matcher(matcher, matcher_re, NULL, NULL);
        else if (typ == SDB_SERVICE)
-               return sdb_store_service_matcher(matcher, matcher_re, NULL);
+               m = sdb_store_service_matcher(matcher, matcher_re, NULL);
        else if (typ == SDB_ATTRIBUTE)
-               return sdb_store_attr_matcher(matcher, matcher_re, NULL, NULL);
-       return NULL;
+               m = sdb_store_attr_matcher(matcher, matcher_re, NULL, NULL);
+
+       if (m && inv) {
+               sdb_store_matcher_t *tmp;
+               tmp = sdb_store_inv_matcher(m);
+               /* pass ownership to the inverse matcher */
+               sdb_object_deref(SDB_OBJ(m));
+               m = tmp;
+       }
+       return m;
 } /* sdb_store_matcher_parse_cmp */
 
 sdb_store_matcher_t *
index 4bade3b47af690eae54b703eb12d8b1fd477464c..858c766b698aa124308a292f8ddcf90250127120 100644 (file)
@@ -78,9 +78,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
 
 %token SCANNER_ERROR
 
-%token AND OR WHERE
+%token AND OR NOT WHERE
 
-%token CMP_EQUAL CMP_REGEX
+%token CMP_EQUAL CMP_NEQUAL CMP_REGEX CMP_NREGEX
 
 %token <str> IDENTIFIER STRING
 %token <node> FETCH LIST LOOKUP
@@ -88,8 +88,9 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
 /* Precedence (lowest first): */
 %left OR
 %left AND
-%left CMP_EQUAL
-%left CMP_REGEX
+%left NOT
+%left CMP_EQUAL CMP_NEQUAL
+%left CMP_REGEX CMP_NREGEX
 %left '(' ')'
 %left '.'
 
@@ -283,6 +284,11 @@ matcher:
                        $$ = sdb_store_dis_matcher($1, $3);
                }
        |
+       NOT matcher
+               {
+                       $$ = sdb_store_inv_matcher($2);
+               }
+       |
        compare_matcher
                {
                        $$ = $1;
@@ -304,6 +310,15 @@ compare_matcher:
                        free($5); $5 = NULL;
                }
        |
+       IDENTIFIER '.' IDENTIFIER CMP_NEQUAL STRING
+               {
+                       $$ = sdb_store_matcher_parse_cmp($1, $3, "!=", $5);
+                       /* TODO: simplify memory management in the parser */
+                       free($1); $1 = NULL;
+                       free($3); $3 = NULL;
+                       free($5); $5 = NULL;
+               }
+       |
        IDENTIFIER '.' IDENTIFIER CMP_REGEX STRING
                {
                        $$ = sdb_store_matcher_parse_cmp($1, $3, "=~", $5);
@@ -311,6 +326,14 @@ compare_matcher:
                        free($3); $3 = NULL;
                        free($5); $5 = NULL;
                }
+       |
+       IDENTIFIER '.' IDENTIFIER CMP_NREGEX STRING
+               {
+                       $$ = sdb_store_matcher_parse_cmp($1, $3, "!~", $5);
+                       free($1); $1 = NULL;
+                       free($3); $3 = NULL;
+                       free($5); $5 = NULL;
+               }
        ;
 
 %%
index 9eec4de6c455e3dadd99fe586c2d4e68ba324395..32c13c54c355865d4024e94f683a06b6330b9492 100644 (file)
@@ -115,7 +115,9 @@ string              ('[^']*')
        }
 
 =      { return CMP_EQUAL; }
+!=     { return CMP_NEQUAL; }
 =~     { return CMP_REGEX; }
+!~     { return CMP_NREGEX; }
 
 .      { /* XXX: */ return yytext[0]; }
 
index 977bd9568d3203aab6a27f6c7354403494eee72b..a16d343d37d0a9991e244d419c6226ecc64c23d5 100644 (file)
@@ -348,17 +348,27 @@ START_TEST(test_parse_cmp)
                int expected;
        } golden_data[] = {
                { "host",      "name", "=",  "hostname", MATCHER_HOST },
+               { "host",      "name", "!=", "hostname", MATCHER_NOT },
                { "host",      "name", "=~", "hostname", MATCHER_HOST },
+               { "host",      "name", "!~", "hostname", MATCHER_NOT },
                { "host",      "attr", "=",  "hostname", -1 },
+               { "host",      "attr", "!=", "hostname", -1 },
                { "host",      "name", "&^", "hostname", -1 },
                { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
-               { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
+               { "service",   "name", "!=", "srvname",  MATCHER_NOT },
+               { "service",   "name", "=~", "srvname",  MATCHER_SERVICE },
+               { "service",   "name", "!~", "srvname",  MATCHER_NOT },
                { "service",   "attr", "=",  "srvname",  -1 },
+               { "service",   "attr", "!=", "srvname",  -1 },
                { "service",   "name", "&^", "srvname",  -1 },
                { "attribute", "name", "=",  "attrname", MATCHER_ATTR },
+               { "attribute", "name", "!=", "attrname", MATCHER_NOT },
                { "attribute", "name", "=~", "attrname", MATCHER_ATTR },
+               { "attribute", "name", "!~", "attrname", MATCHER_NOT },
                { "attribute", "attr", "=",  "attrname", MATCHER_ATTR },
+               { "attribute", "attr", "!=", "attrname", MATCHER_NOT },
                { "attribute", "attr", "=~", "attrname", MATCHER_ATTR },
+               { "attribute", "attr", "!~", "attrname", MATCHER_NOT },
                { "attribute", "attr", "&^", "attrname", -1 },
        };