Rename event filters to predicates

This commit is contained in:
Vftdan 2024-08-16 01:52:25 +02:00
parent 9f876162e5
commit 2208131d68
4 changed files with 241 additions and 241 deletions

190
event_predicate.c Normal file
View File

@ -0,0 +1,190 @@
#include <limits.h>
#include "event_predicate.h"
typedef struct {
size_t capacity;
size_t length;
EventPredicate *values;
} EventPredicateList;
static EventPredicateList predicates = {
.length = 0,
.capacity = 0,
.values = NULL,
};
static bool
event_predicate_list_extend(EventPredicateList * lst)
{
size_t capacity = lst->capacity;
capacity = capacity + (capacity >> 1) + 1;
EventPredicate *new_values;
if (lst->values) {
new_values = reallocarray(lst->values, capacity, sizeof(EventPredicate));
} else {
new_values = T_ALLOC(capacity, EventPredicate);
}
if (!new_values) {
return false;
}
lst->values = new_values;
lst->capacity = capacity;
return true;
}
static void
event_predicate_list_clear(EventPredicateList * lst)
{
if (lst->values) {
free(lst->values);
lst->values = NULL;
}
lst->capacity = 0;
lst->length = 0;
}
EventPredicateHandle
event_predicate_register(EventPredicate filter)
{
size_t i = predicates.length;
if (i >= INT32_MAX) {
return -1;
}
while (i <= predicates.capacity) {
event_predicate_list_extend(&predicates);
}
predicates.values[i] = filter;
predicates.length = i + 1;
return (EventPredicateHandle) i;
}
static EventPredicate*
event_predicate_get_ptr(EventPredicateHandle handle)
{
if (handle < 0 || (size_t) handle >= predicates.length) {
return NULL;
}
return &predicates.values[handle];
}
EventPredicate
event_predicate_get(EventPredicateHandle handle)
{
EventPredicate *ptr = event_predicate_get_ptr(handle);
if (ptr) {
return *ptr;
} else {
return (EventPredicate) {
.type = EVPRED_INVALID,
.enabled = false,
.inverted = false,
};
}
}
EventPredicateResult
event_predicate_apply(EventPredicateHandle handle, EventNode * event)
{
EventPredicate *ptr = event_predicate_get_ptr(handle);
if (!ptr) {
return EVPREDRES_DISABLED;
}
if (!ptr->enabled) {
return EVPREDRES_DISABLED;
}
bool accepted = false;
switch (ptr->type) {
case EVPRED_INVALID:
return EVPREDRES_DISABLED;
case EVPRED_ACCEPT:
accepted = true;
break;
case EVPRED_CODE_NS...EVPRED_PAYLOAD:
if (!event) {
return EVPREDRES_DISABLED;
}
{
int64_t actual;
switch (ptr->type) {
case EVPRED_CODE_NS:
actual = event->data.code.ns;
break;
case EVPRED_CODE_MAJOR:
actual = event->data.code.major;
break;
case EVPRED_CODE_MINOR:
actual = event->data.code.minor;
break;
case EVPRED_PAYLOAD:
actual = event->data.payload;
break;
default:
return EVPREDRES_DISABLED;
}
accepted = ptr->range_data.min_value <= actual && actual <= ptr->range_data.max_value;
}
break;
case EVPRED_CONJUNCTION:
case EVPRED_DISJUNCTION:
if (!ptr->aggregate_data.handles) {
return EVPREDRES_DISABLED;
}
{
bool disjunction = ptr->type == EVPRED_DISJUNCTION;
accepted = !disjunction;
for (size_t i = 0; i < ptr->aggregate_data.length; ++i) {
EventPredicateResult child_result = event_predicate_apply(ptr->aggregate_data.handles[i], event); // TODO protect from stack overflow
bool should_stop = false;
switch (child_result) {
case EVPREDRES_DISABLED:
continue;
case EVPREDRES_ACCEPTED:
should_stop = false;
break;
case EVPREDRES_REJECTED:
should_stop = true;
break;
}
if (disjunction) {
should_stop = !should_stop;
}
if (should_stop) {
accepted = disjunction;
break;
}
}
}
break;
}
if (ptr->inverted) {
accepted = !accepted;
}
return accepted ? EVPREDRES_ACCEPTED : EVPREDRES_REJECTED;
}
void
event_predicate_set_enabled(EventPredicateHandle handle, bool enabled)
{
EventPredicate *ptr = event_predicate_get_ptr(handle);
if (!ptr) {
return;
}
ptr->enabled = enabled;
}
void event_predicate_set_inverted(EventPredicateHandle handle, bool inverted)
{
EventPredicate *ptr = event_predicate_get_ptr(handle);
if (!ptr) {
return;
}
ptr->inverted = inverted;
}
void
event_predicate_reset()
{
event_predicate_list_clear(&predicates);
}

51
event_predicate.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef PREDS_H_
#define PREDS_H_
#include "events.h"
typedef struct event_predicate EventPredicate;
typedef int32_t EventPredicateHandle;
typedef enum {
EVPRED_INVALID,
EVPRED_ACCEPT,
// Range
EVPRED_CODE_NS,
EVPRED_CODE_MAJOR,
EVPRED_CODE_MINOR,
EVPRED_PAYLOAD,
// Aggregation
EVPRED_CONJUNCTION,
EVPRED_DISJUNCTION,
} EventPredicateType;
typedef enum {
EVPREDRES_DISABLED = -1,
EVPREDRES_REJECTED = 0,
EVPREDRES_ACCEPTED = 1,
} EventPredicateResult;
struct event_predicate {
EventPredicateType type;
bool enabled;
bool inverted;
union {
struct {
int64_t min_value;
int64_t max_value;
} range_data;
struct {
size_t length;
EventPredicateHandle *handles;
} aggregate_data;
};
};
EventPredicateHandle event_predicate_register(EventPredicate filter);
EventPredicate event_predicate_get(EventPredicateHandle handle);
EventPredicateResult event_predicate_apply(EventPredicateHandle handle, EventNode * event);
void event_predicate_set_enabled(EventPredicateHandle handle, bool enabled);
void event_predicate_set_inverted(EventPredicateHandle handle, bool inverted);
void event_predicate_reset();
#endif /* end of include guard: PREDS_H_ */

190
filters.c
View File

@ -1,190 +0,0 @@
#include <limits.h>
#include "filters.h"
typedef struct {
size_t capacity;
size_t length;
EventFilter *values;
} EventFilterList;
static EventFilterList filters = {
.length = 0,
.capacity = 0,
.values = NULL,
};
static bool
event_filter_list_extend(EventFilterList * lst)
{
size_t capacity = lst->capacity;
capacity = capacity + (capacity >> 1) + 1;
EventFilter *new_values;
if (lst->values) {
new_values = reallocarray(lst->values, capacity, sizeof(EventFilter));
} else {
new_values = T_ALLOC(capacity, EventFilter);
}
if (!new_values) {
return false;
}
lst->values = new_values;
lst->capacity = capacity;
return true;
}
static void
event_filter_list_clear(EventFilterList * lst)
{
if (lst->values) {
free(lst->values);
lst->values = NULL;
}
lst->capacity = 0;
lst->length = 0;
}
EventFilterHandle
event_filter_register(EventFilter filter)
{
size_t i = filters.length;
if (i >= INT32_MAX) {
return -1;
}
while (i <= filters.capacity) {
event_filter_list_extend(&filters);
}
filters.values[i] = filter;
filters.length = i + 1;
return (EventFilterHandle) i;
}
static EventFilter*
event_filter_get_ptr(EventFilterHandle handle)
{
if (handle < 0 || (size_t) handle >= filters.length) {
return NULL;
}
return &filters.values[handle];
}
EventFilter
event_filter_get(EventFilterHandle handle)
{
EventFilter *ptr = event_filter_get_ptr(handle);
if (ptr) {
return *ptr;
} else {
return (EventFilter) {
.type = EVFILTER_INVALID,
.enabled = false,
.inverted = false,
};
}
}
EventFilterResult
event_filter_apply(EventFilterHandle handle, EventNode * event)
{
EventFilter *ptr = event_filter_get_ptr(handle);
if (!ptr) {
return EVFILTERRES_DISABLED;
}
if (!ptr->enabled) {
return EVFILTERRES_DISABLED;
}
bool accepted = false;
switch (ptr->type) {
case EVFILTER_INVALID:
return EVFILTERRES_DISABLED;
case EVFILTER_ACCEPT:
accepted = true;
break;
case EVFILTER_CODE_NS...EVFILTER_PAYLOAD:
if (!event) {
return EVFILTERRES_DISABLED;
}
{
int64_t actual;
switch (ptr->type) {
case EVFILTER_CODE_NS:
actual = event->data.code.ns;
break;
case EVFILTER_CODE_MAJOR:
actual = event->data.code.major;
break;
case EVFILTER_CODE_MINOR:
actual = event->data.code.minor;
break;
case EVFILTER_PAYLOAD:
actual = event->data.payload;
break;
default:
return EVFILTERRES_DISABLED;
}
accepted = ptr->range_data.min_value <= actual && actual <= ptr->range_data.max_value;
}
break;
case EVFILTER_CONJUNCTION:
case EVFILTER_DISJUNCTION:
if (!ptr->aggregate_data.handles) {
return EVFILTERRES_DISABLED;
}
{
bool disjunction = ptr->type == EVFILTER_DISJUNCTION;
accepted = !disjunction;
for (size_t i = 0; i < ptr->aggregate_data.length; ++i) {
EventFilterResult child_result = event_filter_apply(ptr->aggregate_data.handles[i], event); // TODO protect from stack overflow
bool should_stop = false;
switch (child_result) {
case EVFILTERRES_DISABLED:
continue;
case EVFILTERRES_ACCEPTED:
should_stop = false;
break;
case EVFILTERRES_REJECTED:
should_stop = true;
break;
}
if (disjunction) {
should_stop = !should_stop;
}
if (should_stop) {
accepted = disjunction;
break;
}
}
}
break;
}
if (ptr->inverted) {
accepted = !accepted;
}
return accepted ? EVFILTERRES_ACCEPTED : EVFILTERRES_REJECTED;
}
void
event_filter_set_enabled(EventFilterHandle handle, bool enabled)
{
EventFilter *ptr = event_filter_get_ptr(handle);
if (!ptr) {
return;
}
ptr->enabled = enabled;
}
void event_filter_set_inverted(EventFilterHandle handle, bool inverted)
{
EventFilter *ptr = event_filter_get_ptr(handle);
if (!ptr) {
return;
}
ptr->inverted = inverted;
}
void
event_filter_reset()
{
event_filter_list_clear(&filters);
}

View File

@ -1,51 +0,0 @@
#ifndef FILTERS_H_
#define FILTERS_H_
#include "events.h"
typedef struct event_filter EventFilter;
typedef int32_t EventFilterHandle;
typedef enum {
EVFILTER_INVALID,
EVFILTER_ACCEPT,
// Range
EVFILTER_CODE_NS,
EVFILTER_CODE_MAJOR,
EVFILTER_CODE_MINOR,
EVFILTER_PAYLOAD,
// Aggregation
EVFILTER_CONJUNCTION,
EVFILTER_DISJUNCTION,
} EventFilterType;
typedef enum {
EVFILTERRES_DISABLED = -1,
EVFILTERRES_REJECTED = 0,
EVFILTERRES_ACCEPTED = 1,
} EventFilterResult;
struct event_filter {
EventFilterType type;
bool enabled;
bool inverted;
union {
struct {
int64_t min_value;
int64_t max_value;
} range_data;
struct {
size_t length;
EventFilterHandle *handles;
} aggregate_data;
};
};
EventFilterHandle event_filter_register(EventFilter filter);
EventFilter event_filter_get(EventFilterHandle handle);
EventFilterResult event_filter_apply(EventFilterHandle handle, EventNode * event);
void event_filter_set_enabled(EventFilterHandle handle, bool enabled);
void event_filter_set_inverted(EventFilterHandle handle, bool inverted);
void event_filter_reset();
#endif /* end of include guard: FILTERS_H_ */