Skip to content

Commit 8d8fcf5

Browse files
Add support for modifier as-bool.
1 parent fbcc650 commit 8d8fcf5

3 files changed

Lines changed: 101 additions & 2 deletions

File tree

doc/user/ModifierReference.en.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@ Modifiers
109109
An empty field is changed to "Delain", while if there is already a value, a comma is added before
110110
adding "Delain".
111111

112+
.. modifier:: as-bool
113+
114+
Coerce the feature to a Boolean if possible. The following types can be coerced
115+
116+
Boolean
117+
Identity.
118+
Integer
119+
0 is false, any other value is true.
120+
Float
121+
0.0 is false, anything else is true.
122+
String
123+
False unless the string is one of "true", "1", "on", "enable", "Y", "yes".
124+
IP Address
125+
A valid IP address is true, otherwise false.
126+
Duration
127+
A non-zero duration is true, otherwise false.
128+
Tuple
129+
A non-zero length tuple is true, otherwise false. Note the value(s) in the tuple are not
130+
examined.
131+
Null
132+
False.
133+
112134
.. modifier:: as-integer
113135

114136
Coerce the feature to an Integer type if possible. If the feature is already an Integer, it is

plugin/src/Modifier.cc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,82 @@ Mod_concat::load(Config &cfg, YAML::Node, TextView, TextView, YAML::Node key_val
829829

830830
// ---
831831

832+
/// Convert the feature to boolean.
833+
class Mod_as_bool : public Modifier
834+
{
835+
using self_type = Mod_as_bool;
836+
using super_type = Modifier;
837+
838+
public:
839+
inline static const std::string KEY = "as-bool"; ///< Identifier name.
840+
841+
/** Modify the feature.
842+
*
843+
* @param ctx Run time context.
844+
* @param feature Feature to modify [in,out]
845+
* @return Errors, if any.
846+
*/
847+
Rv<Feature> operator()(Context &ctx, Feature &feature) override;
848+
849+
/** Check if @a ftype is a valid type to be modified.
850+
*
851+
* @param ftype Type of feature to modify.
852+
* @return @c true if this modifier can modity that feature type, @c false if not.
853+
*/
854+
bool is_valid_for(ActiveType const &ex_type) const override;
855+
856+
/// Resulting type of feature after modifying.
857+
ActiveType result_type(ActiveType const &) const override;
858+
859+
/** Create an instance from YAML config.
860+
*
861+
* @param cfg Configuration state object.
862+
* @param mod_node Node with modifier.
863+
* @param key_node Node in @a mod_node that identifies the modifier.
864+
* @return A constructed instance or errors.
865+
*/
866+
static Rv<Handle> load(Config &cfg, YAML::Node node, TextView key, TextView arg, YAML::Node key_value);
867+
868+
protected:
869+
inline static const auto VALUE_TYPES = MaskFor({STRING, INTEGER, FLOAT, BOOLEAN, TUPLE, IP_ADDR, NIL});
870+
Expr _value; ///< Default value.
871+
872+
explicit Mod_as_bool(Expr &&expr) : _value(std::move(expr)) {}
873+
};
874+
875+
bool
876+
Mod_as_bool::is_valid_for(ActiveType const &ex_type) const
877+
{
878+
return ex_type.can_satisfy(VALUE_TYPES);
879+
}
880+
881+
ActiveType
882+
Mod_as_bool::result_type(ActiveType const &) const
883+
{
884+
return {BOOLEAN};
885+
}
886+
887+
Rv<Feature>
888+
Mod_as_bool::operator()(Context &, Feature &feature)
889+
{
890+
return { feature.as_bool() };
891+
}
892+
893+
Rv<Modifier::Handle>
894+
Mod_as_bool::load(Config &cfg, YAML::Node, TextView, TextView, YAML::Node key_value)
895+
{
896+
auto &&[expr, errata]{cfg.parse_expr(key_value)};
897+
if (!errata.is_ok()) {
898+
errata.note(R"(While parsing "{}" modifier at {}.)", KEY, key_value.Mark());
899+
return std::move(errata);
900+
}
901+
if (!(expr.is_null() || expr.result_type().can_satisfy(VALUE_TYPES))) {
902+
return Errata(S_ERROR, "Value of {} modifier is not of type {}.", KEY, VALUE_TYPES);
903+
}
904+
return Handle(new self_type{std::move(expr)});
905+
}
906+
907+
// --- //
832908
/// Convert the feature to an Integer.
833909
class Mod_as_integer : public Modifier
834910
{
@@ -1253,6 +1329,7 @@ namespace
12531329
Modifier::define(Mod_else::KEY, &Mod_else::load);
12541330
Modifier::define(Mod_join::KEY, &Mod_join::load);
12551331
Modifier::define(Mod_concat::KEY, &Mod_concat::load);
1332+
Modifier::define(Mod_as_bool::KEY, &Mod_as_bool::load);
12561333
Modifier::define(Mod_as_integer::KEY, &Mod_as_integer::load);
12571334
Modifier::define(Mod_As_Duration::KEY, &Mod_As_Duration::load);
12581335
Modifier::define(Mod_filter::KEY, &Mod_filter::load);

plugin/src/ip_space.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ Ex_ip_col::validate(Config &cfg, Spec &spec, const TextView &arg)
964964
} else {
965965
info._arg = cfg.localize(arg);
966966
info._idx = INVALID_IDX;
967-
return {{STRING, INTEGER, IP_ADDR, TUPLE}};
967+
return {{NIL, STRING, INTEGER, IP_ADDR, TUPLE}};
968968
}
969969

970970
ActiveType result_type = NIL;
@@ -987,7 +987,7 @@ Ex_ip_col::validate(Config &cfg, Spec &spec, const TextView &arg)
987987
result_type = TUPLE;
988988
break;
989989
}
990-
return result_type;
990+
return {{ NIL, result_type }}; // any column can return @c NIL if the address isn't found.
991991
}
992992

993993
Feature

0 commit comments

Comments
 (0)