Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

filterx: native dict/list types #385

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ add_subdirectory(secret-storage)
add_subdirectory(logthrsource)
add_subdirectory(logthrdest)
add_subdirectory(signal-slot-connector)
add_subdirectory(adt)

set(LIB_SUBDIR_HEADERS
${ACK_TRACKER_HEADERS}
Expand Down Expand Up @@ -66,6 +67,7 @@ set(LIB_SUBDIR_HEADERS
${LOGTHRDEST_HEADERS}
${LOGTHRSOURCE_HEADERS}
${SIGNAL_SLOT_CONNECTOR_HEADERS}
${ADT_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/filter/filter-expr-grammar.h
${CMAKE_CURRENT_BINARY_DIR}/filterx/filterx-grammar.h
${CMAKE_CURRENT_BINARY_DIR}/rewrite/rewrite-expr-grammar.h
Expand Down Expand Up @@ -284,6 +286,7 @@ set(LIB_SOURCES
${LOGTHRDEST_SOURCES}
${LOGTHRSOURCE_SOURCES}
${SIGNAL_SLOT_CONNECTOR_SOURCES}
${ADT_SOURCES}
${PROJECT_BINARY_DIR}/lib/cfg-grammar.c
${PROJECT_BINARY_DIR}/lib/block-ref-grammar.c
${PROJECT_BINARY_DIR}/lib/cfg-lex.c
Expand Down Expand Up @@ -435,6 +438,7 @@ install(FILES ${CSV_SCANNER_HEADERS} DESTINATION include/syslog-ng/scanner/csv-s
install(FILES ${LOGTHRDEST_HEADERS} DESTINATION include/syslog-ng/logthrdest)
install(FILES ${LOGTHRSOURCE_HEADERS} DESTINATION include/syslog-ng/logthrsource)
install(FILES ${SIGNAL_SLOT_CONNECTOR_HEADERS} DESTINATION include/syslog-ng/signal-slot-connector)
install(FILES ${ADT_HEADERS} DESTINATION include/syslog-ng/adt)

set(TOOLS
merge-grammar.py
Expand Down
4 changes: 3 additions & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ include lib/logthrsource/Makefile.am
include lib/logthrdest/Makefile.am
include lib/signal-slot-connector/Makefile.am
include lib/multi-line/Makefile.am
include lib/adt/Makefile.am

LSNG_RELEASE = $(shell echo @PACKAGE_VERSION@ | cut -d. -f1,2)

Expand Down Expand Up @@ -307,7 +308,8 @@ lib_libsyslog_ng_la_SOURCES = \
$(multiline_sources) \
$(logthrsource_sources) \
$(logthrdest_sources) \
$(signal_slot_connector_sources)
$(signal_slot_connector_sources) \
$(adt_sources)

lib_libsyslog_ng_la_CFLAGS = \
$(AM_CFLAGS) \
Expand Down
10 changes: 10 additions & 0 deletions lib/adt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set(ADT_HEADERS
adt/iord_map.h
adt/ilist.h
PARENT_SCOPE)

set(ADT_SOURCES
adt/iord_map.c
PARENT_SCOPE)

add_subdirectory(tests)
12 changes: 12 additions & 0 deletions lib/adt/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
adtincludedir = ${pkgincludedir}/adt

EXTRA_DIST += lib/adt/CMakeLists.txt

adtinclude_HEADERS = \
lib/adt/iord_map.h \
lib/adt/ilist.h

adt_sources = \
lib/adt/iord_map.c

include lib/adt/tests/Makefile.am
86 changes: 86 additions & 0 deletions lib/adt/ilist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2024 Axoflow
* Copyright (c) 2024 László Várady
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/

#ifndef ADT_ILIST
#define ADT_ILIST

#include <stddef.h>
#include <iv_list.h>

/*
* Intrusive list (just a wrapper around iv_list for easier use)
*/

typedef struct iv_list_head IList;
typedef struct iv_list_head IListNode;

#define ilist_init(self) INIT_IV_LIST_HEAD(self)
#define ilist_push_back(self, node) iv_list_add_tail(node, self)
#define ilist_push_front(self, node) iv_list_add(node, self)
#define ilist_splice_back(self, list) iv_list_splice_tail(list, self)
#define ilist_splice_front(self, list) iv_list_splice(list, self)
#define ilist_remove(node) iv_list_del(node)
#define ilist_is_empty(self) iv_list_empty(self)
#define ilist_foreach(self, current, next) iv_list_for_each_safe(current, next, self)
#define ilist_entry(self, type, member) iv_list_entry(self, type, member)

static inline IList *
ilist_pop_back(IList *self)
{
IList *e = self->prev;
iv_list_del(e);
return e;
}

static inline IList *
ilist_pop_front(IList *self)
{
IList *e = self->next;
iv_list_del(e);
return e;
}

static inline void
_ilist_reverse_node_links(IList *node)
{
IList *orig_next = node->next;
node->next = node->prev;
node->prev = orig_next;
}

static inline void
ilist_reverse(IList *self)
{
IList *current = self->next;

while (current != self)
{
_ilist_reverse_node_links(current);
current = current->prev;
}

_ilist_reverse_node_links(self);
}

#endif
204 changes: 204 additions & 0 deletions lib/adt/iord_map.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* Copyright (c) 2024 Axoflow
* Copyright (c) 2024 László Várady
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/

#include "iord_map.h"

#define iord_map_node_container_of(node, offset) ((guint8 *) (node) - (intptr_t) (offset))
#define iord_map_node_from_container(container, offset) ((IOrdMapNode *) ((guint8 *) (container) + (intptr_t) (offset)))


void
iord_map_init(IOrdMap *self, GHashFunc hash_func, GEqualFunc key_equal_func,
guint16 key_container_offset, guint16 value_container_offset)
{
iord_map_init_full(self, hash_func, key_equal_func, NULL, key_container_offset, NULL, value_container_offset);
}

void
iord_map_init_full(IOrdMap *self, GHashFunc hash_func, GEqualFunc key_equal_func,
GDestroyNotify key_destroy_func, guint16 key_container_offset,
GDestroyNotify value_destroy_func, guint16 value_container_offset)
{
self->ht = g_hash_table_new_full(hash_func, key_equal_func, key_destroy_func, value_destroy_func);
iord_map_node_init(&self->keys);
iord_map_node_init(&self->values);
self->key_destroy_func = key_destroy_func;
self->key_container_offset = key_container_offset;
self->value_destroy_func = value_destroy_func;
self->value_container_offset = value_container_offset;
}

void
iord_map_destroy(IOrdMap *self)
{
g_hash_table_destroy(self->ht);
}

IOrdMap *
iord_map_new(GHashFunc hash_func, GEqualFunc key_equal_func,
guint16 key_container_offset, guint16 value_container_offset)
{
return iord_map_new_full(hash_func, key_equal_func, NULL, key_container_offset, NULL, value_container_offset);
}

IOrdMap *
iord_map_new_full(GHashFunc hash_func, GEqualFunc key_equal_func,
GDestroyNotify key_destroy_func, guint16 key_container_offset,
GDestroyNotify value_destroy_func, guint16 value_container_offset)
{
IOrdMap *self = g_new0(IOrdMap, 1);

iord_map_init_full(self, hash_func, key_equal_func, key_destroy_func, key_container_offset,
value_destroy_func, value_container_offset);

return self;
}

void
iord_map_free(IOrdMap *self)
{
iord_map_destroy(self);
g_free(self);
}

gboolean
iord_map_contains(IOrdMap *self, gconstpointer key)
{
return g_hash_table_contains(self->ht, key);
}

gboolean
iord_map_foreach(IOrdMap *self, IOrdMapForeachFunc func, gpointer user_data)
{
for (struct iv_list_head *key = self->keys.next, *value = self->values.next;
key != &self->keys;
key = key->next, value = value->next)
{
gpointer key_container = iord_map_node_container_of(key, self->key_container_offset);
gpointer value_container = iord_map_node_container_of(value, self->value_container_offset);
if (!func(key_container, value_container, user_data))
return FALSE;
}

return TRUE;
}

gboolean
iord_map_insert(IOrdMap *self, gpointer key, gpointer value)
{
IOrdMapNode *key_node = iord_map_node_from_container(key, self->key_container_offset);
g_assert(!key_node->next || iv_list_empty(key_node));

gpointer orig_key, old_value;
if (!g_hash_table_lookup_extended(self->ht, key, &orig_key, &old_value))
{
iv_list_add_tail(key_node, &self->keys);
goto finish;
}

iv_list_del(iord_map_node_from_container(orig_key, self->key_container_offset));
iv_list_del(iord_map_node_from_container(old_value, self->value_container_offset));

/* keeps the original key */
iv_list_add_tail(iord_map_node_from_container(orig_key, self->key_container_offset), &self->keys);

finish:
iv_list_add_tail(iord_map_node_from_container(value, self->value_container_offset), &self->values);
return g_hash_table_insert(self->ht, key, value);
}

gboolean
iord_map_prepend(IOrdMap *self, gpointer key, gpointer value)
{
IOrdMapNode *key_node = iord_map_node_from_container(key, self->key_container_offset);
g_assert(!key_node->next || iv_list_empty(key_node));

gpointer orig_key, old_value;
if (!g_hash_table_lookup_extended(self->ht, key, &orig_key, &old_value))
{
iv_list_add(key_node, &self->keys);
goto finish;
}

iv_list_del(iord_map_node_from_container(orig_key, self->key_container_offset));
iv_list_del(iord_map_node_from_container(old_value, self->value_container_offset));

/* keeps the original key */
iv_list_add(iord_map_node_from_container(orig_key, self->key_container_offset), &self->keys);

finish:
iv_list_add(iord_map_node_from_container(value, self->value_container_offset), &self->values);
return g_hash_table_insert(self->ht, key, value);
}

gpointer
iord_map_lookup(IOrdMap *self, gconstpointer key)
{
return g_hash_table_lookup(self->ht, key);
}

gboolean
iord_map_remove(IOrdMap *self, gconstpointer key)
{
gpointer key_to_delete, value_to_delete;
if (!g_hash_table_steal_extended(self->ht, key, &key_to_delete, &value_to_delete))
return FALSE;

iv_list_del(iord_map_node_from_container(key_to_delete, self->key_container_offset));
iv_list_del(iord_map_node_from_container(value_to_delete, self->value_container_offset));

if (self->key_destroy_func)
self->key_destroy_func(key_to_delete);

if (self->value_destroy_func)
self->value_destroy_func(value_to_delete);

return TRUE;
}

void
iord_map_clear(IOrdMap *self)
{
g_hash_table_remove_all(self->ht);
iord_map_node_init(&self->keys);
iord_map_node_init(&self->values);
}

gsize
iord_map_size(IOrdMap *self)
{
return g_hash_table_size(self->ht);
}

IOrdMapNode *
iord_map_get_keys(IOrdMap *self)
{
return &self->keys;
}

IOrdMapNode *
iord_map_get_values(IOrdMap *self)
{
return &self->values;
}
Loading
Loading