From ccdacdd4133099dd22ea4ff30edf20d2fa3fa079 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 21 May 2019 09:07:35 +0800 Subject: [PATCH] add a simple set data structure We work with a few sets, so add a data structure for it to avoid ad-hoc implementations in other modules. This is simplify a list as the sets we're working with tends to be quite small: typically less than 10. As long as we don't need to support more, the perf should be good enough. --- src/module.mk | 1 + src/set.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/set.h | 36 ++++++++++++++++++++++++++++++++++++ src/tmpfiles.h | 1 + test/module.mk | 1 + test/set_test.cc | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 src/set.c create mode 100644 src/set.h create mode 100644 test/set_test.cc diff --git a/src/module.mk b/src/module.mk index f3aaa77..72fa2fa 100644 --- a/src/module.mk +++ b/src/module.mk @@ -2,6 +2,7 @@ SRC-tmpfiles := \ main.c \ SRC-libtmpfiles.so := \ + set.c \ all: tmpfiles tmpfiles: $(SRC-libtmpfiles.so:.c=.o) $(SRC-tmpfiles:.c=.o) diff --git a/src/set.c b/src/set.c new file mode 100644 index 0000000..a381ba8 --- /dev/null +++ b/src/set.c @@ -0,0 +1,43 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#include "tmpfiles.h" + +void ordered_set_init(ordered_set_t *set) +{ + set->reserved = 16; + set->count = 0; + set->elements = xmalloc(sizeof(*set->elements) * set->reserved); +} + +void ordered_set_add(ordered_set_t *set, const char *element) +{ + if (set->count == set->reserved) { + set->reserved *= 2; + set->elements = xrealloc(set->elements, sizeof(*set->elements) * set->reserved); + } + + set->elements[set->count] = xstrdup(element); + set->count++; +} + +bool ordered_set_exists(ordered_set_t *set, const char *element) +{ + for (size_t i = 0; i < set->count; ++i) + if (strcmp(set->elements[i], element) == 0) + return true; + + return false; +} + +void ordered_set_free(ordered_set_t *set) +{ + for (size_t i = 0; i < set->count; ++i) + free(set->elements[i]); + + free(set->elements); + set->elements = NULL; +} diff --git a/src/set.h b/src/set.h new file mode 100644 index 0000000..382934d --- /dev/null +++ b/src/set.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +#ifndef TMPFILES_SET_H +#define TMPFILES_SET_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char **elements; + size_t reserved; + size_t count; +} ordered_set_t; + +/* Initialize a set. Its storage should be declared already. */ +extern void ordered_set_init(ordered_set_t *set); + +/* Add a string to the set. The string is duplicated. */ +extern void ordered_set_add(ordered_set_t *set, const char *element); + +/* Test whether the string is in the set. */ +extern bool ordered_set_exists(ordered_set_t *set, const char *element); + +/* Clear a set. Must call ordered_set_init before using again. */ +extern void ordered_set_free(ordered_set_t *set); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/tmpfiles.h b/src/tmpfiles.h index 8fbcd2b..6d9f171 100644 --- a/src/tmpfiles.h +++ b/src/tmpfiles.h @@ -19,5 +19,6 @@ #include "headers.h" #include "xfuncs.h" +#include "set.h" #endif diff --git a/test/module.mk b/test/module.mk index d84994c..9d66ebd 100644 --- a/test/module.mk +++ b/test/module.mk @@ -2,6 +2,7 @@ LDFLAGS-tmpfiles_test = -pthread LDLIBS-tmpfiles_test = -lgtest SRC-tmpfiles_test := \ + set_test.cc \ xfuncs_test.cc \ OBJ-tmpfiles_test := $(SRC-tmpfiles_test:.cc=.o) diff --git a/test/set_test.cc b/test/set_test.cc new file mode 100644 index 0000000..09f4079 --- /dev/null +++ b/test/set_test.cc @@ -0,0 +1,32 @@ +/* + * Copyright 2017-2019 Gentoo Foundation + * Copyright 2017-2019 The Chromium OS Authors + * Released under the 2-clause BSD license. + */ + +/* Tests for the set module. */ + +#include "test.h" + +/* Make sure we can reinit things. */ +TEST(Set, Reinit) { + ordered_set_t set; + ordered_set_init(&set); + ordered_set_free(&set); + ordered_set_init(&set); + ordered_set_free(&set); + ordered_set_init(&set); + ordered_set_free(&set); +} + +/* Smoke test for the API. */ +TEST(Set, Smoke) { + ordered_set_t set; + ordered_set_init(&set); + ASSERT_FALSE(ordered_set_exists(&set, "foo")); + ASSERT_FALSE(ordered_set_exists(&set, "bar")); + ordered_set_add(&set, "foo"); + ASSERT_TRUE(ordered_set_exists(&set, "foo")); + ASSERT_FALSE(ordered_set_exists(&set, "bar")); + ordered_set_free(&set); +}