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 | }; |
