From 1b6c51787f78a85fc5ec5da42d859ce2255b45df Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 11:10:30 +0000 Subject: [PATCH 01/14] Fix: Corrected type of #include --- src/fastevent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastevent.h b/src/fastevent.h index a45a8bfb..1a18ba6f 100644 --- a/src/fastevent.h +++ b/src/fastevent.h @@ -15,7 +15,7 @@ #endif #include -#include +#include "refobject.h" typedef enum { FASTEVENT_TYPE_SLOWEVENT = 0, From f1b2785fc4089464662f1e06bef5ce46ff565a2d Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 11:15:39 +0000 Subject: [PATCH 02/14] Feature: Changed refobject subsystem to use defined types --- src/buffer.c | 11 ++++++----- src/buffer.h | 2 ++ src/fastevent.c | 31 ++++++++++++++++--------------- src/listensocket.c | 12 ++++++++++-- src/listensocket.h | 5 +++++ src/module.c | 16 ++++++++++++---- src/module.h | 4 ++++ src/refobject.c | 22 ++++++++++++++++------ src/refobject.h | 30 ++++++++++++++++++++++++++++-- src/reportxml.c | 18 +++++++++++++++--- src/reportxml.h | 5 ++++- 11 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 9d8e1ace..26c938f3 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -37,16 +37,17 @@ static void __free(refobject_t self, void **userdata) free(buffer->buffer); } +REFOBJECT_DEFINE_TYPE(buffer_t, + REFOBJECT_DEFINE_TYPE_FREE(__free) + ); + buffer_t * buffer_new(ssize_t preallocation, void *userdata, const char *name, refobject_t associated) { - buffer_t *buffer = NULL; - refobject_t refobject = refobject_new(sizeof(*buffer), __free, userdata, name, associated); + buffer_t *buffer = refobject_new__new(buffer_t, userdata, name, associated); - if (REFOBJECT_IS_NULL(refobject)) + if (!buffer) return NULL; - buffer = REFOBJECT_TO_TYPE(refobject, buffer_t *); - if (preallocation > 0) buffer_preallocate(buffer, preallocation); diff --git a/src/buffer.h b/src/buffer.h index 8aea026a..c7490582 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -28,6 +28,8 @@ * This set of functions is intentinally not thread safe. */ +REFOBJECT_FORWARD_TYPE(buffer_t); + /* This creates a new buffer object. * Parameters: * preallocation diff --git a/src/fastevent.c b/src/fastevent.c index 5022c698..4d52246d 100644 --- a/src/fastevent.c +++ b/src/fastevent.c @@ -26,19 +26,19 @@ #ifdef FASTEVENT_ENABLED -struct registration { +typedef struct { refobject_base_t __base; fastevent_type_t type; fastevent_cb_t cb; fastevent_freecb_t freecb; void *userdata; -}; +} fastevent_registration_t; struct eventrow { size_t length; size_t used; - struct registration **registrations; + fastevent_registration_t **registrations; }; static struct eventrow fastevent_registrations[FASTEVENT_TYPE__END]; @@ -54,9 +54,9 @@ static inline struct eventrow * __get_row(fastevent_type_t type) return &(fastevent_registrations[idx]); } -static int __add_to_row(struct eventrow * row, struct registration *registration) +static int __add_to_row(struct eventrow * row, fastevent_registration_t *registration) { - struct registration **n; + fastevent_registration_t **n; if (row == NULL) return -1; @@ -77,7 +77,7 @@ static int __add_to_row(struct eventrow * row, struct registration *registration return 0; } -static int __remove_from_row(struct eventrow * row, struct registration *registration) +static int __remove_from_row(struct eventrow * row, fastevent_registration_t *registration) { size_t i; @@ -98,7 +98,7 @@ static int __remove_from_row(struct eventrow * row, struct registration *registr static void __unregister(refobject_t self, void **userdata) { - struct registration *registration = REFOBJECT_TO_TYPE(self, struct registration *); + fastevent_registration_t *registration = REFOBJECT_TO_TYPE(self, fastevent_registration_t *); struct eventrow * row; (void)userdata; @@ -143,11 +143,14 @@ int fastevent_shutdown(void) return 0; } +REFOBJECT_DEFINE_PRIVATE_TYPE(fastevent_registration_t, + REFOBJECT_DEFINE_TYPE_FREE(__unregister) + ); + refobject_t fastevent_register(fastevent_type_t type, fastevent_cb_t cb, fastevent_freecb_t freecb, void *userdata) { struct eventrow * row; - struct registration *registration; - refobject_t ret; + fastevent_registration_t *registration; if (cb == NULL) return REFOBJECT_NULL; @@ -160,15 +163,13 @@ refobject_t fastevent_register(fastevent_type_t type, fastevent_cb_t cb, fasteve return REFOBJECT_NULL; } - ret = refobject_new(sizeof(struct registration), __unregister, NULL, NULL, NULL); + registration = refobject_new__new(fastevent_registration_t, NULL, NULL, NULL); - if (REFOBJECT_IS_NULL(ret)) { + if (!registration) { thread_rwlock_unlock(&fastevent_lock); return REFOBJECT_NULL; } - registration = REFOBJECT_TO_TYPE(ret, struct registration *); - registration->type = type; registration->cb = cb; registration->freecb = freecb; @@ -176,12 +177,12 @@ refobject_t fastevent_register(fastevent_type_t type, fastevent_cb_t cb, fasteve if (__add_to_row(row, registration) != 0) { thread_rwlock_unlock(&fastevent_lock); - refobject_unref(ret); + refobject_unref((refobject_base_t*)registration); return REFOBJECT_NULL; } thread_rwlock_unlock(&fastevent_lock); - return ret; + return (refobject_t)(refobject_base_t*)registration; } void fastevent_emit(fastevent_type_t type, fastevent_flag_t flags, fastevent_datatype_t datatype, ...) diff --git a/src/listensocket.c b/src/listensocket.c index f188ef56..5ed9ad30 100644 --- a/src/listensocket.c +++ b/src/listensocket.c @@ -150,9 +150,13 @@ static void __listensocket_container_free(refobject_t self, void **userdata) thread_mutex_destroy(&container->lock); } +REFOBJECT_DEFINE_TYPE(listensocket_container_t, + REFOBJECT_DEFINE_TYPE_FREE(__listensocket_container_free) + ); + listensocket_container_t * listensocket_container_new(void) { - listensocket_container_t *self = REFOBJECT_TO_TYPE(refobject_new(sizeof(listensocket_container_t), __listensocket_container_free, NULL, NULL, NULL), listensocket_container_t *); + listensocket_container_t *self = refobject_new__new(listensocket_container_t, NULL, NULL, NULL); if (!self) return NULL; @@ -527,13 +531,17 @@ static void __listensocket_free(refobject_t self, void **userdata) thread_mutex_destroy(&listensocket->lock); } +REFOBJECT_DEFINE_TYPE(listensocket_t, + REFOBJECT_DEFINE_TYPE_FREE(__listensocket_free) + ); + static listensocket_t * listensocket_new(const listener_t *listener) { listensocket_t *self; if (listener == NULL) return NULL; - self = REFOBJECT_TO_TYPE(refobject_new(sizeof(listensocket_t), __listensocket_free, NULL, NULL, NULL), listensocket_t *); + self = refobject_new__new(listensocket_t, NULL, NULL, NULL); if (!self) return NULL; diff --git a/src/listensocket.h b/src/listensocket.h index 4991892d..a6d063bd 100644 --- a/src/listensocket.h +++ b/src/listensocket.h @@ -10,8 +10,11 @@ #define __LISTENSOCKET_H__ #include "icecasttypes.h" +#include "refobject.h" #include "cfgfile.h" +REFOBJECT_FORWARD_TYPE(listensocket_container_t); + listensocket_container_t * listensocket_container_new(void); int listensocket_container_configure(listensocket_container_t *self, const ice_config_t *config); int listensocket_container_configure_and_setup(listensocket_container_t *self, const ice_config_t *config); @@ -20,6 +23,8 @@ connection_t * listensocket_container_accept(listensocket_container int listensocket_container_set_sockcount_cb(listensocket_container_t *self, void (*cb)(size_t count, void *userdata), void *userdata); ssize_t listensocket_container_sockcount(listensocket_container_t *self); +REFOBJECT_FORWARD_TYPE(listensocket_t); + int listensocket_refsock(listensocket_t *self); int listensocket_unrefsock(listensocket_t *self); connection_t * listensocket_accept(listensocket_t *self, listensocket_container_t *container); diff --git a/src/module.c b/src/module.c index 997d4819..19ad5adb 100644 --- a/src/module.c +++ b/src/module.c @@ -50,9 +50,13 @@ static void __module_container_free(refobject_t self, void **userdata) avl_tree_free(cont->module, (avl_free_key_fun_type)refobject_unref); } +REFOBJECT_DEFINE_TYPE(module_container_t, + REFOBJECT_DEFINE_TYPE_FREE(__module_container_free) + ); + module_container_t * module_container_new(void) { - module_container_t *ret = REFOBJECT_TO_TYPE(refobject_new(sizeof(module_container_t), __module_container_free, NULL, NULL, NULL), module_container_t *); + module_container_t *ret = refobject_new__new(module_container_t, NULL, NULL, NULL); if (!ret) return NULL; @@ -101,13 +105,13 @@ int module_container_delete_module(module_container_t *self, module_t * module_container_get_module(module_container_t *self, const char *name) { - refobject_t search; + refobject_base_t *search; module_t *ret; if (!self || !name) return NULL; - search = refobject_new(sizeof(refobject_base_t), NULL, NULL, name, NULL); + search = refobject_new__new(refobject_base_t, NULL, name, NULL); thread_mutex_lock(&(self->lock)); if (avl_get_by_key(self->module, REFOBJECT_TO_TYPE(search, void *), (void**)&ret) != 0) { @@ -168,9 +172,13 @@ static void __module_free(refobject_t self, void **userdata) thread_mutex_destroy(&(mod->lock)); } +REFOBJECT_DEFINE_TYPE(module_t, + REFOBJECT_DEFINE_TYPE_FREE(__module_free) + ); + module_t * module_new(const char *name, module_setup_handler_t newcb, module_setup_handler_t freecb, void *userdata) { - module_t *ret = REFOBJECT_TO_TYPE(refobject_new(sizeof(module_t), __module_free, NULL, name, NULL), module_t *); + module_t *ret = refobject_new__new(module_t, NULL, name, NULL); if (!ret) return NULL; diff --git a/src/module.h b/src/module.h index d9d38a2f..69b3c334 100644 --- a/src/module.h +++ b/src/module.h @@ -12,6 +12,7 @@ #include #include "icecasttypes.h" +#include "refobject.h" typedef void (*module_client_handler_function_t)(module_t *self, client_t *client); typedef int (*module_setup_handler_t)(module_t *self, void **userdata); @@ -21,6 +22,9 @@ typedef struct { module_client_handler_function_t cb; } module_client_handler_t; +REFOBJECT_FORWARD_TYPE(module_container_t); +REFOBJECT_FORWARD_TYPE(module_t); + module_container_t * module_container_new(void); int module_container_add_module(module_container_t *self, module_t *module); int module_container_delete_module(module_container_t *self, const char *name); diff --git a/src/refobject.c b/src/refobject.c index 2aa7fd18..83f10434 100644 --- a/src/refobject.c +++ b/src/refobject.c @@ -19,19 +19,29 @@ #define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *) -refobject_t refobject_new(size_t len, refobject_free_t freecb, void *userdata, const char *name, refobject_t associated) +REFOBJECT_DEFINE_TYPE(refobject_base_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + +static inline int check_type(const refobject_type_t *type) +{ + return type->control_length == sizeof(refobject_type_t) && type->control_version == REFOBJECT_CONTROL_VERSION && + type->type_length >= sizeof(refobject_base_t); +} + +refobject_t refobject_new__real(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated) { refobject_base_t *ret = NULL; - if (len < sizeof(refobject_base_t)) + if (!check_type(type)) return (refobject_t)ret; - ret = calloc(1, len); + ret = calloc(1, type->type_length); if (ret == NULL) return (refobject_t)ret; + ret->type = type; ret->refc = 1; - ret->freecb = freecb; ret->userdata = userdata; thread_mutex_create(&(ret->lock)); @@ -82,8 +92,8 @@ int refobject_unref(refobject_t self) return 0; } - if (base->freecb) - base->freecb(self, &(base->userdata)); + if (base->type->type_freecb) + base->type->type_freecb(self, &(base->userdata)); if (base->userdata) free(base->userdata); diff --git a/src/refobject.h b/src/refobject.h index e259dc5a..56b291eb 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -46,6 +46,18 @@ #define REFOBJECT_TO_TYPE(x,y) ((y)(x)) #endif +#define REFOBJECT_CONTROL_VERSION 0 +#define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t refobject_type__ ## type; +#define REFOBJECT_DEFINE_TYPE(type, extra) const refobject_type_t refobject_type__ ## type = { \ + .control_length = sizeof(refobject_type_t), \ + .control_version = REFOBJECT_CONTROL_VERSION, \ + .type_length = sizeof(type), \ + .type_name = # type, \ + extra \ +} +#define REFOBJECT_DEFINE_PRIVATE_TYPE(type, extra) static REFOBJECT_DEFINE_TYPE(type, extra) +#define REFOBJECT_DEFINE_TYPE_FREE(cb) .type_freecb = (cb) + /* Type used for callback called then the object is actually freed * That is once all references to it are gone. * @@ -56,18 +68,31 @@ */ typedef void (*refobject_free_t)(refobject_t self, void **userdata); +/* Meta type used to defined types. + */ + +typedef struct { + size_t control_length; + int control_version; + size_t type_length; + const char * type_name; + refobject_free_t type_freecb; +} refobject_type_t; + /* Only defined here as the size must be publically known. * DO NOT use any of the members in here directly! */ struct refobject_base_tag { + const refobject_type_t* type; size_t refc; mutex_t lock; void *userdata; - refobject_free_t freecb; char *name; refobject_t associated; }; +REFOBJECT_FORWARD_TYPE(refobject_base_t); + /* Create a new refobject * The total length of the new object is given by len (see malloc(3)), * the callback called on free is given by freecb (see refobject_free_t above), @@ -78,7 +103,8 @@ struct refobject_base_tag { * All parameters beside len are optional and can be NULL/REFOBJECT_NULL. * If no freecb is given the userdata is freed (see refobject_free_t above). */ -refobject_t refobject_new(size_t len, refobject_free_t freecb, void *userdata, const char *name, refobject_t associated); +#define refobject_new__new(type, userdata, name, associated) REFOBJECT_TO_TYPE(refobject_new__real(&(refobject_type__ ## type), (userdata), (name), (associated)), type*) +refobject_t refobject_new__real(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated); /* This increases the reference counter of the object */ int refobject_ref(refobject_t self); diff --git a/src/reportxml.c b/src/reportxml.c index b6ea1c7e..89b45e61 100644 --- a/src/reportxml.c +++ b/src/reportxml.c @@ -236,6 +236,10 @@ static void __report_free(refobject_t self, void **userdata) refobject_unref(report->root); } +REFOBJECT_DEFINE_TYPE(reportxml_t, + REFOBJECT_DEFINE_TYPE_FREE(__report_free) + ); + static reportxml_t * reportxml_new_with_root(reportxml_node_t *root) { reportxml_t *ret; @@ -243,7 +247,7 @@ static reportxml_t * reportxml_new_with_root(reportxml_node_t *root) if (!root) return NULL; - ret = REFOBJECT_TO_TYPE(refobject_new(sizeof(reportxml_t), __report_free, NULL, NULL, NULL), reportxml_t *); + ret = refobject_new__new(reportxml_t, NULL, NULL, NULL); ret->root = root; return ret; @@ -368,6 +372,10 @@ static void __report_node_free(refobject_t self, void **userdata) free(node->xml_childs); } +REFOBJECT_DEFINE_TYPE(reportxml_node_t, + REFOBJECT_DEFINE_TYPE_FREE(__report_node_free) + ); + reportxml_node_t * reportxml_node_new(reportxml_node_type_t type, const char *id, const char *definition, const char *akindof) { reportxml_node_t *ret; @@ -377,7 +385,7 @@ reportxml_node_t * reportxml_node_new(reportxml_node_type_t type, const cha if (!nodedef) return NULL; - ret = REFOBJECT_TO_TYPE(refobject_new(sizeof(reportxml_node_t), __report_node_free, NULL, NULL, NULL), reportxml_node_t *); + ret = refobject_new__new(reportxml_node_t, NULL, NULL, NULL); if (ret == NULL) return NULL; @@ -975,9 +983,13 @@ static int __compare_definitions(void *arg, void *a, void *b) return ret; } +REFOBJECT_DEFINE_TYPE(reportxml_database_t, + REFOBJECT_DEFINE_TYPE_FREE(__database_free) + ); + reportxml_database_t * reportxml_database_new(void) { - reportxml_database_t *ret = REFOBJECT_TO_TYPE(refobject_new(sizeof(reportxml_database_t), __database_free, NULL, NULL, NULL), reportxml_database_t *); + reportxml_database_t *ret = refobject_new__new(reportxml_database_t, NULL, NULL, NULL); if (!ret) return NULL; diff --git a/src/reportxml.h b/src/reportxml.h index 68d4b3d8..b58ca9c3 100644 --- a/src/reportxml.h +++ b/src/reportxml.h @@ -15,6 +15,7 @@ #include "icecasttypes.h" #include "compat.h" +#include "refobject.h" /* XML Tag Types * While a hint of what the nodes are used for is given, see the specification for more details. @@ -60,11 +61,13 @@ typedef enum { REPORTXML_NODE_TYPE_EXTENSION } reportxml_node_type_t; +REFOBJECT_FORWARD_TYPE(reportxml_t); +REFOBJECT_FORWARD_TYPE(reportxml_node_t); +REFOBJECT_FORWARD_TYPE(reportxml_database_t); /* ---[ Document level ]--- */ /* The document object is NOT thread safe. */ - /* This creates a new, empty report XML document */ reportxml_t * reportxml_new(void); /* This gets the root node of a report XML document */ From c0ff861107022414b550d9b11317108705952f4e Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 12:55:32 +0000 Subject: [PATCH 03/14] Fix: Updated unit tests to new refobject API --- src/fastevent.c | 4 +- src/refobject.h | 2 + src/tests/ctest_buffer.c | 4 +- src/tests/ctest_refobject.c | 91 +++++++++++++++++++++++++------------ 4 files changed, 69 insertions(+), 32 deletions(-) diff --git a/src/fastevent.c b/src/fastevent.c index 4d52246d..5ab90b64 100644 --- a/src/fastevent.c +++ b/src/fastevent.c @@ -177,12 +177,12 @@ refobject_t fastevent_register(fastevent_type_t type, fastevent_cb_t cb, fasteve if (__add_to_row(row, registration) != 0) { thread_rwlock_unlock(&fastevent_lock); - refobject_unref((refobject_base_t*)registration); + refobject_unref(REFOBJECT_FROM_TYPE(registration)); return REFOBJECT_NULL; } thread_rwlock_unlock(&fastevent_lock); - return (refobject_t)(refobject_base_t*)registration; + return REFOBJECT_FROM_TYPE(registration); } void fastevent_emit(fastevent_type_t type, fastevent_flag_t flags, fastevent_datatype_t datatype, ...) diff --git a/src/refobject.h b/src/refobject.h index 56b291eb..4272fc0a 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -46,6 +46,8 @@ #define REFOBJECT_TO_TYPE(x,y) ((y)(x)) #endif +#define REFOBJECT_FROM_TYPE(x) ((refobject_t)(refobject_base_t*)(x)) + #define REFOBJECT_CONTROL_VERSION 0 #define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t refobject_type__ ## type; #define REFOBJECT_DEFINE_TYPE(type, extra) const refobject_type_t refobject_type__ ## type = { \ diff --git a/src/tests/ctest_buffer.c b/src/tests/ctest_buffer.c index d29219cb..d8158e08 100644 --- a/src/tests/ctest_buffer.c +++ b/src/tests/ctest_buffer.c @@ -80,10 +80,10 @@ static void test_userdata(void) static void test_associated(void) { - refobject_t a; + refobject_base_t *a; buffer_t *b; - a = refobject_new(sizeof(refobject_base_t), NULL, NULL, NULL, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); diff --git a/src/tests/ctest_refobject.c b/src/tests/ctest_refobject.c index 1f553f6f..cc54a3e0 100644 --- a/src/tests/ctest_refobject.c +++ b/src/tests/ctest_refobject.c @@ -29,9 +29,9 @@ static void test_ptr(void) static void test_create_ref_unref(void) { - refobject_t a; + refobject_base_t *a; - a = refobject_new(sizeof(refobject_base_t), NULL, NULL, NULL, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ctest_test("referenced", refobject_ref(a) == 0); @@ -43,23 +43,51 @@ static void test_sizes(void) { refobject_t a; - a = refobject_new(sizeof(refobject_base_t) + 1024, NULL, NULL, NULL, REFOBJECT_NULL); + typedef struct { + refobject_base_t __base; + char padding[1024]; + } ctest_test_type_a_t; + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + + typedef struct { + refobject_base_t __base; + char padding[131072]; + } ctest_test_type_b_t; + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + + typedef struct { + char padding[sizeof(refobject_base_t) - 1]; + } ctest_test_type_c_t; + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + + typedef struct { + char padding[0]; + } ctest_test_type_d_t; + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + + a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_a_t, NULL, NULL, REFOBJECT_NULL)); ctest_test("refobject created with size=sizeof(refobject_base_t) + 1024", !REFOBJECT_IS_NULL(a)); ctest_test("un-referenced", refobject_unref(a) == 0); - a = refobject_new(sizeof(refobject_base_t) + 131072, NULL, NULL, NULL, REFOBJECT_NULL); + a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_b_t, NULL, NULL, REFOBJECT_NULL)); ctest_test("refobject created with size=sizeof(refobject_base_t) + 131072", !REFOBJECT_IS_NULL(a)); ctest_test("un-referenced", refobject_unref(a) == 0); - if (sizeof(refobject_base_t) >= 1) { - a = refobject_new(sizeof(refobject_base_t) - 1, NULL, NULL, NULL, REFOBJECT_NULL); - ctest_test("refobject created with size=sizeof(refobject_base_t) - 1", REFOBJECT_IS_NULL(a)); - if (!REFOBJECT_IS_NULL(a)) { - ctest_test("un-referenced", refobject_unref(a) == 0); - } + a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_c_t, NULL, NULL, REFOBJECT_NULL)); + ctest_test("refobject created with size=sizeof(refobject_base_t) - 1", REFOBJECT_IS_NULL(a)); + if (!REFOBJECT_IS_NULL(a)) { + ctest_test("un-referenced", refobject_unref(a) == 0); } - a = refobject_new(0, NULL, NULL, NULL, REFOBJECT_NULL); + a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_d_t, NULL, NULL, REFOBJECT_NULL)); ctest_test("refobject created with size=0", REFOBJECT_IS_NULL(a)); if (!REFOBJECT_IS_NULL(a)) { ctest_test("un-referenced", refobject_unref(a) == 0); @@ -68,11 +96,11 @@ static void test_sizes(void) static void test_name(void) { - refobject_t a; + refobject_base_t *a; const char *name = "test object name"; const char *ret; - a = refobject_new(sizeof(refobject_base_t), NULL, NULL, name, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, NULL, name, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_name(a); @@ -84,12 +112,12 @@ static void test_name(void) static void test_userdata(void) { - refobject_t a; + refobject_base_t *a; int tmp = 0; void *userdata = &tmp; void *ret; - a = refobject_new(sizeof(refobject_base_t), NULL, NULL, NULL, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_userdata(a); @@ -103,7 +131,7 @@ static void test_userdata(void) ctest_test("un-referenced", refobject_unref(a) == 0); - a = refobject_new(sizeof(refobject_base_t), NULL, userdata, NULL, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, userdata, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_userdata(a); ctest_test("get userdata", ret == userdata); @@ -115,12 +143,12 @@ static void test_userdata(void) static void test_associated(void) { - refobject_t a, b; + refobject_base_t *a, *b; - a = refobject_new(sizeof(refobject_base_t), NULL, NULL, NULL, REFOBJECT_NULL); + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); - b = refobject_new(sizeof(refobject_base_t), NULL, NULL, NULL, a); + b = refobject_new__new(refobject_base_t, NULL, NULL, a); ctest_test("refobject created with associated", !REFOBJECT_IS_NULL(b)); ctest_test("un-referenced (1 of 2)", refobject_unref(b) == 0); @@ -135,22 +163,29 @@ static void test_freecb__freecb(refobject_t self, void **userdata) static void test_freecb(void) { - refobject_t a; + typedef struct { + refobject_base_t __base; + } ctest_test_type_t; + ctest_test_type_t *a; + + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t, + REFOBJECT_DEFINE_TYPE_FREE(test_freecb__freecb) + ); test_freecb__called = 0; - a = refobject_new(sizeof(refobject_base_t), test_freecb__freecb, NULL, NULL, REFOBJECT_NULL); - ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); - ctest_test("un-referenced", refobject_unref(a) == 0); + a = refobject_new__new(ctest_test_type_t, NULL, NULL, REFOBJECT_NULL); + ctest_test("refobject created", a != NULL); + ctest_test("un-referenced", refobject_unref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb called", test_freecb__called == 1); test_freecb__called = 0; - a = refobject_new(sizeof(refobject_base_t), test_freecb__freecb, NULL, NULL, REFOBJECT_NULL); - ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); - ctest_test("referenced", refobject_ref(a) == 0); + a = refobject_new__new(ctest_test_type_t, NULL, NULL, REFOBJECT_NULL); + ctest_test("refobject created", a != NULL); + ctest_test("referenced", refobject_ref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb uncalled", test_freecb__called == 0); - ctest_test("un-referenced (1 of 2)", refobject_unref(a) == 0); + ctest_test("un-referenced (1 of 2)", refobject_unref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb uncalled", test_freecb__called == 0); - ctest_test("un-referenced (2 of 2)", refobject_unref(a) == 0); + ctest_test("un-referenced (2 of 2)", refobject_unref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb called", test_freecb__called == 1); } From d10a9683aa685fc36818fa6b58fdbb25995b061b Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 13:12:01 +0000 Subject: [PATCH 04/14] Feature: Added tests for REFOBJECT_GET_TYPENAME() and REFOBJECT_IS_VALID() --- src/refobject.h | 7 +++++++ src/tests/ctest_refobject.c | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/refobject.h b/src/refobject.h index 4272fc0a..9ba4d331 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -38,16 +38,23 @@ */ #ifdef HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION #define REFOBJECT_NULL ((refobject_t)(refobject_base_t*)NULL) +#define REFOBJECT_GET_BASE(x) (((refobject_t)(x)).refobject_base) #define REFOBJECT_IS_NULL(x) (((refobject_t)(x)).refobject_base == NULL) #define REFOBJECT_TO_TYPE(x,y) ((y)(((refobject_t)(x)).refobject_base)) #else #define REFOBJECT_NULL NULL +#define REFOBJECT_GET_BASE(x) ((refobject_base_t)(x)) #define REFOBJECT_IS_NULL(x) ((x) == NULL) #define REFOBJECT_TO_TYPE(x,y) ((y)(x)) #endif #define REFOBJECT_FROM_TYPE(x) ((refobject_t)(refobject_base_t*)(x)) +#define REFOBJECT_GET_TYPE(x) (REFOBJECT_GET_BASE((x)) == NULL ? NULL : REFOBJECT_GET_BASE((x))->type) +#define REFOBJECT_GET_TYPENAME(x) (REFOBJECT_GET_TYPE((x)) == NULL ? NULL : REFOBJECT_GET_TYPE((x))->type_name) + +#define REFOBJECT_IS_VALID(x,type) (!REFOBJECT_IS_NULL((x)) && REFOBJECT_GET_TYPE((x)) == &(refobject_type__ ## type)) + #define REFOBJECT_CONTROL_VERSION 0 #define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t refobject_type__ ## type; #define REFOBJECT_DEFINE_TYPE(type, extra) const refobject_type_t refobject_type__ ## type = { \ diff --git a/src/tests/ctest_refobject.c b/src/tests/ctest_refobject.c index cc54a3e0..14144bd6 100644 --- a/src/tests/ctest_refobject.c +++ b/src/tests/ctest_refobject.c @@ -39,6 +39,44 @@ static void test_create_ref_unref(void) ctest_test("un-referenced (2 of 2)", refobject_unref(a) == 0); } +static void test_typename(void) +{ + refobject_base_t *a; + const char *typename; + + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); + + typename = REFOBJECT_GET_TYPENAME(a); + ctest_test("got typename", typename != NULL); + ctest_test("typename matches", strcmp(typename, "refobject_base_t") == 0); + + ctest_test("un-referenced", refobject_unref(a) == 0); +} + +static void test_valid(void) +{ + refobject_base_t *a; + + typedef struct { + refobject_base_t __base; + } ctest_test_type_t; + + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t, + REFOBJECT_DEFINE_TYPE_FREE(NULL) + ); + + ctest_test("NULL is not valid", !REFOBJECT_IS_VALID(REFOBJECT_NULL, refobject_base_t)); + + a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); + + ctest_test("is valid", REFOBJECT_IS_VALID(a, refobject_base_t)); + ctest_test("is valid as diffrent type", !REFOBJECT_IS_VALID(a, ctest_test_type_t)); + + ctest_test("un-referenced", refobject_unref(a) == 0); +} + static void test_sizes(void) { refobject_t a; @@ -202,6 +240,9 @@ int main (void) test_create_ref_unref(); + test_typename(); + test_valid(); + test_sizes(); test_name(); From 0cbc5c01edc461f7ac0e40768a6a3a4f35938e66 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 13:18:33 +0000 Subject: [PATCH 05/14] Update: Added comments --- src/refobject.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/refobject.h b/src/refobject.h index 9ba4d331..21fcb594 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -78,13 +78,20 @@ typedef void (*refobject_free_t)(refobject_t self, void **userdata); /* Meta type used to defined types. + * DO NOT use any of the members in here directly! */ typedef struct { + /* Size of this control structure */ size_t control_length; + /* ABI version of this structure */ int control_version; + + /* Total length of the objects to be created */ size_t type_length; + /* Name of type */ const char * type_name; + /* Callback to be called on final free() */ refobject_free_t type_freecb; } refobject_type_t; From 2dd9045842536abf17cba4f21765e82aa0519d08 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 14:11:24 +0000 Subject: [PATCH 06/14] Fix: Corrected structure of how refobject_type*__* is generated. --- src/refobject.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/refobject.h b/src/refobject.h index 21fcb594..7e375e4c 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -53,19 +53,22 @@ #define REFOBJECT_GET_TYPE(x) (REFOBJECT_GET_BASE((x)) == NULL ? NULL : REFOBJECT_GET_BASE((x))->type) #define REFOBJECT_GET_TYPENAME(x) (REFOBJECT_GET_TYPE((x)) == NULL ? NULL : REFOBJECT_GET_TYPE((x))->type_name) -#define REFOBJECT_IS_VALID(x,type) (!REFOBJECT_IS_NULL((x)) && REFOBJECT_GET_TYPE((x)) == &(refobject_type__ ## type)) +#define REFOBJECT_IS_VALID(x,type) (!REFOBJECT_IS_NULL((x)) && REFOBJECT_GET_TYPE((x)) == (refobject_type__ ## type)) -#define REFOBJECT_CONTROL_VERSION 0 -#define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t refobject_type__ ## type; -#define REFOBJECT_DEFINE_TYPE(type, extra) const refobject_type_t refobject_type__ ## type = { \ +#define REFOBJECT_CONTROL_VERSION 1 +#define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t * refobject_type__ ## type; +#define REFOBJECT_DEFINE_TYPE__RAW(type, ...) \ +static const refobject_type_t refobject_typedef__ ## type = \ +{ \ .control_length = sizeof(refobject_type_t), \ .control_version = REFOBJECT_CONTROL_VERSION, \ .type_length = sizeof(type), \ - .type_name = # type, \ - extra \ + .type_name = # type \ + , ## __VA_ARGS__ \ } -#define REFOBJECT_DEFINE_PRIVATE_TYPE(type, extra) static REFOBJECT_DEFINE_TYPE(type, extra) -#define REFOBJECT_DEFINE_TYPE_FREE(cb) .type_freecb = (cb) +#define REFOBJECT_DEFINE_TYPE(type, ...) REFOBJECT_DEFINE_TYPE__RAW(type, ## __VA_ARGS__); const refobject_type_t * refobject_type__ ## type = &refobject_typedef__ ## type +#define REFOBJECT_DEFINE_PRIVATE_TYPE(type, ...) REFOBJECT_DEFINE_TYPE__RAW(type, ## __VA_ARGS__); static const refobject_type_t * refobject_type__ ## type = &refobject_typedef__ ## type +#define REFOBJECT_DEFINE_TYPE_FREE(cb) .type_freecb = (cb) /* Type used for callback called then the object is actually freed * That is once all references to it are gone. @@ -119,7 +122,7 @@ REFOBJECT_FORWARD_TYPE(refobject_base_t); * All parameters beside len are optional and can be NULL/REFOBJECT_NULL. * If no freecb is given the userdata is freed (see refobject_free_t above). */ -#define refobject_new__new(type, userdata, name, associated) REFOBJECT_TO_TYPE(refobject_new__real(&(refobject_type__ ## type), (userdata), (name), (associated)), type*) +#define refobject_new__new(type, userdata, name, associated) REFOBJECT_TO_TYPE(refobject_new__real((refobject_type__ ## type), (userdata), (name), (associated)), type*) refobject_t refobject_new__real(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated); /* This increases the reference counter of the object */ From 9f6d3c30183798c7b0e303d48a250d0384a6bd23 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 14:15:00 +0000 Subject: [PATCH 07/14] Cleanup: Removed no longer needed REFOBJECT_DEFINE_TYPE_FREE(NULL)s --- src/refobject.c | 4 +--- src/tests/ctest_refobject.c | 20 +++++--------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/refobject.c b/src/refobject.c index 83f10434..e232553d 100644 --- a/src/refobject.c +++ b/src/refobject.c @@ -19,9 +19,7 @@ #define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *) -REFOBJECT_DEFINE_TYPE(refobject_base_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); +REFOBJECT_DEFINE_TYPE(refobject_base_t); static inline int check_type(const refobject_type_t *type) { diff --git a/src/tests/ctest_refobject.c b/src/tests/ctest_refobject.c index 14144bd6..734454aa 100644 --- a/src/tests/ctest_refobject.c +++ b/src/tests/ctest_refobject.c @@ -62,9 +62,7 @@ static void test_valid(void) refobject_base_t __base; } ctest_test_type_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t); ctest_test("NULL is not valid", !REFOBJECT_IS_VALID(REFOBJECT_NULL, refobject_base_t)); @@ -85,31 +83,23 @@ static void test_sizes(void) refobject_base_t __base; char padding[1024]; } ctest_test_type_a_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t); typedef struct { refobject_base_t __base; char padding[131072]; } ctest_test_type_b_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t); typedef struct { char padding[sizeof(refobject_base_t) - 1]; } ctest_test_type_c_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t); typedef struct { char padding[0]; } ctest_test_type_d_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t, - REFOBJECT_DEFINE_TYPE_FREE(NULL) - ); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t); a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_a_t, NULL, NULL, REFOBJECT_NULL)); ctest_test("refobject created with size=sizeof(refobject_base_t) + 1024", !REFOBJECT_IS_NULL(a)); From 491c4ab2f4641f432f22672786304ab6b6bc2397 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 14:27:07 +0000 Subject: [PATCH 08/14] Feature: Implemented simple API refobject_new() and refobject_new_ext() --- src/refobject.c | 38 +++++++++++++++++++++++++- src/refobject.h | 26 ++++++++++++++++-- src/tests/ctest_buffer.c | 2 +- src/tests/ctest_refobject.c | 53 ++++++++++++++++++++++++------------- 4 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/refobject.c b/src/refobject.c index e232553d..d2abed2e 100644 --- a/src/refobject.c +++ b/src/refobject.c @@ -19,7 +19,15 @@ #define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *) -REFOBJECT_DEFINE_TYPE(refobject_base_t); +static int return_zero(refobject_t self, const refobject_type_t *type, va_list ap) +{ + (void)self, (void)type, (void)ap; + return 0; +} + +REFOBJECT_DEFINE_TYPE(refobject_base_t, + REFOBJECT_DEFINE_TYPE_NEW(return_zero) + ); static inline int check_type(const refobject_type_t *type) { @@ -64,6 +72,34 @@ refobject_t refobject_new__real(const refobject_type_t *type, void *userdata return (refobject_t)ret; } +refobject_t refobject_new__simple(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated, ...) +{ + refobject_t ret; + int res; + va_list ap; + + if (!check_type(type)) + return REFOBJECT_NULL; + + if (!type->type_newcb) + return REFOBJECT_NULL; + + ret = refobject_new__real(type, userdata, name, associated); + if (REFOBJECT_IS_NULL(ret)) + return REFOBJECT_NULL; + + va_start(ap, associated); + res = type->type_newcb(ret, type, ap); + va_end(ap); + + if (res != 0) { + refobject_unref(ret); + return REFOBJECT_NULL; + } + + return ret; +} + int refobject_ref(refobject_t self) { if (REFOBJECT_IS_NULL(self)) diff --git a/src/refobject.h b/src/refobject.h index 7e375e4c..946a78a5 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -17,6 +17,8 @@ #include #endif +#include + #include "common/thread/thread.h" #include "icecasttypes.h" @@ -69,6 +71,9 @@ static const refobject_type_t refobject_typedef__ ## type = \ #define REFOBJECT_DEFINE_TYPE(type, ...) REFOBJECT_DEFINE_TYPE__RAW(type, ## __VA_ARGS__); const refobject_type_t * refobject_type__ ## type = &refobject_typedef__ ## type #define REFOBJECT_DEFINE_PRIVATE_TYPE(type, ...) REFOBJECT_DEFINE_TYPE__RAW(type, ## __VA_ARGS__); static const refobject_type_t * refobject_type__ ## type = &refobject_typedef__ ## type #define REFOBJECT_DEFINE_TYPE_FREE(cb) .type_freecb = (cb) +#define REFOBJECT_DEFINE_TYPE_NEW(cb) .type_newcb = (cb) + +typedef struct refobject_type_tag refobject_type_t; /* Type used for callback called then the object is actually freed * That is once all references to it are gone. @@ -80,11 +85,23 @@ static const refobject_type_t refobject_typedef__ ## type = \ */ typedef void (*refobject_free_t)(refobject_t self, void **userdata); +/* Type used for callback called then the object is created + * using the generic refobject_new(). + * + * Additional parameters passed to refobject_new() are passed + * in the list ap. All limitations of apply. + * + * This function must return zero in case of success and + * non-zero in case of error. In case of error refobject_unref() + * is called internally to clear the object. + */ +typedef int (*refobject_new_t)(refobject_t self, const refobject_type_t *type, va_list ap); + /* Meta type used to defined types. * DO NOT use any of the members in here directly! */ -typedef struct { +struct refobject_type_tag { /* Size of this control structure */ size_t control_length; /* ABI version of this structure */ @@ -96,7 +113,9 @@ typedef struct { const char * type_name; /* Callback to be called on final free() */ refobject_free_t type_freecb; -} refobject_type_t; + /* Callback to be callback by refobject_new() */ + refobject_new_t type_newcb; +}; /* Only defined here as the size must be publically known. * DO NOT use any of the members in here directly! @@ -124,6 +143,9 @@ REFOBJECT_FORWARD_TYPE(refobject_base_t); */ #define refobject_new__new(type, userdata, name, associated) REFOBJECT_TO_TYPE(refobject_new__real((refobject_type__ ## type), (userdata), (name), (associated)), type*) refobject_t refobject_new__real(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated); +#define refobject_new(type, ...) REFOBJECT_TO_TYPE(refobject_new__simple((refobject_type__ ## type), NULL, NULL, REFOBJECT_NULL, ## __VA_ARGS__), type*) +#define refobject_new_ext(type, userdata, name, associated, ...) REFOBJECT_TO_TYPE(refobject_new__simple((refobject_type__ ## type), (userdata), (name), (associated), ## __VA_ARGS__), type*) +refobject_t refobject_new__simple(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated, ...); /* This increases the reference counter of the object */ int refobject_ref(refobject_t self); diff --git a/src/tests/ctest_buffer.c b/src/tests/ctest_buffer.c index d8158e08..feec0384 100644 --- a/src/tests/ctest_buffer.c +++ b/src/tests/ctest_buffer.c @@ -83,7 +83,7 @@ static void test_associated(void) refobject_base_t *a; buffer_t *b; - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); diff --git a/src/tests/ctest_refobject.c b/src/tests/ctest_refobject.c index 734454aa..fbea21f0 100644 --- a/src/tests/ctest_refobject.c +++ b/src/tests/ctest_refobject.c @@ -16,6 +16,12 @@ #include "../refobject.h" +static int return_zero(refobject_t self, const refobject_type_t *type, va_list ap) +{ + (void)self, (void)type, (void)ap; + return 0; +} + static void test_ptr(void) { refobject_t a; @@ -31,7 +37,7 @@ static void test_create_ref_unref(void) { refobject_base_t *a; - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ctest_test("referenced", refobject_ref(a) == 0); @@ -44,7 +50,7 @@ static void test_typename(void) refobject_base_t *a; const char *typename; - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); typename = REFOBJECT_GET_TYPENAME(a); @@ -66,7 +72,7 @@ static void test_valid(void) ctest_test("NULL is not valid", !REFOBJECT_IS_VALID(REFOBJECT_NULL, refobject_base_t)); - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ctest_test("is valid", REFOBJECT_IS_VALID(a, refobject_base_t)); @@ -83,39 +89,47 @@ static void test_sizes(void) refobject_base_t __base; char padding[1024]; } ctest_test_type_a_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t, + REFOBJECT_DEFINE_TYPE_NEW(return_zero) + ); typedef struct { refobject_base_t __base; char padding[131072]; } ctest_test_type_b_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t, + REFOBJECT_DEFINE_TYPE_NEW(return_zero) + ); typedef struct { char padding[sizeof(refobject_base_t) - 1]; } ctest_test_type_c_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t, + REFOBJECT_DEFINE_TYPE_NEW(return_zero) + ); typedef struct { char padding[0]; } ctest_test_type_d_t; - REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t); + REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t, + REFOBJECT_DEFINE_TYPE_NEW(return_zero) + ); - a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_a_t, NULL, NULL, REFOBJECT_NULL)); + a = REFOBJECT_FROM_TYPE(refobject_new(ctest_test_type_a_t)); ctest_test("refobject created with size=sizeof(refobject_base_t) + 1024", !REFOBJECT_IS_NULL(a)); ctest_test("un-referenced", refobject_unref(a) == 0); - a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_b_t, NULL, NULL, REFOBJECT_NULL)); + a = REFOBJECT_FROM_TYPE(refobject_new(ctest_test_type_b_t)); ctest_test("refobject created with size=sizeof(refobject_base_t) + 131072", !REFOBJECT_IS_NULL(a)); ctest_test("un-referenced", refobject_unref(a) == 0); - a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_c_t, NULL, NULL, REFOBJECT_NULL)); + a = REFOBJECT_FROM_TYPE(refobject_new(ctest_test_type_c_t)); ctest_test("refobject created with size=sizeof(refobject_base_t) - 1", REFOBJECT_IS_NULL(a)); if (!REFOBJECT_IS_NULL(a)) { ctest_test("un-referenced", refobject_unref(a) == 0); } - a = REFOBJECT_FROM_TYPE(refobject_new__new(ctest_test_type_d_t, NULL, NULL, REFOBJECT_NULL)); + a = REFOBJECT_FROM_TYPE(refobject_new(ctest_test_type_d_t)); ctest_test("refobject created with size=0", REFOBJECT_IS_NULL(a)); if (!REFOBJECT_IS_NULL(a)) { ctest_test("un-referenced", refobject_unref(a) == 0); @@ -128,7 +142,7 @@ static void test_name(void) const char *name = "test object name"; const char *ret; - a = refobject_new__new(refobject_base_t, NULL, name, REFOBJECT_NULL); + a = refobject_new_ext(refobject_base_t, NULL, name, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_name(a); @@ -145,7 +159,7 @@ static void test_userdata(void) void *userdata = &tmp; void *ret; - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_userdata(a); @@ -159,7 +173,7 @@ static void test_userdata(void) ctest_test("un-referenced", refobject_unref(a) == 0); - a = refobject_new__new(refobject_base_t, userdata, NULL, REFOBJECT_NULL); + a = refobject_new_ext(refobject_base_t, userdata, NULL, REFOBJECT_NULL); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); ret = refobject_get_userdata(a); ctest_test("get userdata", ret == userdata); @@ -173,10 +187,10 @@ static void test_associated(void) { refobject_base_t *a, *b; - a = refobject_new__new(refobject_base_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(refobject_base_t); ctest_test("refobject created", !REFOBJECT_IS_NULL(a)); - b = refobject_new__new(refobject_base_t, NULL, NULL, a); + b = refobject_new_ext(refobject_base_t, NULL, NULL, a); ctest_test("refobject created with associated", !REFOBJECT_IS_NULL(b)); ctest_test("un-referenced (1 of 2)", refobject_unref(b) == 0); @@ -197,17 +211,18 @@ static void test_freecb(void) ctest_test_type_t *a; REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t, - REFOBJECT_DEFINE_TYPE_FREE(test_freecb__freecb) + REFOBJECT_DEFINE_TYPE_FREE(test_freecb__freecb), + REFOBJECT_DEFINE_TYPE_NEW(return_zero) ); test_freecb__called = 0; - a = refobject_new__new(ctest_test_type_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(ctest_test_type_t); ctest_test("refobject created", a != NULL); ctest_test("un-referenced", refobject_unref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb called", test_freecb__called == 1); test_freecb__called = 0; - a = refobject_new__new(ctest_test_type_t, NULL, NULL, REFOBJECT_NULL); + a = refobject_new(ctest_test_type_t); ctest_test("refobject created", a != NULL); ctest_test("referenced", refobject_ref(REFOBJECT_FROM_TYPE(a)) == 0); ctest_test("freecb uncalled", test_freecb__called == 0); From 48bb4773014c4106511f421542c18c6cf46c5ebe Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 14:42:37 +0000 Subject: [PATCH 09/14] Feature: Added REFOBJECT_DEFINE_TYPE_NEW_NOOP() --- src/refobject.c | 4 ++-- src/refobject.h | 2 ++ src/tests/ctest_refobject.c | 16 +++++----------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/refobject.c b/src/refobject.c index d2abed2e..7b8eb464 100644 --- a/src/refobject.c +++ b/src/refobject.c @@ -19,14 +19,14 @@ #define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *) -static int return_zero(refobject_t self, const refobject_type_t *type, va_list ap) +int refobject_new__return_zero(refobject_t self, const refobject_type_t *type, va_list ap) { (void)self, (void)type, (void)ap; return 0; } REFOBJECT_DEFINE_TYPE(refobject_base_t, - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); static inline int check_type(const refobject_type_t *type) diff --git a/src/refobject.h b/src/refobject.h index 946a78a5..4755d70e 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -72,8 +72,10 @@ static const refobject_type_t refobject_typedef__ ## type = \ #define REFOBJECT_DEFINE_PRIVATE_TYPE(type, ...) REFOBJECT_DEFINE_TYPE__RAW(type, ## __VA_ARGS__); static const refobject_type_t * refobject_type__ ## type = &refobject_typedef__ ## type #define REFOBJECT_DEFINE_TYPE_FREE(cb) .type_freecb = (cb) #define REFOBJECT_DEFINE_TYPE_NEW(cb) .type_newcb = (cb) +#define REFOBJECT_DEFINE_TYPE_NEW_NOOP() .type_newcb = refobject_new__return_zero typedef struct refobject_type_tag refobject_type_t; +int refobject_new__return_zero(refobject_t self, const refobject_type_t *type, va_list ap); /* Type used for callback called then the object is actually freed * That is once all references to it are gone. diff --git a/src/tests/ctest_refobject.c b/src/tests/ctest_refobject.c index fbea21f0..36cb292e 100644 --- a/src/tests/ctest_refobject.c +++ b/src/tests/ctest_refobject.c @@ -16,12 +16,6 @@ #include "../refobject.h" -static int return_zero(refobject_t self, const refobject_type_t *type, va_list ap) -{ - (void)self, (void)type, (void)ap; - return 0; -} - static void test_ptr(void) { refobject_t a; @@ -90,7 +84,7 @@ static void test_sizes(void) char padding[1024]; } ctest_test_type_a_t; REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_a_t, - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); typedef struct { @@ -98,21 +92,21 @@ static void test_sizes(void) char padding[131072]; } ctest_test_type_b_t; REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_b_t, - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); typedef struct { char padding[sizeof(refobject_base_t) - 1]; } ctest_test_type_c_t; REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_c_t, - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); typedef struct { char padding[0]; } ctest_test_type_d_t; REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_d_t, - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); a = REFOBJECT_FROM_TYPE(refobject_new(ctest_test_type_a_t)); @@ -212,7 +206,7 @@ static void test_freecb(void) REFOBJECT_DEFINE_PRIVATE_TYPE(ctest_test_type_t, REFOBJECT_DEFINE_TYPE_FREE(test_freecb__freecb), - REFOBJECT_DEFINE_TYPE_NEW(return_zero) + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); test_freecb__called = 0; From bdbe3379cec7c0442ae9de04c35398c642cb67c4 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 14:48:25 +0000 Subject: [PATCH 10/14] Update: Replaced buffer_new_simple() by refobject_new(buffer_t) --- src/buffer.c | 7 ++++--- src/buffer.h | 4 +++- src/tests/ctest_buffer.c | 18 +++++++++--------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 26c938f3..33259993 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -38,12 +38,13 @@ static void __free(refobject_t self, void **userdata) } REFOBJECT_DEFINE_TYPE(buffer_t, - REFOBJECT_DEFINE_TYPE_FREE(__free) + REFOBJECT_DEFINE_TYPE_FREE(__free), + REFOBJECT_DEFINE_TYPE_NEW_NOOP() ); buffer_t * buffer_new(ssize_t preallocation, void *userdata, const char *name, refobject_t associated) { - buffer_t *buffer = refobject_new__new(buffer_t, userdata, name, associated); + buffer_t *buffer = refobject_new_ext(buffer_t, userdata, name, associated); if (!buffer) return NULL; @@ -56,7 +57,7 @@ buffer_t * buffer_new(ssize_t preallocation, void *userdata, const char *name, buffer_t * buffer_new_simple(void) { - return buffer_new(-1, NULL, NULL, REFOBJECT_NULL); + return refobject_new(buffer_t); } void buffer_preallocate(buffer_t *buffer, size_t request) diff --git a/src/buffer.h b/src/buffer.h index c7490582..c2a33a62 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -39,7 +39,9 @@ REFOBJECT_FORWARD_TYPE(buffer_t); */ buffer_t * buffer_new(ssize_t preallocation, void *userdata, const char *name, refobject_t associated); -/* This creates a new buffer with defaults. +/* Depreciated: This creates a new buffer with defaults. + * Do NOT use this. Use refobject_new(buffer_t) + * * This is the same as: * buffer_new(-1, NULL, NULL, REFOBJECT_NULL) */ diff --git a/src/tests/ctest_buffer.c b/src/tests/ctest_buffer.c index feec0384..682d3e00 100644 --- a/src/tests/ctest_buffer.c +++ b/src/tests/ctest_buffer.c @@ -25,7 +25,7 @@ static void test_create_ref_unref(void) ctest_test("buffer created", a != NULL); ctest_test("un-referenced", refobject_unref(a) == 0); - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("un-referenced", refobject_unref(a) == 0); @@ -102,7 +102,7 @@ static void test_empty(void) const char *string; int ret; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ret = buffer_get_data(a, &data, &length); @@ -147,7 +147,7 @@ static void test_string(void) const char *string = NULL; int ret; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("pushed string", buffer_push_string(a, hw) == 0); ret = buffer_get_string(a, &string); @@ -182,7 +182,7 @@ static void test_binary(void) size_t length; const void *data; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("pushed data pattern a", buffer_push_data(a, pattern_a, sizeof(pattern_a)) == 0); @@ -238,7 +238,7 @@ static void test_shift(void) buffer_t *a; const char *pattern = "AABBBCC"; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("pushed string", buffer_push_string(a, pattern) == 0); @@ -264,7 +264,7 @@ static void test_length(void) const char *match_b = "AABB"; const char *match_c = ""; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("pushed string", buffer_push_string(a, pattern) == 0); @@ -290,7 +290,7 @@ static void test_printf(void) const char *match_b = ":Hello World!:<-127 >"; const char *match_c = ":Hello World!:<-127 >? +127?"; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer created", a != NULL); ctest_test("Set length to match pattern a", buffer_push_printf(a, ":%s:", str) == 0); @@ -310,9 +310,9 @@ static void test_push_buffer(void) const char *pattern = "AABBBCC"; const char *match_a = "AABBBCCAABBBCC"; - a = buffer_new_simple(); + a = refobject_new(buffer_t); ctest_test("buffer a created", a != NULL); - b = buffer_new_simple(); + b = refobject_new(buffer_t); ctest_test("buffer b created", b != NULL); ctest_test("pushed string", buffer_push_string(a, pattern) == 0); From b875e80230af52e451b9c01201b364ab549842f8 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 15:01:10 +0000 Subject: [PATCH 11/14] Update: Replaced module_container_new() --- src/global.c | 2 +- src/module.c | 18 ++++++++---------- src/module.h | 1 - 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/global.c b/src/global.c index db126887..9671e036 100644 --- a/src/global.c +++ b/src/global.c @@ -38,7 +38,7 @@ void global_initialize(void) global.clients = 0; global.sources = 0; global.source_tree = avl_tree_new(source_compare_sources, NULL); - global.modulecontainer = module_container_new(); + global.modulecontainer = refobject_new(module_container_t); thread_mutex_create(&_global_mutex); } diff --git a/src/module.c b/src/module.c index 19ad5adb..52287f42 100644 --- a/src/module.c +++ b/src/module.c @@ -50,24 +50,22 @@ static void __module_container_free(refobject_t self, void **userdata) avl_tree_free(cont->module, (avl_free_key_fun_type)refobject_unref); } -REFOBJECT_DEFINE_TYPE(module_container_t, - REFOBJECT_DEFINE_TYPE_FREE(__module_container_free) - ); - -module_container_t * module_container_new(void) +int __module_container_new(refobject_t self, const refobject_type_t *type, va_list ap) { - module_container_t *ret = refobject_new__new(module_container_t, NULL, NULL, NULL); - - if (!ret) - return NULL; + module_container_t *ret = REFOBJECT_TO_TYPE(self, module_container_t*); thread_mutex_create(&(ret->lock)); ret->module = avl_tree_new(compare_refobject_t_name, NULL); - return ret; + return 0; } +REFOBJECT_DEFINE_TYPE(module_container_t, + REFOBJECT_DEFINE_TYPE_FREE(__module_container_free), + REFOBJECT_DEFINE_TYPE_NEW(__module_container_new) + ); + int module_container_add_module(module_container_t *self, module_t *module) { if (!self) diff --git a/src/module.h b/src/module.h index 69b3c334..20ed3ada 100644 --- a/src/module.h +++ b/src/module.h @@ -25,7 +25,6 @@ typedef struct { REFOBJECT_FORWARD_TYPE(module_container_t); REFOBJECT_FORWARD_TYPE(module_t); -module_container_t * module_container_new(void); int module_container_add_module(module_container_t *self, module_t *module); int module_container_delete_module(module_container_t *self, const char *name); module_t * module_container_get_module(module_container_t *self, const char *name); From fea817da2db72a11acbf25e0a6994d2fca9e9b1c Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 10 Oct 2018 15:06:45 +0000 Subject: [PATCH 12/14] Update: Replaced listensocket_container_new() --- src/connection.c | 2 +- src/listensocket.c | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/connection.c b/src/connection.c index a71333ce..c533c15e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1703,7 +1703,7 @@ void connection_setup_sockets (ice_config_t *config) allowed_ip = matchfile_new(config->allowfile); } - global.listensockets = listensocket_container_new(); + global.listensockets = refobject_new(listensocket_container_t); listensocket_container_configure(global.listensockets, config); global_unlock(); diff --git a/src/listensocket.c b/src/listensocket.c index 5ed9ad30..2fef714a 100644 --- a/src/listensocket.c +++ b/src/listensocket.c @@ -150,26 +150,25 @@ static void __listensocket_container_free(refobject_t self, void **userdata) thread_mutex_destroy(&container->lock); } -REFOBJECT_DEFINE_TYPE(listensocket_container_t, - REFOBJECT_DEFINE_TYPE_FREE(__listensocket_container_free) - ); - -listensocket_container_t * listensocket_container_new(void) +int __listensocket_container_new(refobject_t self, const refobject_type_t *type, va_list ap) { - listensocket_container_t *self = refobject_new__new(listensocket_container_t, NULL, NULL, NULL); - if (!self) - return NULL; + listensocket_container_t *ret = REFOBJECT_TO_TYPE(self, listensocket_container_t*); - self->sock = NULL; - self->sock_len = 0; - self->sockcount_cb = NULL; - self->sockcount_userdata = NULL; + ret->sock = NULL; + ret->sock_len = 0; + ret->sockcount_cb = NULL; + ret->sockcount_userdata = NULL; - thread_mutex_create(&self->lock); + thread_mutex_create(&ret->lock); - return self; + return 0; } +REFOBJECT_DEFINE_TYPE(listensocket_container_t, + REFOBJECT_DEFINE_TYPE_FREE(__listensocket_container_free), + REFOBJECT_DEFINE_TYPE_NEW(__listensocket_container_new) + ); + static inline void __find_matching_entry(listensocket_container_t *self, const listener_t *listener, listensocket_t ***found, int **ref) { const listener_t *b; From a242f0f77b52190a41da8ac654bca2f7cac03ebd Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 11 Oct 2018 08:58:22 +0000 Subject: [PATCH 13/14] Update: Replaced reportxml_new() and reportxml_database_new() --- src/cfgfile.c | 2 +- src/client.c | 2 +- src/reportxml.c | 66 +++++++++++++++++++++++++------------------------ src/reportxml.h | 8 ++++-- 4 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/cfgfile.c b/src/cfgfile.c index 2a014b1e..b8a973fd 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -232,7 +232,7 @@ void config_init_configuration(ice_config_t *configuration) { memset(configuration, 0, sizeof(ice_config_t)); _set_defaults(configuration); - configuration->reportxml_db = reportxml_database_new(); + configuration->reportxml_db = refobject_new(reportxml_database_t); } static inline void __read_int(xmlDocPtr doc, xmlNodePtr node, int *val, const char *warning) diff --git a/src/client.c b/src/client.c index 5c91cd13..e7e1bd51 100644 --- a/src/client.c +++ b/src/client.c @@ -661,7 +661,7 @@ reportxml_t *client_get_reportxml(const char *state_definition, const char *stat if (!report) { reportxml_node_t *rootnode, *incidentnode, *statenode; - report = reportxml_new(); + report = refobject_new(reportxml_t); rootnode = reportxml_get_root_node(report); incidentnode = reportxml_node_new(REPORTXML_NODE_TYPE_INCIDENT, NULL, NULL, NULL); statenode = reportxml_node_new(REPORTXML_NODE_TYPE_STATE, NULL, state_definition, state_akindof); diff --git a/src/reportxml.c b/src/reportxml.c index 89b45e61..afed1966 100644 --- a/src/reportxml.c +++ b/src/reportxml.c @@ -236,8 +236,22 @@ static void __report_free(refobject_t self, void **userdata) refobject_unref(report->root); } +static int __report_new(refobject_t self, const refobject_type_t *type, va_list ap) +{ + reportxml_t *ret = REFOBJECT_TO_TYPE(self, reportxml_t*); + reportxml_node_t *root = reportxml_node_new(REPORTXML_NODE_TYPE_REPORT, NULL, NULL, NULL); + + if (!root) + return -1; + + ret->root = root; + + return 0; +} + REFOBJECT_DEFINE_TYPE(reportxml_t, - REFOBJECT_DEFINE_TYPE_FREE(__report_free) + REFOBJECT_DEFINE_TYPE_FREE(__report_free), + REFOBJECT_DEFINE_TYPE_NEW(__report_new) ); static reportxml_t * reportxml_new_with_root(reportxml_node_t *root) @@ -255,20 +269,7 @@ static reportxml_t * reportxml_new_with_root(reportxml_node_t *root) reportxml_t * reportxml_new(void) { - reportxml_node_t *root = reportxml_node_new(REPORTXML_NODE_TYPE_REPORT, NULL, NULL, NULL); - reportxml_t *ret; - - if (!root) - return NULL; - - ret = reportxml_new_with_root(root); - - if (!ret) { - refobject_unref(root); - return NULL; - } - - return ret; + return refobject_new(reportxml_t); } reportxml_node_t * reportxml_get_root_node(reportxml_t *report) @@ -983,26 +984,27 @@ static int __compare_definitions(void *arg, void *a, void *b) return ret; } +static int __database_new(refobject_t self, const refobject_type_t *type, va_list ap) +{ + reportxml_database_t *ret = REFOBJECT_TO_TYPE(self, reportxml_database_t*); + + thread_mutex_create(&(ret->lock)); + + ret->definitions = avl_tree_new(__compare_definitions, NULL); + if (!ret->definitions) + return -1; + + return 0; +} + REFOBJECT_DEFINE_TYPE(reportxml_database_t, - REFOBJECT_DEFINE_TYPE_FREE(__database_free) + REFOBJECT_DEFINE_TYPE_FREE(__database_free), + REFOBJECT_DEFINE_TYPE_NEW(__database_new) ); reportxml_database_t * reportxml_database_new(void) { - reportxml_database_t *ret = refobject_new__new(reportxml_database_t, NULL, NULL, NULL); - - if (!ret) - return NULL; - - ret->definitions = avl_tree_new(__compare_definitions, NULL); - if (!ret->definitions) { - refobject_unref(ret); - return NULL; - } - - thread_mutex_create(&(ret->lock)); - - return ret; + return refobject_new(reportxml_database_t); } int reportxml_database_add_report(reportxml_database_t *db, reportxml_t *report) @@ -1305,7 +1307,7 @@ reportxml_t * reportxml_database_build_report(reportxml_database_t *db /* Empty definition? Not exactly an exciting report... */ ICECAST_LOG_WARN("Empty definition for \"%H\". Returning empty report. This is likely an error.", id); refobject_unref(definition); - return reportxml_new(); + return refobject_new(reportxml_t); } if (type == REPORTXML_NODE_TYPE__ERROR) { @@ -1333,7 +1335,7 @@ reportxml_t * reportxml_database_build_report(reportxml_database_t *db break; } - ret = reportxml_new(); + ret = refobject_new(reportxml_t); if (!ret) { refobject_unref(definition); ICECAST_LOG_ERROR("Can not allocate new report. BAD."); diff --git a/src/reportxml.h b/src/reportxml.h index b58ca9c3..fb4c494c 100644 --- a/src/reportxml.h +++ b/src/reportxml.h @@ -68,7 +68,9 @@ REFOBJECT_FORWARD_TYPE(reportxml_database_t); /* ---[ Document level ]--- */ /* The document object is NOT thread safe. */ -/* This creates a new, empty report XML document */ +/* Depreciated: This creates a new, empty report XML document + * Do NOT use this. Use refobject_new(reportxml_t) + */ reportxml_t * reportxml_new(void); /* This gets the root node of a report XML document */ reportxml_node_t * reportxml_get_root_node(reportxml_t *report); @@ -128,7 +130,9 @@ xmlNodePtr reportxml_node_get_xml_child(reportxml_node_t *node, siz /* The database object is thread safe. */ -/* Create a new database object */ +/* Depreciated: Create a new database object + * Do NOT use this. Use refobject_new(reportxml_database_t) + */ reportxml_database_t * reportxml_database_new(void); /* Add an report to the database */ int reportxml_database_add_report(reportxml_database_t *db, reportxml_t *report); From d8c887aa37fe7b47a841e942c96b778271b0ae67 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 11 Oct 2018 09:17:40 +0000 Subject: [PATCH 14/14] Update: Added comments about the API --- src/refobject.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/refobject.h b/src/refobject.h index 4755d70e..2e7ec504 100644 --- a/src/refobject.h +++ b/src/refobject.h @@ -37,6 +37,15 @@ * as the operation is only defined for it's members. * REFOBJECT_TO_TYPE(type,x) * This casts the refobject (x) to the type (type). + * REFOBJECT_FROM_TYPE(x) + * Converts an object to a (refobject_t). This is the inverse of REFOBJECT_TO_TYPE(). + * REFOBJECT_GET_TYPENAME(x) + * Get the name of the type of the object. + * REFOBJECT_IS_VALID(x,type) + * This returns true if x is not NULL and of type type. + * REFOBJECT_GET_BASE(x) + * REFOBJECT_GET_TYPE(x) + * Not to be used by the user. */ #ifdef HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION #define REFOBJECT_NULL ((refobject_t)(refobject_base_t*)NULL) @@ -57,6 +66,33 @@ #define REFOBJECT_IS_VALID(x,type) (!REFOBJECT_IS_NULL((x)) && REFOBJECT_GET_TYPE((x)) == (refobject_type__ ## type)) +/* The following macros are used to define types. + * + * REFOBJECT_FORWARD_TYPE(type) + * Adds a forward decleration for the type. This is useful for non private types. + * REFOBJECT_DEFINE_TYPE(type,extras...) + * This defines a public type. One or more of the EXTRA macros be used. + * REFOBJECT_DEFINE_PRIVATE_TYPE(type,extras...) + * Same as REFOBJECT_DEFINE_TYPE() but defines private type. + * + * EXTRA Marcos: + * REFOBJECT_DEFINE_TYPE_FREE(cb) + * This defines a callback to be called when the object is freed. + * cb must be of type refobject_free_t. + * REFOBJECT_DEFINE_TYPE_NEW(cb) + * This defines a callback to be called when a new object is created. + * cb must be of type refobject_new_t. + * REFOBJECT_DEFINE_TYPE_NEW_NOOP() + * This installs a dummy callback for creation. This allows the type + * to be created using refobject_new(type) as with REFOBJECT_DEFINE_TYPE_NEW(). + * This is useful for types that do not need to be initialized more than what + * refobject_new() already does. + * + * Other Macros: + * REFOBJECT_CONTROL_VERSION + * REFOBJECT_DEFINE_TYPE__RAW() + * Not to be used by the user. + */ #define REFOBJECT_CONTROL_VERSION 1 #define REFOBJECT_FORWARD_TYPE(type) extern const refobject_type_t * refobject_type__ ## type; #define REFOBJECT_DEFINE_TYPE__RAW(type, ...) \