diff options
-rw-r--r-- | lib/filter.cpp | 146 | ||||
-rw-r--r-- | lib/filter.h | 22 | ||||
-rw-r--r-- | lib/statement.cpp | 12 | ||||
-rw-r--r-- | lib/word.cpp | 24 |
4 files changed, 193 insertions, 11 deletions
diff --git a/lib/filter.cpp b/lib/filter.cpp index 1472eeb..fec0fd3 100644 --- a/lib/filter.cpp +++ b/lib/filter.cpp | |||
@@ -92,6 +92,15 @@ namespace verbly { | |||
92 | 92 | ||
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | |||
96 | case type::mask: | ||
97 | { | ||
98 | new(&mask_.name) std::string(other.mask_.name); | ||
99 | mask_.internal = other.mask_.internal; | ||
100 | new(&mask_.subfilter) std::unique_ptr<filter>(new filter(*other.mask_.subfilter)); | ||
101 | |||
102 | break; | ||
103 | } | ||
95 | } | 104 | } |
96 | } | 105 | } |
97 | 106 | ||
@@ -122,6 +131,9 @@ namespace verbly { | |||
122 | field tempCompareField; | 131 | field tempCompareField; |
123 | std::list<filter> tempChildren; | 132 | std::list<filter> tempChildren; |
124 | bool tempOrlogic; | 133 | bool tempOrlogic; |
134 | std::string tempMaskName; | ||
135 | bool tempMaskInternal; | ||
136 | std::unique_ptr<filter> tempMaskSubfilter; | ||
125 | 137 | ||
126 | switch (tempType) | 138 | switch (tempType) |
127 | { | 139 | { |
@@ -201,6 +213,15 @@ namespace verbly { | |||
201 | 213 | ||
202 | break; | 214 | break; |
203 | } | 215 | } |
216 | |||
217 | case type::mask: | ||
218 | { | ||
219 | tempMaskName = std::move(first.mask_.name); | ||
220 | tempMaskInternal = first.mask_.internal; | ||
221 | tempMaskSubfilter = std::move(first.mask_.subfilter); | ||
222 | |||
223 | break; | ||
224 | } | ||
204 | } | 225 | } |
205 | 226 | ||
206 | first.~filter(); | 227 | first.~filter(); |
@@ -285,6 +306,15 @@ namespace verbly { | |||
285 | 306 | ||
286 | break; | 307 | break; |
287 | } | 308 | } |
309 | |||
310 | case type::mask: | ||
311 | { | ||
312 | new(&first.mask_.name) std::string(std::move(second.mask_.name)); | ||
313 | first.mask_.internal = second.mask_.internal; | ||
314 | new(&first.mask_.subfilter) std::unique_ptr<filter>(std::move(second.mask_.subfilter)); | ||
315 | |||
316 | break; | ||
317 | } | ||
288 | } | 318 | } |
289 | 319 | ||
290 | second.~filter(); | 320 | second.~filter(); |
@@ -369,6 +399,15 @@ namespace verbly { | |||
369 | 399 | ||
370 | break; | 400 | break; |
371 | } | 401 | } |
402 | |||
403 | case type::mask: | ||
404 | { | ||
405 | new(&first.mask_.name) std::string(std::move(tempMaskName)); | ||
406 | first.mask_.internal = tempMaskInternal; | ||
407 | new(&first.mask_.subfilter) std::unique_ptr<filter>(std::move(tempMaskSubfilter)); | ||
408 | |||
409 | break; | ||
410 | } | ||
372 | } | 411 | } |
373 | } | 412 | } |
374 | 413 | ||
@@ -444,6 +483,17 @@ namespace verbly { | |||
444 | 483 | ||
445 | break; | 484 | break; |
446 | } | 485 | } |
486 | |||
487 | case type::mask: | ||
488 | { | ||
489 | using string_type = std::string; | ||
490 | using ptr_type = std::unique_ptr<filter>; | ||
491 | |||
492 | mask_.name.~string_type(); | ||
493 | mask_.subfilter.~ptr_type(); | ||
494 | |||
495 | break; | ||
496 | } | ||
447 | } | 497 | } |
448 | } | 498 | } |
449 | 499 | ||
@@ -1024,6 +1074,44 @@ namespace verbly { | |||
1024 | } | 1074 | } |
1025 | } | 1075 | } |
1026 | 1076 | ||
1077 | filter::filter(std::string name, bool internal, filter subfilter) : | ||
1078 | type_(type::mask) | ||
1079 | { | ||
1080 | new(&mask_.name) std::string(std::move(name)); | ||
1081 | mask_.internal = internal; | ||
1082 | new(&mask_.subfilter) std::unique_ptr<filter>(new filter(std::move(subfilter))); | ||
1083 | } | ||
1084 | |||
1085 | const std::string& filter::getMaskName() const | ||
1086 | { | ||
1087 | if (type_ == type::mask) | ||
1088 | { | ||
1089 | return mask_.name; | ||
1090 | } else { | ||
1091 | throw std::domain_error("This filter is not a mask filter"); | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | bool filter::isMaskInternal() const | ||
1096 | { | ||
1097 | if (type_ == type::mask) | ||
1098 | { | ||
1099 | return mask_.internal; | ||
1100 | } else { | ||
1101 | throw std::domain_error("This filter is not a mask filter"); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | const filter& filter::getMaskFilter() const | ||
1106 | { | ||
1107 | if (type_ == type::mask) | ||
1108 | { | ||
1109 | return *mask_.subfilter; | ||
1110 | } else { | ||
1111 | throw std::domain_error("This filter is not a mask filter"); | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1027 | filter filter::operator!() const | 1115 | filter filter::operator!() const |
1028 | { | 1116 | { |
1029 | switch (type_) | 1117 | switch (type_) |
@@ -1145,6 +1233,11 @@ namespace verbly { | |||
1145 | 1233 | ||
1146 | return result; | 1234 | return result; |
1147 | } | 1235 | } |
1236 | |||
1237 | case type::mask: | ||
1238 | { | ||
1239 | return {mask_.name, mask_.internal, !*mask_.subfilter}; | ||
1240 | } | ||
1148 | } | 1241 | } |
1149 | } | 1242 | } |
1150 | 1243 | ||
@@ -1168,6 +1261,7 @@ namespace verbly { | |||
1168 | } | 1261 | } |
1169 | 1262 | ||
1170 | case type::singleton: | 1263 | case type::singleton: |
1264 | case type::mask: | ||
1171 | { | 1265 | { |
1172 | filter result(false); | 1266 | filter result(false); |
1173 | result.group_.children.push_back(*this); | 1267 | result.group_.children.push_back(*this); |
@@ -1205,6 +1299,7 @@ namespace verbly { | |||
1205 | } | 1299 | } |
1206 | 1300 | ||
1207 | case type::singleton: | 1301 | case type::singleton: |
1302 | case type::mask: | ||
1208 | { | 1303 | { |
1209 | filter result(true); | 1304 | filter result(true); |
1210 | result.group_.children.push_back(*this); | 1305 | result.group_.children.push_back(*this); |
@@ -1232,6 +1327,11 @@ namespace verbly { | |||
1232 | } | 1327 | } |
1233 | } | 1328 | } |
1234 | 1329 | ||
1330 | filter filter::mask(std::string name, filter subfilter) | ||
1331 | { | ||
1332 | return {std::move(name), false, std::move(subfilter)}; | ||
1333 | } | ||
1334 | |||
1235 | filter filter::normalize(object context) const | 1335 | filter filter::normalize(object context) const |
1236 | { | 1336 | { |
1237 | { | 1337 | { |
@@ -1408,6 +1508,7 @@ namespace verbly { | |||
1408 | filter result(group_.orlogic); | 1508 | filter result(group_.orlogic); |
1409 | std::map<field, filter> positiveJoins; | 1509 | std::map<field, filter> positiveJoins; |
1410 | std::map<field, filter> negativeJoins; | 1510 | std::map<field, filter> negativeJoins; |
1511 | std::map<std::tuple<std::string, bool>, filter> masks; | ||
1411 | 1512 | ||
1412 | for (const filter& child : group_.children) | 1513 | for (const filter& child : group_.children) |
1413 | { | 1514 | { |
@@ -1502,6 +1603,20 @@ namespace verbly { | |||
1502 | 1603 | ||
1503 | break; | 1604 | break; |
1504 | } | 1605 | } |
1606 | |||
1607 | case type::mask: | ||
1608 | { | ||
1609 | auto maskId = std::tie(normalized.mask_.name, normalized.mask_.internal); | ||
1610 | |||
1611 | if (!masks.count(maskId)) | ||
1612 | { | ||
1613 | masks[maskId] = filter(group_.orlogic); | ||
1614 | } | ||
1615 | |||
1616 | masks.at(maskId) += std::move(*normalized.mask_.subfilter); | ||
1617 | |||
1618 | break; | ||
1619 | } | ||
1505 | } | 1620 | } |
1506 | } | 1621 | } |
1507 | 1622 | ||
@@ -1521,8 +1636,22 @@ namespace verbly { | |||
1521 | result += !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); | 1636 | result += !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); |
1522 | } | 1637 | } |
1523 | 1638 | ||
1639 | for (auto& mapping : masks) | ||
1640 | { | ||
1641 | const std::string& name = std::get<0>(mapping.first); | ||
1642 | bool internal = std::get<1>(mapping.first); | ||
1643 | filter& subfilter = mapping.second; | ||
1644 | |||
1645 | result += {name, internal, std::move(subfilter)}; | ||
1646 | } | ||
1647 | |||
1524 | return result; | 1648 | return result; |
1525 | } | 1649 | } |
1650 | |||
1651 | case type::mask: | ||
1652 | { | ||
1653 | return {mask_.name, mask_.internal, mask_.subfilter->normalize(context)}; | ||
1654 | } | ||
1526 | } | 1655 | } |
1527 | } | 1656 | } |
1528 | } | 1657 | } |
@@ -1552,10 +1681,27 @@ namespace verbly { | |||
1552 | if (result.group_.children.empty()) | 1681 | if (result.group_.children.empty()) |
1553 | { | 1682 | { |
1554 | result = {}; | 1683 | result = {}; |
1684 | } else if (result.group_.children.size() == 1) | ||
1685 | { | ||
1686 | filter tempChild = std::move(result.group_.children.front()); | ||
1687 | |||
1688 | result = std::move(tempChild); | ||
1555 | } | 1689 | } |
1556 | 1690 | ||
1557 | return result; | 1691 | return result; |
1558 | } | 1692 | } |
1693 | |||
1694 | case type::mask: | ||
1695 | { | ||
1696 | filter subfilter = mask_.subfilter->compact(); | ||
1697 | |||
1698 | if (subfilter.type_ == type::empty) | ||
1699 | { | ||
1700 | return {}; | ||
1701 | } else { | ||
1702 | return {mask_.name, mask_.internal, std::move(subfilter)}; | ||
1703 | } | ||
1704 | } | ||
1559 | } | 1705 | } |
1560 | } | 1706 | } |
1561 | 1707 | ||
diff --git a/lib/filter.h b/lib/filter.h index a12a822..942fe18 100644 --- a/lib/filter.h +++ b/lib/filter.h | |||
@@ -14,7 +14,8 @@ namespace verbly { | |||
14 | enum class type { | 14 | enum class type { |
15 | empty, | 15 | empty, |
16 | singleton, | 16 | singleton, |
17 | group | 17 | group, |
18 | mask | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | enum class comparison { | 21 | enum class comparison { |
@@ -106,6 +107,16 @@ namespace verbly { | |||
106 | 107 | ||
107 | const_iterator end() const; | 108 | const_iterator end() const; |
108 | 109 | ||
110 | // Mask | ||
111 | |||
112 | filter(std::string name, bool internal, filter subfilter); | ||
113 | |||
114 | const std::string& getMaskName() const; | ||
115 | |||
116 | bool isMaskInternal() const; | ||
117 | |||
118 | const filter& getMaskFilter() const; | ||
119 | |||
109 | // Negation | 120 | // Negation |
110 | 121 | ||
111 | filter operator!() const; | 122 | filter operator!() const; |
@@ -118,6 +129,10 @@ namespace verbly { | |||
118 | filter& operator&=(filter condition); | 129 | filter& operator&=(filter condition); |
119 | filter& operator|=(filter condition); | 130 | filter& operator|=(filter condition); |
120 | 131 | ||
132 | // Maskifying | ||
133 | |||
134 | static filter mask(std::string name, filter subfilter); | ||
135 | |||
121 | // Utility | 136 | // Utility |
122 | 137 | ||
123 | filter normalize(object context) const; | 138 | filter normalize(object context) const; |
@@ -141,6 +156,11 @@ namespace verbly { | |||
141 | std::list<filter> children; | 156 | std::list<filter> children; |
142 | bool orlogic; | 157 | bool orlogic; |
143 | } group_; | 158 | } group_; |
159 | struct { | ||
160 | std::string name; | ||
161 | bool internal; | ||
162 | std::unique_ptr<filter> subfilter; | ||
163 | } mask_; | ||
144 | }; | 164 | }; |
145 | type type_ = type::empty; | 165 | type type_ = type::empty; |
146 | 166 | ||
diff --git a/lib/statement.cpp b/lib/statement.cpp index e84a402..5dd3789 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp | |||
@@ -594,6 +594,18 @@ namespace verbly { | |||
594 | 594 | ||
595 | return grp; | 595 | return grp; |
596 | } | 596 | } |
597 | |||
598 | case filter::type::mask: | ||
599 | { | ||
600 | condition result = parseFilter(clause.getMaskFilter()); | ||
601 | |||
602 | if (result.getType() == condition::type::empty) | ||
603 | { | ||
604 | return {}; | ||
605 | } else { | ||
606 | return result; | ||
607 | } | ||
608 | } | ||
597 | } | 609 | } |
598 | } | 610 | } |
599 | 611 | ||
diff --git a/lib/word.cpp b/lib/word.cpp index dc269c9..6f0fe22 100644 --- a/lib/word.cpp +++ b/lib/word.cpp | |||
@@ -172,20 +172,24 @@ namespace verbly { | |||
172 | 172 | ||
173 | filter word::synonyms_field::operator%=(filter joinCondition) const | 173 | filter word::synonyms_field::operator%=(filter joinCondition) const |
174 | { | 174 | { |
175 | return (verbly::notion::words %= ( | 175 | return (verbly::word::notions %= |
176 | std::move(joinCondition) | 176 | filter("synonyms", true, |
177 | && (filter( | 177 | (verbly::notion::words %= ( |
178 | verbly::word::id, | 178 | std::move(joinCondition) |
179 | filter::comparison::field_does_not_equal, | 179 | && (filter( |
180 | verbly::word::id)))); | 180 | verbly::word::id, |
181 | filter::comparison::field_does_not_equal, | ||
182 | verbly::word::id)))))); | ||
181 | } | 183 | } |
182 | 184 | ||
183 | word::synonyms_field::operator filter() const | 185 | word::synonyms_field::operator filter() const |
184 | { | 186 | { |
185 | return (verbly::notion::words %= filter( | 187 | return (verbly::word::notions %= |
186 | verbly::word::id, | 188 | filter("synonyms", true, |
187 | filter::comparison::field_does_not_equal, | 189 | (verbly::notion::words %= filter( |
188 | verbly::word::id)); | 190 | verbly::word::id, |
191 | filter::comparison::field_does_not_equal, | ||
192 | verbly::word::id)))); | ||
189 | } | 193 | } |
190 | 194 | ||
191 | }; | 195 | }; |