source/FeatureMayAlwaysSet.cpp (122 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <mariana-trench/Assert.h>
#include <mariana-trench/FeatureMayAlwaysSet.h>
#include <mariana-trench/JsonValidation.h>
namespace marianatrench {
FeatureMayAlwaysSet::FeatureMayAlwaysSet(
std::initializer_list<const Feature*> features)
: set_(features) {}
FeatureMayAlwaysSet::FeatureMayAlwaysSet(
const FeatureSet& may,
const FeatureSet& always)
: set_(/* over */ may.set_, /* under */ always.set_) {}
FeatureMayAlwaysSet FeatureMayAlwaysSet::make_may(
std::initializer_list<const Feature*> features) {
auto set = sparta::PatriciaTreeSet<const Feature*>(features);
return FeatureMayAlwaysSet(OverUnderSet(/* over */ set, /* under */ {}));
}
FeatureMayAlwaysSet FeatureMayAlwaysSet::make_may(const FeatureSet& features) {
return FeatureMayAlwaysSet(
OverUnderSet(/* over */ features.set_, /* under */ {}));
}
FeatureMayAlwaysSet FeatureMayAlwaysSet::make_always(
std::initializer_list<const Feature*> features) {
auto set = sparta::PatriciaTreeSet<const Feature*>(features);
return FeatureMayAlwaysSet(OverUnderSet(/* over */ set, /* under */ set));
}
FeatureMayAlwaysSet FeatureMayAlwaysSet::make_always(
const FeatureSet& features) {
return FeatureMayAlwaysSet(
OverUnderSet(/* over */ features.set_, /* under */ features.set_));
}
FeatureSet FeatureMayAlwaysSet::may() const {
mt_assert(set_.is_value());
return FeatureSet(set_.over());
}
FeatureSet FeatureMayAlwaysSet::always() const {
mt_assert(set_.is_value());
return FeatureSet(set_.under());
}
void FeatureMayAlwaysSet::add_may(const Feature* feature) {
set_.add_over(feature);
}
void FeatureMayAlwaysSet::add_may(const FeatureSet& features) {
set_.add_over(features.set_);
}
void FeatureMayAlwaysSet::add_always(const Feature* feature) {
set_.add_under(feature);
}
void FeatureMayAlwaysSet::add_always(const FeatureSet& features) {
set_.add_under(features.set_);
}
void FeatureMayAlwaysSet::add(const FeatureMayAlwaysSet& other) {
set_.add(other.set_);
}
bool FeatureMayAlwaysSet::leq(const FeatureMayAlwaysSet& other) const {
return set_.leq(other.set_);
}
bool FeatureMayAlwaysSet::equals(const FeatureMayAlwaysSet& other) const {
return set_.equals(other.set_);
}
void FeatureMayAlwaysSet::join_with(const FeatureMayAlwaysSet& other) {
set_.join_with(other.set_);
}
void FeatureMayAlwaysSet::widen_with(const FeatureMayAlwaysSet& other) {
set_.widen_with(other.set_);
}
void FeatureMayAlwaysSet::meet_with(const FeatureMayAlwaysSet& other) {
set_.meet_with(other.set_);
}
void FeatureMayAlwaysSet::narrow_with(const FeatureMayAlwaysSet& other) {
set_.narrow_with(other.set_);
}
FeatureMayAlwaysSet FeatureMayAlwaysSet::from_json(
const Json::Value& value,
Context& context) {
auto may_features = FeatureSet{};
auto always_features = FeatureSet{};
// As long as either of the required keys are present, this will not be
// bottom(), even when the list is empty, e.g. "may_features: []".
bool is_bottom = true;
JsonValidation::validate_object(value);
if (value.isMember("may_features")) {
JsonValidation::null_or_array(value, /* field */ "may_features");
may_features.join_with(
FeatureSet::from_json(value["may_features"], context));
is_bottom = false;
}
if (value.isMember("always_features")) {
JsonValidation::null_or_array(value, /* field */ "always_features");
always_features.join_with(
FeatureSet::from_json(value["always_features"], context));
is_bottom = false;
}
return is_bottom ? FeatureMayAlwaysSet::bottom()
: FeatureMayAlwaysSet(may_features, always_features);
}
Json::Value FeatureMayAlwaysSet::to_json() const {
mt_assert(set_.is_value());
auto may_features = may();
auto always_features = always();
may_features.difference_with(always_features);
auto value = Json::Value(Json::objectValue);
if (!may_features.empty()) {
value["may_features"] = may_features.to_json();
}
if (!always_features.empty()) {
value["always_features"] = always_features.to_json();
}
return value;
}
std::ostream& operator<<(
std::ostream& out,
const FeatureMayAlwaysSet& features) {
if (features.is_top()) {
return out << "T";
} else if (features.is_bottom()) {
return out << "_|_";
} else if (features.empty()) {
return out << "{}";
} else {
return out << "{may=" << features.may() << ", always=" << features.always()
<< "}";
}
}
} // namespace marianatrench