From 494e19b3c27e6a1eb63b39c245ad4024702e883b Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 1 Apr 2018 11:33:21 -0400 Subject: Converted verbly::filter to use a variant object --- CMakeLists.txt | 4 + lib/filter.cpp | 1108 ++++++++++++++++++++------------------------------------ lib/filter.h | 77 ++-- vendor/hkutil | 2 +- 4 files changed, 434 insertions(+), 757 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d4f476..8dd2792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,10 @@ pkg_check_modules(sqlite3 sqlite3>=3.8.3 REQUIRED) set(CMAKE_BUILD_TYPE Debug) +include_directories( + vendor/hkutil + vendor/hkutil/vendor) + add_library(verbly lib/filter.cpp lib/field.cpp lib/notion.cpp lib/word.cpp lib/frame.cpp lib/part.cpp lib/form.cpp lib/pronunciation.cpp lib/statement.cpp lib/binding.cpp lib/database.cpp lib/token.cpp lib/part.cpp) set_property(TARGET verbly PROPERTY CXX_STANDARD 11) set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/lib/filter.cpp b/lib/filter.cpp index fec0fd3..592b190 100644 --- a/lib/filter.cpp +++ b/lib/filter.cpp @@ -10,497 +10,6 @@ namespace verbly { - filter::filter(const filter& other) - { - type_ = other.type_; - - switch (type_) - { - case type::empty: - { - break; - } - - case type::singleton: - { - new(&singleton_.filterField) field(other.singleton_.filterField); - singleton_.filterType = other.singleton_.filterType; - - switch (singleton_.filterType) - { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - { - singleton_.intValue = other.singleton_.intValue; - - break; - } - - case comparison::boolean_equals: - { - singleton_.boolValue = other.singleton_.boolValue; - - break; - } - - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - new(&singleton_.stringValue) std::string(other.singleton_.stringValue); - - break; - } - - case comparison::is_null: - case comparison::is_not_null: - { - break; - } - - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - new(&singleton_.join) std::unique_ptr(new filter(*other.singleton_.join)); - - break; - } - - case comparison::field_equals: - case comparison::field_does_not_equal: - { - new(&singleton_.compareField) field(other.singleton_.compareField); - - break; - } - } - - break; - } - - case type::group: - { - new(&group_.children) std::list(other.group_.children); - group_.orlogic = other.group_.orlogic; - - break; - } - - case type::mask: - { - new(&mask_.name) std::string(other.mask_.name); - mask_.internal = other.mask_.internal; - new(&mask_.subfilter) std::unique_ptr(new filter(*other.mask_.subfilter)); - - break; - } - } - } - - filter::filter(filter&& other) : filter() - { - swap(*this, other); - } - - filter& filter::operator=(filter other) - { - swap(*this, other); - - return *this; - } - - void swap(filter& first, filter& second) - { - using type = filter::type; - using comparison = filter::comparison; - - type tempType = first.type_; - field tempField; - comparison tempComparison; - std::unique_ptr tempJoin; - std::string tempStringValue; - int tempIntValue; - bool tempBoolValue; - field tempCompareField; - std::list tempChildren; - bool tempOrlogic; - std::string tempMaskName; - bool tempMaskInternal; - std::unique_ptr tempMaskSubfilter; - - switch (tempType) - { - case type::empty: - { - break; - } - - case type::singleton: - { - tempField = std::move(first.singleton_.filterField); - tempComparison = first.singleton_.filterType; - - switch (tempComparison) - { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - { - tempIntValue = first.singleton_.intValue; - - break; - } - - case comparison::boolean_equals: - { - tempBoolValue = first.singleton_.boolValue; - - break; - } - - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - tempStringValue = std::move(first.singleton_.stringValue); - - break; - } - - case comparison::is_null: - case comparison::is_not_null: - { - break; - } - - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - tempJoin = std::move(first.singleton_.join); - - break; - } - - case comparison::field_equals: - case comparison::field_does_not_equal: - { - tempCompareField = std::move(first.singleton_.compareField); - - break; - } - } - - break; - } - - case type::group: - { - tempChildren = std::move(first.group_.children); - tempOrlogic = first.group_.orlogic; - - break; - } - - case type::mask: - { - tempMaskName = std::move(first.mask_.name); - tempMaskInternal = first.mask_.internal; - tempMaskSubfilter = std::move(first.mask_.subfilter); - - break; - } - } - - first.~filter(); - - first.type_ = second.type_; - - switch (first.type_) - { - case type::empty: - { - break; - } - - case type::singleton: - { - new(&first.singleton_.filterField) field(std::move(second.singleton_.filterField)); - first.singleton_.filterType = second.singleton_.filterType; - - switch (first.singleton_.filterType) - { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - { - first.singleton_.intValue = second.singleton_.intValue; - - break; - } - - case comparison::boolean_equals: - { - first.singleton_.boolValue = second.singleton_.boolValue; - - break; - } - - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - new(&first.singleton_.stringValue) std::string(std::move(second.singleton_.stringValue)); - - break; - } - - case comparison::is_null: - case comparison::is_not_null: - { - break; - } - - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - new(&first.singleton_.join) std::unique_ptr(std::move(second.singleton_.join)); - - break; - } - - case comparison::field_equals: - case comparison::field_does_not_equal: - { - new(&first.singleton_.compareField) field(std::move(second.singleton_.compareField)); - - break; - } - } - - break; - } - - case type::group: - { - new(&first.group_.children) std::list(std::move(second.group_.children)); - first.group_.orlogic = second.group_.orlogic; - - break; - } - - case type::mask: - { - new(&first.mask_.name) std::string(std::move(second.mask_.name)); - first.mask_.internal = second.mask_.internal; - new(&first.mask_.subfilter) std::unique_ptr(std::move(second.mask_.subfilter)); - - break; - } - } - - second.~filter(); - - second.type_ = tempType; - - switch (second.type_) - { - case type::empty: - { - break; - } - - case type::singleton: - { - new(&second.singleton_.filterField) field(std::move(tempField)); - second.singleton_.filterType = tempComparison; - - switch (second.singleton_.filterType) - { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - { - second.singleton_.intValue = tempIntValue; - - break; - } - - case comparison::boolean_equals: - { - second.singleton_.boolValue = tempBoolValue; - - break; - } - - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - new(&second.singleton_.stringValue) std::string(std::move(tempStringValue)); - - break; - } - - case comparison::is_null: - case comparison::is_not_null: - { - break; - } - - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - new(&second.singleton_.join) std::unique_ptr(std::move(tempJoin)); - - break; - } - - case comparison::field_equals: - case comparison::field_does_not_equal: - { - new(&second.singleton_.compareField) field(std::move(tempCompareField)); - - break; - } - } - - break; - } - - case type::group: - { - new(&second.group_.children) std::list(std::move(tempChildren)); - second.group_.orlogic = tempOrlogic; - - break; - } - - case type::mask: - { - new(&first.mask_.name) std::string(std::move(tempMaskName)); - first.mask_.internal = tempMaskInternal; - new(&first.mask_.subfilter) std::unique_ptr(std::move(tempMaskSubfilter)); - - break; - } - } - } - - filter::~filter() - { - switch (type_) - { - case type::empty: - { - break; - } - - case type::singleton: - { - singleton_.filterField.~field(); - - switch (singleton_.filterType) - { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - case comparison::boolean_equals: - case comparison::is_null: - case comparison::is_not_null: - { - break; - } - - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - using string_type = std::string; - - singleton_.stringValue.~string_type(); - - break; - } - - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - using ptr_type = std::unique_ptr; - - singleton_.join.~ptr_type(); - - break; - } - - case comparison::field_equals: - case comparison::field_does_not_equal: - { - singleton_.compareField.~field(); - - break; - } - } - - break; - } - - case type::group: - { - using list_type = std::list; - - group_.children.~list_type(); - - break; - } - - case type::mask: - { - using string_type = std::string; - using ptr_type = std::unique_ptr; - - mask_.name.~string_type(); - mask_.subfilter.~ptr_type(); - - break; - } - } - } - - filter::filter() - { - } - filter::filter( field filterField, comparison filterType, @@ -518,9 +27,12 @@ namespace verbly { case comparison::int_is_at_most: case comparison::int_is_less_than: { - new(&singleton_.filterField) field(std::move(filterField)); - singleton_.filterType = filterType; - singleton_.intValue = filterValue; + variant_ = singleton_type + { + std::move(filterField), + filterType, + filterValue + }; break; } @@ -543,7 +55,8 @@ namespace verbly { } } } else { - throw std::domain_error("Cannot match a non-integer field against an integer value"); + throw std::domain_error( + "Cannot match a non-integer field against an integer value"); } } @@ -562,9 +75,12 @@ namespace verbly { case comparison::string_is_like: case comparison::string_is_not_like: { - new(&singleton_.filterField) field(std::move(filterField)); - singleton_.filterType = filterType; - new(&singleton_.stringValue) std::string(std::move(filterValue)); + variant_ = singleton_type + { + std::move(filterField), + filterType, + std::move(filterValue) + }; break; } @@ -589,7 +105,8 @@ namespace verbly { } } } else { - throw std::domain_error("Cannot match a non-string field against an string value"); + throw std::domain_error( + "Cannot match a non-string field against an string value"); } } @@ -605,9 +122,12 @@ namespace verbly { { case comparison::boolean_equals: { - new(&singleton_.filterField) field(std::move(filterField)); - singleton_.filterType = filterType; - singleton_.boolValue = filterValue; + variant_ = singleton_type + { + std::move(filterField), + filterType, + filterValue + }; break; } @@ -635,7 +155,8 @@ namespace verbly { } } } else { - throw std::domain_error("Cannot match a non-boolean field against a boolean value"); + throw std::domain_error( + "Cannot match a non-boolean field against a boolean value"); } } @@ -651,8 +172,11 @@ namespace verbly { case comparison::is_null: case comparison::is_not_null: { - new(&singleton_.filterField) field(std::move(filterField)); - singleton_.filterType = filterType; + variant_ = singleton_type + { + std::move(filterField), + filterType + }; break; } @@ -675,11 +199,13 @@ namespace verbly { case comparison::field_equals: case comparison::field_does_not_equal: { - throw std::invalid_argument("Incorrect constructor for given comparison"); + throw std::invalid_argument( + "Incorrect constructor for given comparison"); } } } else { - throw std::domain_error("Cannot check nullity/non-nullity of non-nullable field"); + throw std::domain_error( + "Cannot check nullity/non-nullity of non-nullable field"); } } @@ -701,9 +227,12 @@ namespace verbly { case comparison::matches: case comparison::does_not_match: { - new(&singleton_.filterField) field(std::move(joinOn)); - singleton_.filterType = filterType; - new(&singleton_.join) std::unique_ptr(new filter(std::move(joinCondition))); + variant_ = singleton_type + { + std::move(joinOn), + filterType, + rec_filter(new filter(std::move(joinCondition))) + }; break; } @@ -726,7 +255,8 @@ namespace verbly { case comparison::field_equals: case comparison::field_does_not_equal: { - throw std::invalid_argument("Incorrect constructor for given comparison"); + throw std::invalid_argument( + "Incorrect constructor for given comparison"); } } @@ -740,9 +270,12 @@ namespace verbly { case comparison::hierarchally_matches: case comparison::does_not_hierarchally_match: { - new(&singleton_.filterField) field(std::move(joinOn)); - singleton_.filterType = filterType; - new(&singleton_.join) std::unique_ptr(new filter(std::move(joinCondition))); + variant_ = singleton_type + { + std::move(joinOn), + filterType, + rec_filter(new filter(std::move(joinCondition))) + }; break; } @@ -765,7 +298,8 @@ namespace verbly { case comparison::field_equals: case comparison::field_does_not_equal: { - throw std::invalid_argument("Incorrect constructor for given comparison"); + throw std::invalid_argument( + "Incorrect constructor for given comparison"); } } @@ -803,9 +337,12 @@ namespace verbly { throw std::domain_error("Cannot compare join fields"); } - new(&singleton_.filterField) field(std::move(filterField)); - singleton_.filterType = filterType; - new(&singleton_.compareField) field(std::move(compareField)); + variant_ = singleton_type + { + std::move(filterField), + filterType, + std::move(compareField) + }; break; } @@ -835,146 +372,155 @@ namespace verbly { field filter::getField() const { - if (type_ == type::singleton) + if (type_ != type::singleton) { - return singleton_.filterField; - } else { throw std::domain_error("This filter does not have a field"); } + + return mpark::get(variant_).filterField; } filter::comparison filter::getComparison() const { - if (type_ == type::singleton) + if (type_ != type::singleton) { - return singleton_.filterType; - } else { throw std::domain_error("This filter does not have a comparison"); } + + return mpark::get(variant_).filterType; } filter filter::getJoinCondition() const { - if (type_ == type::singleton) + if (type_ != type::singleton) + { + throw std::domain_error("This filter does not have a join condition"); + } + + const singleton_type& ss = mpark::get(variant_); + + switch (ss.filterType) { - switch (singleton_.filterType) + case comparison::matches: + case comparison::does_not_match: + case comparison::hierarchally_matches: + case comparison::does_not_hierarchally_match: { - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - { - return *singleton_.join; - } + return *mpark::get(ss.data); + } - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - case comparison::boolean_equals: - case comparison::is_null: - case comparison::is_not_null: - case comparison::field_equals: - case comparison::field_does_not_equal: - { - throw std::domain_error("This filter does not have a join condition"); - } + case comparison::string_equals: + case comparison::string_does_not_equal: + case comparison::string_is_like: + case comparison::string_is_not_like: + case comparison::int_equals: + case comparison::int_does_not_equal: + case comparison::int_is_at_least: + case comparison::int_is_greater_than: + case comparison::int_is_at_most: + case comparison::int_is_less_than: + case comparison::boolean_equals: + case comparison::is_null: + case comparison::is_not_null: + case comparison::field_equals: + case comparison::field_does_not_equal: + { + throw std::domain_error("This filter does not have a join condition"); } - } else { - throw std::domain_error("This filter does not have a join condition"); } } std::string filter::getStringArgument() const { - if (type_ == type::singleton) + if (type_ != type::singleton) + { + throw std::domain_error("This filter does not have a string argument"); + } + + const singleton_type& ss = mpark::get(variant_); + + switch (ss.filterType) { - switch (singleton_.filterType) + case comparison::string_equals: + case comparison::string_does_not_equal: + case comparison::string_is_like: + case comparison::string_is_not_like: { - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - { - return singleton_.stringValue; - } + return mpark::get(ss.data); + } - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - case comparison::boolean_equals: - case comparison::is_null: - case comparison::is_not_null: - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - case comparison::field_equals: - case comparison::field_does_not_equal: - { - throw std::domain_error("This filter does not have a string argument"); - } + case comparison::int_equals: + case comparison::int_does_not_equal: + case comparison::int_is_at_least: + case comparison::int_is_greater_than: + case comparison::int_is_at_most: + case comparison::int_is_less_than: + case comparison::boolean_equals: + case comparison::is_null: + case comparison::is_not_null: + case comparison::matches: + case comparison::does_not_match: + case comparison::hierarchally_matches: + case comparison::does_not_hierarchally_match: + case comparison::field_equals: + case comparison::field_does_not_equal: + { + throw std::domain_error("This filter does not have a string argument"); } - } else { - throw std::domain_error("This filter does not have a string argument"); } } int filter::getIntegerArgument() const { - if (type_ == type::singleton) + if (type_ != type::singleton) + { + throw std::domain_error("This filter does not have an integer argument"); + } + + const singleton_type& ss = mpark::get(variant_); + + switch (ss.filterType) { - switch (singleton_.filterType) + case comparison::int_equals: + case comparison::int_does_not_equal: + case comparison::int_is_at_least: + case comparison::int_is_greater_than: + case comparison::int_is_at_most: + case comparison::int_is_less_than: { - case comparison::int_equals: - case comparison::int_does_not_equal: - case comparison::int_is_at_least: - case comparison::int_is_greater_than: - case comparison::int_is_at_most: - case comparison::int_is_less_than: - { - return singleton_.intValue; - } + return mpark::get(ss.data); + } - case comparison::string_equals: - case comparison::string_does_not_equal: - case comparison::string_is_like: - case comparison::string_is_not_like: - case comparison::boolean_equals: - case comparison::is_null: - case comparison::is_not_null: - case comparison::matches: - case comparison::does_not_match: - case comparison::hierarchally_matches: - case comparison::does_not_hierarchally_match: - case comparison::field_equals: - case comparison::field_does_not_equal: - { - throw std::domain_error("This filter does not have an integer argument"); - } + case comparison::string_equals: + case comparison::string_does_not_equal: + case comparison::string_is_like: + case comparison::string_is_not_like: + case comparison::boolean_equals: + case comparison::is_null: + case comparison::is_not_null: + case comparison::matches: + case comparison::does_not_match: + case comparison::hierarchally_matches: + case comparison::does_not_hierarchally_match: + case comparison::field_equals: + case comparison::field_does_not_equal: + { + throw std::domain_error( + "This filter does not have an integer argument"); } - } else { - throw std::domain_error("This filter does not have an integer argument"); } } bool filter::getBooleanArgument() const { - if ((type_ == type::singleton) && (singleton_.filterType == comparison::boolean_equals)) + if ((type_ != type::singleton) || + (mpark::get(variant_).filterType != + comparison::boolean_equals)) { - return singleton_.boolValue; - } else { throw std::domain_error("This filter does not have a boolean argument"); } + + return mpark::get(mpark::get(variant_).data); } field filter::getCompareField() const @@ -984,12 +530,14 @@ namespace verbly { throw std::domain_error("This filter does not have a compare field"); } - switch (singleton_.filterType) + const singleton_type& ss = mpark::get(variant_); + + switch (ss.filterType) { case comparison::field_equals: case comparison::field_does_not_equal: { - return singleton_.compareField; + return mpark::get(ss.data); break; } @@ -1018,20 +566,20 @@ namespace verbly { } - filter::filter(bool orlogic) : type_(type::group) + filter::filter(bool orlogic) : + type_(type::group), + variant_(group_type {{}, orlogic}) { - new(&group_.children) std::list(); - group_.orlogic = orlogic; } bool filter::getOrlogic() const { - if (type_ == type::group) + if (type_ != type::group) { - return group_.orlogic; - } else { throw std::domain_error("This filter is not a group filter"); } + + return mpark::get(variant_).orlogic; } filter filter::operator+(filter condition) const @@ -1044,72 +592,77 @@ namespace verbly { filter& filter::operator+=(filter condition) { - if (type_ == type::group) + if (type_ != type::group) { - group_.children.push_back(std::move(condition)); - - return *this; - } else { throw std::domain_error("Children can only be added to group filters"); } + + mpark::get(variant_).children.push_back(std::move(condition)); + + return *this; } filter::const_iterator filter::begin() const { - if (type_ == type::group) + if (type_ != type::group) { - return std::begin(group_.children); - } else { throw std::domain_error("This filter has no children"); } + + return std::begin(mpark::get(variant_).children); } filter::const_iterator filter::end() const { - if (type_ == type::group) + if (type_ != type::group) { - return std::end(group_.children); - } else { throw std::domain_error("This filter has no children"); } + + return std::end(mpark::get(variant_).children); } - filter::filter(std::string name, bool internal, filter subfilter) : - type_(type::mask) + filter::filter( + std::string name, + bool internal, + filter subfilter) : + type_(type::mask), + variant_(mask_type { + std::move(name), + internal, + rec_filter(new filter(std::move(subfilter))) + }) { - new(&mask_.name) std::string(std::move(name)); - mask_.internal = internal; - new(&mask_.subfilter) std::unique_ptr(new filter(std::move(subfilter))); } const std::string& filter::getMaskName() const { - if (type_ == type::mask) + if (type_ != type::mask) { - return mask_.name; - } else { throw std::domain_error("This filter is not a mask filter"); } + + return mpark::get(variant_).name; } bool filter::isMaskInternal() const { - if (type_ == type::mask) + if (type_ != type::mask) { - return mask_.internal; - } else { throw std::domain_error("This filter is not a mask filter"); } + + return mpark::get(variant_).internal; } const filter& filter::getMaskFilter() const { - if (type_ == type::mask) + if (type_ != type::mask) { - return *mask_.subfilter; - } else { throw std::domain_error("This filter is not a mask filter"); } + + return *mpark::get(variant_).subfilter; } filter filter::operator!() const @@ -1123,110 +676,169 @@ namespace verbly { case type::singleton: { - switch (singleton_.filterType) + const singleton_type& ss = mpark::get(variant_); + + switch (ss.filterType) { case comparison::int_equals: { - return filter(singleton_.filterField, comparison::int_does_not_equal, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_does_not_equal, + mpark::get(ss.data)); } case comparison::int_does_not_equal: { - return filter(singleton_.filterField, comparison::int_equals, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_equals, + mpark::get(ss.data)); } case comparison::int_is_at_least: { - return filter(singleton_.filterField, comparison::int_is_less_than, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_is_less_than, + mpark::get(ss.data)); } case comparison::int_is_greater_than: { - return filter(singleton_.filterField, comparison::int_is_at_most, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_is_at_most, + mpark::get(ss.data)); } case comparison::int_is_at_most: { - return filter(singleton_.filterField, comparison::int_is_greater_than, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_is_greater_than, + mpark::get(ss.data)); } case comparison::int_is_less_than: { - return filter(singleton_.filterField, comparison::int_is_at_least, singleton_.intValue); + return filter( + ss.filterField, + comparison::int_is_at_least, + mpark::get(ss.data)); } case comparison::boolean_equals: { - return filter(singleton_.filterField, comparison::boolean_equals, !singleton_.boolValue); + return filter( + ss.filterField, + comparison::boolean_equals, + !mpark::get(ss.data)); } case comparison::string_equals: { - return filter(singleton_.filterField, comparison::string_does_not_equal, singleton_.stringValue); + return filter( + ss.filterField, + comparison::string_does_not_equal, + mpark::get(ss.data)); } case comparison::string_does_not_equal: { - return filter(singleton_.filterField, comparison::string_equals, singleton_.stringValue); + return filter( + ss.filterField, + comparison::string_equals, + mpark::get(ss.data)); } case comparison::string_is_like: { - return filter(singleton_.filterField, comparison::string_is_not_like, singleton_.stringValue); + return filter( + ss.filterField, + comparison::string_is_not_like, + mpark::get(ss.data)); } case comparison::string_is_not_like: { - return filter(singleton_.filterField, comparison::string_is_like, singleton_.stringValue); + return filter( + ss.filterField, + comparison::string_is_like, + mpark::get(ss.data)); } case comparison::is_null: { - return filter(singleton_.filterField, comparison::is_not_null); + return filter( + ss.filterField, + comparison::is_not_null); } case comparison::is_not_null: { - return filter(singleton_.filterField, comparison::is_null); + return filter( + ss.filterField, + comparison::is_null); } case comparison::matches: { - return filter(singleton_.filterField, comparison::does_not_match, *singleton_.join); + return filter( + ss.filterField, + comparison::does_not_match, + *mpark::get(ss.data)); } case comparison::does_not_match: { - return filter(singleton_.filterField, comparison::matches, *singleton_.join); + return filter( + ss.filterField, + comparison::matches, + *mpark::get(ss.data)); } case comparison::hierarchally_matches: { - return filter(singleton_.filterField, comparison::does_not_hierarchally_match, *singleton_.join); + return filter( + ss.filterField, + comparison::does_not_hierarchally_match, + *mpark::get(ss.data)); } case comparison::does_not_hierarchally_match: { - return filter(singleton_.filterField, comparison::hierarchally_matches, *singleton_.join); + return filter( + ss.filterField, + comparison::hierarchally_matches, + *mpark::get(ss.data)); } case comparison::field_equals: { - return filter(singleton_.filterField, comparison::field_does_not_equal, singleton_.compareField); + return filter( + ss.filterField, + comparison::field_does_not_equal, + mpark::get(ss.data)); } case comparison::field_does_not_equal: { - return filter(singleton_.filterField, comparison::field_equals, singleton_.compareField); + return filter( + ss.filterField, + comparison::field_equals, + mpark::get(ss.data)); } } } case type::group: { - filter result(!group_.orlogic); + const group_type& gg = mpark::get(variant_); - for (const filter& child : group_.children) + filter result(!gg.orlogic); + + for (const filter& child : gg.children) { result += !child; } @@ -1236,7 +848,9 @@ namespace verbly { case type::mask: { - return {mask_.name, mask_.internal, !*mask_.subfilter}; + const mask_type& mm = mpark::get(variant_); + + return {mm.name, mm.internal, !*mm.subfilter}; } } } @@ -1264,24 +878,35 @@ namespace verbly { case type::mask: { filter result(false); - result.group_.children.push_back(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(*this); + gg.children.push_back(std::move(condition)); return result; } case type::group: { - if (group_.orlogic) + const group_type& og = mpark::get(variant_); + + if (og.orlogic) { filter result(false); - result.group_.children.push_back(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(*this); + gg.children.push_back(std::move(condition)); return result; } else { filter result(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(std::move(condition)); return result; } @@ -1302,24 +927,35 @@ namespace verbly { case type::mask: { filter result(true); - result.group_.children.push_back(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(*this); + gg.children.push_back(std::move(condition)); return result; } case type::group: { - if (!group_.orlogic) + const group_type& og = mpark::get(variant_); + + if (!og.orlogic) { filter result(true); - result.group_.children.push_back(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(*this); + gg.children.push_back(std::move(condition)); return result; } else { filter result(*this); - result.group_.children.push_back(std::move(condition)); + + group_type& gg = mpark::get(result.variant_); + + gg.children.push_back(std::move(condition)); return result; } @@ -1344,6 +980,8 @@ namespace verbly { case type::singleton: { + const singleton_type& ss = mpark::get(variant_); + // First, switch on the normalized context, and then switch on the // current context. We recursively recontextualize by using the // current filter as a subquery for a join such that the context of @@ -1361,7 +999,7 @@ namespace verbly { case object::notion: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::undefined: case object::notion: @@ -1382,7 +1020,7 @@ namespace verbly { case object::word: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::notion: { @@ -1404,13 +1042,14 @@ namespace verbly { case object::form: case object::pronunciation: { - return (verbly::word::forms(inflection::base) %= normalize(object::form)); + return (verbly::word::forms(inflection::base) %= + normalize(object::form)); } } case object::frame: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::undefined: case object::frame: @@ -1435,7 +1074,7 @@ namespace verbly { case object::part: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::undefined: case object::part: @@ -1456,14 +1095,15 @@ namespace verbly { case object::form: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::notion: case object::word: case object::frame: case object::part: { - return (verbly::form::words(inflection::base) %= normalize(object::word)); + return (verbly::form::words(inflection::base) %= + normalize(object::word)); } case object::undefined: @@ -1474,14 +1114,15 @@ namespace verbly { case object::pronunciation: { - return (verbly::form::pronunciations %= normalize(object::pronunciation)); + return (verbly::form::pronunciations %= + normalize(object::pronunciation)); } } } case object::pronunciation: { - switch (singleton_.filterField.getObject()) + switch (ss.filterField.getObject()) { case object::notion: case object::word: @@ -1489,7 +1130,8 @@ namespace verbly { case object::part: case object::form: { - return verbly::pronunciation::forms %= normalize(object::form); + return verbly::pronunciation::forms %= + normalize(object::form); } case object::undefined: @@ -1505,12 +1147,14 @@ namespace verbly { case type::group: { - filter result(group_.orlogic); + const group_type& gg = mpark::get(variant_); + + filter result(gg.orlogic); std::map positiveJoins; std::map negativeJoins; std::map, filter> masks; - for (const filter& child : group_.children) + for (const filter& child : gg.children) { filter normalized = child.normalize(context); @@ -1521,37 +1165,44 @@ namespace verbly { { case type::singleton: { + singleton_type& normSing = + mpark::get(normalized.variant_); + switch (normalized.getComparison()) { case comparison::matches: { - if (!positiveJoins.count(normalized.singleton_.filterField)) + if (!positiveJoins.count(normSing.filterField)) { - positiveJoins[normalized.getField()] = filter(group_.orlogic); + positiveJoins[normalized.getField()] = filter(gg.orlogic); } - positiveJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); + positiveJoins.at(normalized.getField()) += + std::move(*mpark::get(normSing.data)); break; } case comparison::does_not_match: { - if (!negativeJoins.count(normalized.singleton_.filterField)) + if (!negativeJoins.count(normSing.filterField)) { - negativeJoins[normalized.getField()] = filter(!group_.orlogic); + negativeJoins[normalized.getField()] = + filter(!gg.orlogic); } - negativeJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); + negativeJoins.at(normalized.getField()) += + std::move(*mpark::get(normSing.data)); break; } case comparison::hierarchally_matches: { - if (group_.orlogic) + if (gg.orlogic) { - positiveJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); + positiveJoins[normalized.getField()] |= + std::move(*mpark::get(normSing.data)); } else { result += std::move(normalized); } @@ -1561,9 +1212,10 @@ namespace verbly { case comparison::does_not_hierarchally_match: { - if (!group_.orlogic) + if (!gg.orlogic) { - negativeJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); + negativeJoins[normalized.getField()] |= + std::move(*mpark::get(normSing.data)); } else { result += std::move(normalized); } @@ -1606,14 +1258,20 @@ namespace verbly { case type::mask: { - auto maskId = std::tie(normalized.mask_.name, normalized.mask_.internal); + mask_type& normMask = + mpark::get(normalized.variant_); + + auto maskId = + std::tie( + normMask.name, + normMask.internal); if (!masks.count(maskId)) { - masks[maskId] = filter(group_.orlogic); + masks[maskId] = filter(gg.orlogic); } - masks.at(maskId) += std::move(*normalized.mask_.subfilter); + masks.at(maskId) += std::move(*normMask.subfilter); break; } @@ -1625,7 +1283,8 @@ namespace verbly { const field& joinOn = mapping.first; filter& joinCondition = mapping.second; - result += (joinOn %= joinCondition.normalize(joinOn.getJoinObject())); + result += + (joinOn %= joinCondition.normalize(joinOn.getJoinObject())); } for (auto& mapping : negativeJoins) @@ -1633,7 +1292,8 @@ namespace verbly { const field& joinOn = mapping.first; filter& joinCondition = mapping.second; - result += !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); + result += + !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); } for (auto& mapping : masks) @@ -1650,7 +1310,12 @@ namespace verbly { case type::mask: { - return {mask_.name, mask_.internal, mask_.subfilter->normalize(context)}; + const mask_type& mm = mpark::get(variant_); + + return { + mm.name, + mm.internal, + mm.subfilter->normalize(context)}; } } } @@ -1668,8 +1333,10 @@ namespace verbly { case type::group: { - filter result(group_.orlogic); - for (const filter& child : group_.children) + const group_type& gg = mpark::get(variant_); + + filter result(gg.orlogic); + for (const filter& child : gg.children) { filter compactedChild = child.compact(); if (compactedChild.type_ != type::empty) @@ -1678,12 +1345,14 @@ namespace verbly { } } - if (result.group_.children.empty()) + group_type& resGroup = mpark::get(result.variant_); + + if (resGroup.children.empty()) { result = {}; - } else if (result.group_.children.size() == 1) + } else if (resGroup.children.size() == 1) { - filter tempChild = std::move(result.group_.children.front()); + filter tempChild = std::move(resGroup.children.front()); result = std::move(tempChild); } @@ -1693,13 +1362,18 @@ namespace verbly { case type::mask: { - filter subfilter = mask_.subfilter->compact(); + const mask_type& mm = mpark::get(variant_); + + filter subfilter = mm.subfilter->compact(); if (subfilter.type_ == type::empty) { return {}; } else { - return {mask_.name, mask_.internal, std::move(subfilter)}; + return { + mm.name, + mm.internal, + std::move(subfilter)}; } } } diff --git a/lib/filter.h b/lib/filter.h index 942fe18..7db2773 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -4,6 +4,8 @@ #include #include #include +#include "../vendor/hkutil/vendor/variant.hpp" +#include "../vendor/hkutil/hkutil/recptr.h" #include "field.h" #include "enums.h" @@ -11,6 +13,7 @@ namespace verbly { class filter { public: + enum class type { empty, singleton, @@ -40,23 +43,6 @@ namespace verbly { field_does_not_equal }; - // Copy and move constructors - - filter(const filter& other); - filter(filter&& other); - - // Assignment - - filter& operator=(filter other); - - // Swap - - friend void swap(filter& first, filter& second); - - // Destructor - - ~filter(); - // Accessors type getType() const @@ -66,7 +52,7 @@ namespace verbly { // Empty - filter(); + filter() = default; // Singleton @@ -140,29 +126,42 @@ namespace verbly { filter compact() const; private: - union { - struct { - field filterField; - comparison filterType; - union { - std::unique_ptr join; - std::string stringValue; - int intValue; - bool boolValue; - field compareField; - }; - } singleton_; - struct { - std::list children; - bool orlogic; - } group_; - struct { - std::string name; - bool internal; - std::unique_ptr subfilter; - } mask_; + + using rec_filter = hatkirby::recptr; + + struct singleton_type { + field filterField; + comparison filterType; + + mpark::variant< + mpark::monostate, + rec_filter, + std::string, + int, + bool, + field> data; + }; + + struct group_type { + std::list children; + bool orlogic; }; + + struct mask_type { + std::string name; + bool internal; + rec_filter subfilter; + }; + + using variant_type = + mpark::variant< + mpark::monostate, + singleton_type, + group_type, + mask_type>; + type type_ = type::empty; + variant_type variant_; }; diff --git a/vendor/hkutil b/vendor/hkutil index eb30ce1..b430eb5 160000 --- a/vendor/hkutil +++ b/vendor/hkutil @@ -1 +1 @@ -Subproject commit eb30ce13012108fe38709cdf0732aa8b2ec2d52e +Subproject commit b430eb58654298d17492a36c7bcda9f803a327fe -- cgit 1.4.1