Skip to content

Commit

Permalink
Merge pull request #476 from bazsi/filterx-allow-stack-based-integer-…
Browse files Browse the repository at this point in the history
…wrappers

Filterx allow stack based integer wrappers
  • Loading branch information
alltilla authored Feb 7, 2025
2 parents cbaba64 + 9483eb1 commit dd82eff
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 99 deletions.
7 changes: 3 additions & 4 deletions lib/filterx/object-list-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,16 @@
FilterXObject *
filterx_list_get_subscript(FilterXObject *s, gint64 index)
{
FilterXObject *index_obj = filterx_integer_new(index);
FILTERX_INTEGER_DECLARE_ON_STACK(index_obj, index);
FilterXObject *result = filterx_object_get_subscript(s, index_obj);

filterx_object_unref(index_obj);
return result;
}

gboolean
filterx_list_set_subscript(FilterXObject *s, gint64 index, FilterXObject **new_value)
{
FilterXObject *index_obj = filterx_integer_new(index);
FILTERX_INTEGER_DECLARE_ON_STACK(index_obj, index);
gboolean result = filterx_object_set_subscript(s, index_obj, new_value);

filterx_object_unref(index_obj);
Expand All @@ -56,7 +55,7 @@ filterx_list_append(FilterXObject *s, FilterXObject **new_value)
gboolean
filterx_list_unset_index(FilterXObject *s, gint64 index)
{
FilterXObject *index_obj = filterx_integer_new(index);
FILTERX_INTEGER_DECLARE_ON_STACK(index_obj, index);
gboolean result = filterx_object_unset_key(s, index_obj);

filterx_object_unref(index_obj);
Expand Down
8 changes: 8 additions & 0 deletions lib/filterx/object-primitive.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ _integer_add(FilterXObject *s, FilterXObject *object)
return NULL;
}

static FilterXObject *
_integer_clone(FilterXObject *s)
{
FilterXPrimitive *self = (FilterXPrimitive *) s;
return filterx_integer_new(gn_as_int64(&self->value));
}

gboolean
integer_repr(gint64 val, GString *repr)
{
Expand Down Expand Up @@ -371,6 +378,7 @@ FILTERX_DEFINE_TYPE(integer, FILTERX_TYPE_NAME(primitive),
.marshal = _integer_marshal,
.map_to_json = _integer_map_to_json,
.add = _integer_add,
.clone = _integer_clone,
);

FILTERX_DEFINE_TYPE(double, FILTERX_TYPE_NAME(primitive),
Expand Down
15 changes: 15 additions & 0 deletions lib/filterx/object-primitive.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,20 @@ filterx_boolean_unwrap(FilterXObject *s, gboolean *value)
void filterx_primitive_global_init(void);
void filterx_primitive_global_deinit(void);

#define FILTERX_INTEGER_STACK_INIT(v) \
{ \
FILTERX_OBJECT_STACK_INIT(integer), \
.value = { \
{ \
.raw_int64 = v, \
}, \
.type = GN_INT64, \
.precision = 0, \
}, \
}

#define FILTERX_INTEGER_DECLARE_ON_STACK(_name, v) \
FilterXPrimitive __ ## _name ## storage = FILTERX_INTEGER_STACK_INIT(v); \
FilterXObject *_name = &__ ## _name ## storage .super;

#endif
86 changes: 6 additions & 80 deletions lib/generic-number.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,8 @@
#include "generic-number.h"
#include <math.h>

gdouble
gn_as_double(const GenericNumber *number)
{
if (number->type == GN_DOUBLE)
return number->value.raw_double;
else if (number->type == GN_INT64)
return (gdouble) number->value.raw_int64;
g_assert_not_reached();
}

void
gn_set_double(GenericNumber *number, gdouble value, gint precision)
{
number->type = GN_DOUBLE;
number->value.raw_double = value;
number->precision = precision > 0 ? precision : 20;
}

gint64
gn_as_int64(const GenericNumber *number)
_gn_as_int64(const GenericNumber *number)
{
if (number->type == GN_DOUBLE)
{
Expand All @@ -53,56 +35,26 @@ gn_as_int64(const GenericNumber *number)
return G_MAXINT64;
return (gint64) r;
}
else if (number->type == GN_INT64)
return number->value.raw_int64;
g_assert_not_reached();
}

void
gn_set_int64(GenericNumber *number, gint64 value)
{
number->type = GN_INT64;
number->value.raw_int64 = value;
number->precision = 0;
}

gboolean
gn_is_zero(const GenericNumber *number)
_gn_is_zero(const GenericNumber *number)
{
if (number->type == GN_INT64)
return number->value.raw_int64 == 0;

if (number->type == GN_DOUBLE)
return fabs(number->value.raw_double) < DBL_EPSILON;

g_assert_not_reached();
}

void
gn_set_nan(GenericNumber *number)
{
number->type = GN_NAN;
}

gboolean
gn_is_nan(const GenericNumber *number)
_gn_is_nan(const GenericNumber *number)
{
return number->type == GN_NAN || (number->type == GN_DOUBLE && isnan(number->value.raw_double));
return (number->type == GN_DOUBLE && isnan(number->value.raw_double));
}

static gint
_compare_int64(gint64 l, gint64 r)
{
if (l == r)
return 0;
else if (l < r)
return -1;

return 1;
}

static gint
_compare_double(gdouble l, gdouble r)
gint
_gn_compare_double(gdouble l, gdouble r)
{
if (fabs(l - r) < DBL_EPSILON)
return 0;
Expand All @@ -111,29 +63,3 @@ _compare_double(gdouble l, gdouble r)

return 1;
}

gint
gn_compare(const GenericNumber *left, const GenericNumber *right)
{
if (left->type == right->type)
{
if (left->type == GN_INT64)
return _compare_int64(gn_as_int64(left), gn_as_int64(right));
else if (left->type == GN_DOUBLE)
return _compare_double(gn_as_double(left), gn_as_double(right));
}
else if (left->type == GN_NAN || right->type == GN_NAN)
{
;
}
else if (left->type == GN_DOUBLE || right->type == GN_DOUBLE)
{
return _compare_double(gn_as_double(left), gn_as_double(right));
}
else
{
return _compare_int64(gn_as_int64(left), gn_as_int64(right));
}
/* NaNs cannot be compared */
g_assert_not_reached();
}
123 changes: 108 additions & 15 deletions lib/generic-number.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,122 @@

#include "syslog-ng.h"

enum
{
GN_INT64,
GN_DOUBLE,
GN_NAN,
};

typedef struct _GenericNumber
{
enum
{
GN_INT64,
GN_DOUBLE,
GN_NAN,
} type;
gint precision;
union
{
gint64 raw_int64;
gdouble raw_double;
} value;
guint8 type, precision;
} GenericNumber;

void gn_set_double(GenericNumber *number, double value, gint precision);
gdouble gn_as_double(const GenericNumber *number);
void gn_set_int64(GenericNumber *number, gint64 value);
gint64 gn_as_int64(const GenericNumber *number);
gboolean gn_is_zero(const GenericNumber *number);
void gn_set_nan(GenericNumber *number);
gboolean gn_is_nan(const GenericNumber *number);
gint gn_compare(const GenericNumber *left, const GenericNumber *right);
static inline gdouble
gn_as_double(const GenericNumber *number)
{
if (number->type == GN_INT64)
return (gdouble) number->value.raw_int64;
if (number->type == GN_DOUBLE)
return number->value.raw_double;
g_assert_not_reached();
}

static inline void
gn_set_double(GenericNumber *number, gdouble value, gint precision)
{
number->type = GN_DOUBLE;
number->value.raw_double = value;
number->precision = precision > 0 ? precision : 20;
}

gint64 _gn_as_int64(const GenericNumber *number);

static inline gint64
gn_as_int64(const GenericNumber *number)
{
if (number->type == GN_INT64)
return number->value.raw_int64;
return _gn_as_int64(number);
}

static inline void
gn_set_int64(GenericNumber *number, gint64 value)
{
number->type = GN_INT64;
number->value.raw_int64 = value;
number->precision = 0;
}

gboolean _gn_is_zero(const GenericNumber *number);

static inline gboolean
gn_is_zero(const GenericNumber *number)
{
if (number->type == GN_INT64)
return number->value.raw_int64 == 0;
return _gn_is_zero(number);
}

static inline void
gn_set_nan(GenericNumber *number)
{
number->type = GN_NAN;
}

gboolean _gn_is_nan(const GenericNumber *number);

static inline gboolean
gn_is_nan(const GenericNumber *number)
{
if (number->type == GN_NAN)
return TRUE;
return _gn_is_nan(number);
}

static inline gint
_gn_compare_int64(gint64 l, gint64 r)
{
if (l == r)
return 0;
else if (l < r)
return -1;

return 1;
}

gint _gn_compare_double(gdouble l, gdouble r);

static inline gint
gn_compare(const GenericNumber *left, const GenericNumber *right)
{
if (left->type == right->type)
{
if (left->type == GN_INT64)
return _gn_compare_int64(gn_as_int64(left), gn_as_int64(right));
else if (left->type == GN_DOUBLE)
return _gn_compare_double(gn_as_double(left), gn_as_double(right));
}
else if (left->type == GN_NAN || right->type == GN_NAN)
{
;
}
else if (left->type == GN_DOUBLE || right->type == GN_DOUBLE)
{
return _gn_compare_double(gn_as_double(left), gn_as_double(right));
}
else
{
return _gn_compare_int64(gn_as_int64(left), gn_as_int64(right));
}
/* NaNs cannot be compared */
g_assert_not_reached();
}

#endif

0 comments on commit dd82eff

Please sign in to comment.