1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2025-01-03 14:56:36 -05:00

Merge branch 'update-ro' into libigloo

This commit is contained in:
Philipp Schafft 2019-07-08 07:45:25 +00:00
commit c1b2715265
6 changed files with 429 additions and 34 deletions

View File

@ -81,6 +81,8 @@ void igloo_buffer_preallocate(igloo_buffer_t *buffer, size_t request);
int igloo_buffer_get_data(igloo_buffer_t *buffer, const void **data, size_t *length); int igloo_buffer_get_data(igloo_buffer_t *buffer, const void **data, size_t *length);
/* Gets data as a string. The string is '\0'-terminated. /* Gets data as a string. The string is '\0'-terminated.
* igloo_ro_stringify(buffer) will also return this buffer.
*
* Parameters: * Parameters:
* buffery * buffery
* The buffer to operate on. * The buffer to operate on.

View File

@ -42,7 +42,7 @@ extern "C" {
*/ */
typedef int (*igloo_interface_free_t)(igloo_INTERFACE_BASIC_ARGS); typedef int (*igloo_interface_free_t)(igloo_INTERFACE_BASIC_ARGS);
#define igloo_INTERFACE_DESCRIPTION_BASE__VERSION 1 #define igloo_INTERFACE_DESCRIPTION_BASE__VERSION 1
typedef struct { typedef struct {
size_t base_length; size_t base_length;

View File

@ -24,6 +24,11 @@
extern "C" { extern "C" {
#endif #endif
#include <igloo/config.h>
#ifdef IGLOO_CTC_HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdarg.h> #include <stdarg.h>
#include <igloo/config.h> #include <igloo/config.h>
@ -49,6 +54,106 @@ typedef void (*igloo_ro_free_t)(igloo_ro_t self);
*/ */
typedef int (*igloo_ro_new_t)(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap); typedef int (*igloo_ro_new_t)(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap);
/* Type used to store flags for clone operations.
*/
#ifdef IGLOO_CTC_HAVE_STDINT_H
typedef uint_least32_t igloo_ro_cf_t;
#else
typedef unsigned long int igloo_ro_cf_t;
#endif
/* No clone flags set. Usefull for variable initialization. */
#define igloo_RO_CF_NONE ((igloo_ro_cf_t)0x0000)
/* Make a shallow copy of the object */
#define igloo_RO_CF_SHALLOW ((igloo_ro_cf_t)0x0001)
/* Make a deep copy of the object */
#define igloo_RO_CF_DEEP ((igloo_ro_cf_t)0x0002)
/* Make a copy of the object that shares part of it's state with the original.
* This is similar to using dup() on a POSIX filehandle.
* This is useful when interacting with IO.
*/
#define igloo_RO_CF_DUP ((igloo_ro_cf_t)0x0004)
/* Defaults to use if required and allowed is igloo_RO_CF_NONE */
#define igloo_RO_CF_DEFAULT (igloo_RO_CF_SHALLOW|igloo_RO_CF_DEEP)
/* Type uses for callback called when the object should be cloned.
*
* A clone of the object must never have the same address of the object that was cloned.
*
* Parameters:
* self
* The object to clone.
* required, allowed
* See igloo_ro_clone().
* name, associated
* See igloo_ro_new().
*/
typedef igloo_ro_t (*igloo_ro_clone_t)(igloo_ro_t self, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated);
/* Type used for callback called when the object needs to be converted to another type.
*
* This callback is not used when a object of the same type is requested.
* On that case clone is requested.
*
* There are two cases that must be handled by the callback:
* 0) The object self is of the same type as this callback is set for and type is pointing to different type.
* 1) The object self is of any type and type is pointing to the type this callback was set to.
*
* If the callback can not convert it must return igloo_RO_NULL.
*
* Parameters:
* self
* The object to convert.
* type
* The type to convert to.
* required, allowed
* See igloo_ro_clone().
* name, associated
* See igloo_ro_new().
*/
typedef igloo_ro_t (*igloo_ro_convert_t)(igloo_ro_t self, const igloo_ro_type_t *type, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated);
/* Type used for callback called when the object needs to be converted to a string.
*
* This is used mostly for debugging or preseting the object to the user.
* The callback is not expected to return a string that can be used to reconstruct the object.
*/
typedef char * (*igloo_ro_stringify_t)(igloo_ro_t self);
/* Type used as a result of a compare between objects.
*/
typedef enum {
/* The objects could not be compared.
* Common cases may be that when one is NULL and the other is not NULL
* or when both are of difference types that can not be compared to each other
* (e.g. a IO handle and a buffer.)
*/
igloo_RO_CR__ERROR = -1,
/* Both objects represent the same thing but are not the same object.
* See also igloo_RO_CR_SAME.
*/
igloo_RO_CR_EQUAL = 0,
/* Both objects are distinct and no other relation can be applied. */
igloo_RO_CR_NOTEQUAL,
/* Object A is less than object B. */
igloo_RO_CR_ALESSTHANB,
/* Object A is greather than object B. */
igloo_RO_CR_AGREATERTHANB,
/* Both objects are the same.
* That is then they share the same address in memory.
*/
igloo_RO_CR_SAME
} igloo_ro_cr_t;
/* Type used for callback called then two objects must be compared.
*
* Object a is always a object that belongs to the type this callback was set for.
* Objects a, and b are not igloo_RO_NULL.
* Objects a, and b may be of diffrent type.
* Objects a, and b are not the same (See igloo_RO_CR_SAME).
*/
typedef igloo_ro_cr_t (*igloo_ro_compare_t)(igloo_ro_t a, igloo_ro_t b);
/* Meta type used to defined types. /* Meta type used to defined types.
* DO NOT use any of the members in here directly! * DO NOT use any of the members in here directly!
*/ */
@ -60,51 +165,69 @@ typedef int (*igloo_ro_new_t)(igloo_ro_t self, const igloo_ro_type_t *type, va_l
*/ */
struct igloo_ro_type_tag { struct igloo_ro_type_tag {
/* Size of this control structure */ /* Size of this control structure */
size_t control_length; size_t control_length;
/* ABI version of this structure */ /* ABI version of this structure */
int control_version; int control_version;
/* Total length of the objects to be created */ /* Total length of the objects to be created */
size_t type_length; size_t type_length;
/* Name of type */ /* Name of type */
const char * type_name; const char * type_name;
/* STILL UNUSED: Parent type */
const igloo_ro_type_t * type_parent;
/* Callback to be called on final free() */ /* Callback to be called on final free() */
igloo_ro_free_t type_freecb; igloo_ro_free_t type_freecb;
/* Callback to be callback by igloo_ro_new() */ /* Callback to be called by igloo_ro_new() */
igloo_ro_new_t type_newcb; igloo_ro_new_t type_newcb;
/* Callback to be called by igloo_ro_clone() */
igloo_ro_clone_t type_clonecb;
/* Callback to be called by igloo_ro_convert() */
igloo_ro_convert_t type_convertcb;
/* Callback to be called by igloo_ro_stringify() */
igloo_ro_stringify_t type_stringifycb;
/* Callback to be called by igloo_ro_compare() */
igloo_ro_compare_t type_comparecb;
}; };
struct igloo_ro_base_tag { struct igloo_ro_base_tag {
/* Type of the object */ /* Type of the object */
const igloo_ro_type_t * type; const igloo_ro_type_t * type;
/* Reference counters */ /* Reference counters */
size_t refc; size_t refc;
size_t wrefc; size_t wrefc;
/* Mutex for igloo_ro_*(). */ /* Mutex for igloo_ro_*(). */
igloo_mutex_t lock; igloo_mutex_t lock;
/* Name of the object. */ /* Name of the object. */
char * name; char * name;
/* Associated objects */ /* Associated objects */
igloo_ro_t associated; igloo_ro_t associated;
/* STILL UNUSED: Instance objects */
igloo_ro_t instance;
}; };
int igloo_ro_new__return_zero(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap); int igloo_ro_new__return_zero(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap);
/* ---[ END PRIVATE ]--- */ /* ---[ END PRIVATE ]--- */
igloo_ro_t igloo_RO_TO_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type);
#ifdef IGLOO_CTC_HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION #ifdef IGLOO_CTC_HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION
#define igloo_RO__GETBASE(x) (((igloo_ro_t)(x)).subtype__igloo_ro_base_t) #define igloo_RO__GETBASE(x) (((igloo_ro_t)(x)).subtype__igloo_ro_base_t)
#define igloo_RO_NULL ((igloo_ro_t)(igloo_ro_base_t*)NULL) #define igloo_RO_NULL ((igloo_ro_t)(igloo_ro_base_t*)NULL)
#define igloo_RO_IS_NULL(x) (igloo_RO__GETBASE((x)) == NULL) #define igloo_RO_IS_NULL(x) (igloo_RO__GETBASE((x)) == NULL)
#define igloo_RO_TO_TYPE(x,type) (igloo_RO_IS_VALID((x),type) ? ((igloo_ro_t)(x)).subtype__ ## type : NULL) #define igloo_RO_TO_TYPE(x,type) (((igloo_ro_t)igloo_RO_TO_TYPE_raw((x), (igloo_ro__type__ ## type))).subtype__ ## type)
#else #else
#define igloo_RO__GETBASE(x) ((igloo_ro_base_t*)(x)) #define igloo_RO__GETBASE(x) ((igloo_ro_base_t*)(x))
#define igloo_RO_NULL NULL #define igloo_RO_NULL NULL
#define igloo_RO_IS_NULL(x) ((x) == NULL) #define igloo_RO_IS_NULL(x) ((x) == NULL)
#define igloo_RO_TO_TYPE(x,type) (igloo_RO_IS_VALID((x),type) ? (type*)(x) : (type*)NULL) #define igloo_RO_TO_TYPE(x,type) ((type*)igloo_RO_TO_TYPE_raw((x), (igloo_ro__type__ ## type)))
#endif #endif
#define igloo_RO_GET_TYPE(x) (igloo_RO__GETBASE((x)) == NULL ? NULL : igloo_RO__GETBASE((x))->type) #define igloo_RO_GET_TYPE(x) (igloo_RO__GETBASE((x)) == NULL ? NULL : igloo_RO__GETBASE((x))->type)
#define igloo_RO_GET_TYPENAME(x) (igloo_RO_GET_TYPE((x)) == NULL ? NULL : igloo_RO_GET_TYPE((x))->type_name) #define igloo_RO_GET_TYPENAME(x) (igloo_RO_GET_TYPE((x)) == NULL ? NULL : igloo_RO_GET_TYPE((x))->type_name)
#define igloo_RO_IS_VALID(x,type) (!igloo_RO_IS_NULL((x)) && igloo_RO_GET_TYPE((x)) == (igloo_ro__type__ ## type) && igloo_RO__GETBASE((x))->refc) int igloo_RO_IS_VALID_raw(igloo_ro_t object, const igloo_ro_type_t *type);
#define igloo_RO_HAS_TYPE(x,type) (!igloo_RO_IS_NULL((x)) && igloo_RO_GET_TYPE((x)) == (type)) #define igloo_RO_IS_VALID(x,type) igloo_RO_IS_VALID_raw((x), (igloo_ro__type__ ## type))
int igloo_RO_HAS_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type);
#define igloo_RO_HAS_TYPE(x,type) igloo_RO_HAS_TYPE_raw((x), (type))
/* Create a new refobject /* Create a new refobject
* The type argument gives the type for the new object, * The type argument gives the type for the new object,
@ -112,12 +235,12 @@ int igloo_ro_new__return_zero(igloo_ro_t self, const igloo_ro_type_t *type, va_l
* the associated refobject is given by associated. * the associated refobject is given by associated.
*/ */
igloo_ro_t igloo_ro_new__raw(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated); igloo_ro_t igloo_ro_new__raw(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated);
#define igloo_ro_new_raw(type, name, associated) igloo_RO_TO_TYPE(igloo_ro_new__raw((igloo_ro__type__ ## type), (name), (associated)), type) #define igloo_ro_new_raw(type, name, associated) igloo_RO_TO_TYPE(igloo_ro_new__raw((igloo_ro__type__ ## type), (name), (associated)), type)
igloo_ro_t igloo_ro_new__simple(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated, ...); igloo_ro_t igloo_ro_new__simple(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated, ...);
#define igloo_ro_new(type, ...) igloo_RO_TO_TYPE(igloo_ro_new__simple((igloo_ro__type__ ## type), NULL, igloo_RO_NULL, ## __VA_ARGS__), type) #define igloo_ro_new(type, ...) igloo_RO_TO_TYPE(igloo_ro_new__simple((igloo_ro__type__ ## type), NULL, igloo_RO_NULL, ## __VA_ARGS__), type)
#define igloo_ro_new_ext(type, name, associated, ...) igloo_RO_TO_TYPE(igloo_ro_new__simple((igloo_ro__type__ ## type), (name), (associated), ## __VA_ARGS__), type) #define igloo_ro_new_ext(type, name, associated, ...) igloo_RO_TO_TYPE(igloo_ro_new__simple((igloo_ro__type__ ## type), (name), (associated), ## __VA_ARGS__), type)
/* This increases the reference counter of the object */ /* This increases the reference counter of the object */
int igloo_ro_ref(igloo_ro_t self); int igloo_ro_ref(igloo_ro_t self);
@ -134,8 +257,72 @@ int igloo_ro_weak_unref(igloo_ro_t self);
const char * igloo_ro_get_name(igloo_ro_t self); const char * igloo_ro_get_name(igloo_ro_t self);
/* This gets the object's associated object. */ /* This gets the object's associated object. */
igloo_ro_t igloo_ro_get_associated(igloo_ro_t self); igloo_ro_t igloo_ro_get_associated(igloo_ro_t self);
int igloo_ro_set_associated(igloo_ro_t self, igloo_ro_t associated); int igloo_ro_set_associated(igloo_ro_t self, igloo_ro_t associated);
/* Clone the given object returning a copy of it.
*
* This creates a copy of the passed object if possible.
* The mode of copy is selected by the parameters required and allowed.
* Both list flags of modes. Modes listed as required are adhered to.
* However the application may select any additional mode from the allowed
* flags.
*
* If both required and allowed are zero a set of default flags is applied
* as allowed flags.
*
* Parameters:
* self
* The object to copy.
* required
* Flags that must be adhered to when coping.
* allowed
* Flags that are allowed to be used.
* Flags that are listed as required are automatically added the list of allowed flags.
* name, associated
* See igloo_ro_new().
*/
igloo_ro_t igloo_ro_clone(igloo_ro_t self, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated);
/* Make a copy of a object but converts it to another type as well.
*
* This makes makes a copy of the object that is also of a diffrent type.
* If the type is the same as the type of self igloo_ro_clone() is called.
*
* Parameters:
* self
* The object to copy and convert.
* type
* The type to convert to.
* required, allowed
* See igloo_ro_clone().
* name, associated
* See igloo_ro_new().
*/
igloo_ro_t igloo_ro_convert(igloo_ro_t self, const igloo_ro_type_t *type, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated);
/* Convert a object to a string.
* This is used for debugging and presenting to the user.
*
* The resulting string can not be used to recreate the object.
*
* Parameters:
* self
* The object to convert to a string.
* Returns:
* A string as allocated using malloc(3). The caller must call free(3).
*/
char * igloo_ro_stringify(igloo_ro_t self);
/* Compare two objects.
*
* Parameters:
* a, b
* The objects to compare.
* Returns:
* Thre result of the compare. See igloo_ro_cr_t.
*/
igloo_ro_cr_t igloo_ro_compare(igloo_ro_t a, igloo_ro_t b);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -32,7 +32,7 @@ typedef struct igloo_ro_type_tag igloo_ro_type_t;
#define igloo_RO_TYPE(type) type * subtype__ ## type; #define igloo_RO_TYPE(type) type * subtype__ ## type;
#define igloo_RO__CONTROL_VERSION 1 #define igloo_RO__CONTROL_VERSION 1
#define igloo_RO__DEFINE_TYPE(type, suffix, ...) \ #define igloo_RO__DEFINE_TYPE(type, suffix, ...) \
static const igloo_ro_type_t igloo_ro__typedef__ ## type = \ static const igloo_ro_type_t igloo_ro__typedef__ ## type = \
{ \ { \
@ -49,6 +49,10 @@ static const igloo_ro_type_t igloo_ro__typedef__ ## type = \
#define igloo_RO_TYPEDECL_FREE(cb) .type_freecb = (cb) #define igloo_RO_TYPEDECL_FREE(cb) .type_freecb = (cb)
#define igloo_RO_TYPEDECL_NEW(cb) .type_newcb = (cb) #define igloo_RO_TYPEDECL_NEW(cb) .type_newcb = (cb)
#define igloo_RO_TYPEDECL_NEW_NOOP() .type_newcb = igloo_ro_new__return_zero #define igloo_RO_TYPEDECL_NEW_NOOP() .type_newcb = igloo_ro_new__return_zero
#define igloo_RO_TYPEDECL_CLONE(cb) .type_clonecb = (cb)
#define igloo_RO_TYPEDECL_CONVERT(cb) .type_convertcb = (cb)
#define igloo_RO_TYPEDECL_STRINGIFY(cb) .type_stringifycb = (cb)
#define igloo_RO_TYPEDECL_COMPARE(cb) .type_comparecb = (cb)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -31,10 +31,12 @@ struct igloo_buffer_tag {
}; };
static void __free(igloo_ro_t self); static void __free(igloo_ro_t self);
static char * __stringify(igloo_ro_t self);
igloo_RO_PUBLIC_TYPE(igloo_buffer_t, igloo_RO_PUBLIC_TYPE(igloo_buffer_t,
igloo_RO_TYPEDECL_FREE(__free), igloo_RO_TYPEDECL_FREE(__free),
igloo_RO_TYPEDECL_NEW_NOOP() igloo_RO_TYPEDECL_NEW_NOOP(),
igloo_RO_TYPEDECL_STRINGIFY(__stringify)
); );
static void __free(igloo_ro_t self) static void __free(igloo_ro_t self)
@ -139,6 +141,20 @@ int igloo_buffer_get_string(igloo_buffer_t *buffer, const char **string)
return 0; return 0;
} }
static char * __stringify(igloo_ro_t self)
{
igloo_buffer_t *buffer = igloo_RO_TO_TYPE(self, igloo_buffer_t);
const char *ret;
if (!buffer)
return NULL;
if (igloo_buffer_get_string(buffer, &ret) != 0)
return NULL;
return strdup(ret);
}
int igloo_buffer_set_length(igloo_buffer_t *buffer, size_t length) int igloo_buffer_set_length(igloo_buffer_t *buffer, size_t length)
{ {
if (!buffer) if (!buffer)

186
src/ro.c
View File

@ -21,6 +21,7 @@
#include <config.h> #include <config.h>
#endif #endif
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -43,6 +44,29 @@ static inline int check_type(const igloo_ro_type_t *type)
type->type_length >= sizeof(igloo_ro_base_t); type->type_length >= sizeof(igloo_ro_base_t);
} }
static inline int igloo_RO_HAS_TYPE_raw_il(igloo_ro_t object, const igloo_ro_type_t *type)
{
return !igloo_RO_IS_NULL(object) && igloo_RO_GET_TYPE(object) == type;
}
int igloo_RO_HAS_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type)
{
return igloo_RO_HAS_TYPE_raw_il(object, type);
}
static inline int igloo_RO_IS_VALID_raw_li(igloo_ro_t object, const igloo_ro_type_t *type)
{
return igloo_RO_HAS_TYPE_raw_il(object, type) && igloo_RO__GETBASE(object)->refc;
}
int igloo_RO_IS_VALID_raw(igloo_ro_t object, const igloo_ro_type_t *type)
{
return igloo_RO_IS_VALID_raw_li(object, type);
}
igloo_ro_t igloo_RO_TO_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type)
{
return igloo_RO_IS_VALID_raw_li(object, type) ? object : igloo_RO_NULL;
}
igloo_ro_t igloo_ro_new__raw(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated) igloo_ro_t igloo_ro_new__raw(const igloo_ro_type_t *type, const char *name, igloo_ro_t associated)
{ {
igloo_ro_base_t *base; igloo_ro_base_t *base;
@ -286,3 +310,165 @@ int igloo_ro_set_associated(igloo_ro_t self, igloo_ro_t associated)
return 0; return 0;
} }
igloo_ro_t igloo_ro_clone(igloo_ro_t self, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
igloo_ro_t ret = igloo_RO_NULL;
if (!base)
return igloo_RO_NULL;
allowed |= required;
if (!allowed)
allowed = igloo_RO_CF_DEFAULT;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return igloo_RO_NULL;
}
if (base->type->type_clonecb)
ret = base->type->type_clonecb(self, required, allowed, name, associated);
igloo_thread_mutex_unlock(&(base->lock));
return ret;
}
igloo_ro_t igloo_ro_convert(igloo_ro_t self, const igloo_ro_type_t *type, igloo_ro_cf_t required, igloo_ro_cf_t allowed, const char *name, igloo_ro_t associated)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
igloo_ro_t ret = igloo_RO_NULL;
if (!base || !type)
return igloo_RO_NULL;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return igloo_RO_NULL;
}
if (base->type == type) {
igloo_thread_mutex_unlock(&(base->lock));
return igloo_ro_clone(self, required, allowed, name, associated);
}
allowed |= required;
if (!allowed)
allowed = igloo_RO_CF_DEFAULT;
if (base->type->type_convertcb)
ret = base->type->type_convertcb(self, type, required, allowed, name, associated);
if (igloo_RO_IS_NULL(ret))
if (type->type_convertcb)
ret = type->type_convertcb(self, type, required, allowed, name, associated);
igloo_thread_mutex_unlock(&(base->lock));
return ret;
}
char * igloo_ro_stringify(igloo_ro_t self)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
char *ret = NULL;
if (!base)
return strdup("{igloo_RO_NULL}");
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
int len;
char buf;
#define STRINGIFY_FORMAT_WEAK "{%s@%p, weak}", base->type->type_name, base
len = snprintf(&buf, 1, STRINGIFY_FORMAT_WEAK);
if (len > 2) {
/* We add 2 bytes just to make sure no buggy interpretation of \0 inclusion could bite us. */
ret = calloc(1, len + 2);
if (ret) {
snprintf(ret, len + 1, STRINGIFY_FORMAT_WEAK);
}
}
igloo_thread_mutex_unlock(&(base->lock));
return ret;
}
if (base->type->type_stringifycb) {
ret = base->type->type_stringifycb(self);
} else {
int len;
char buf;
#define STRINGIFY_FORMAT_FULL "{%s@%p, strong, name=\"%s\", associated=%p}", base->type->type_name, base, base->name, igloo_RO__GETBASE(base->associated)
len = snprintf(&buf, 1, STRINGIFY_FORMAT_FULL);
if (len > 2) {
/* We add 2 bytes just to make sure no buggy interpretation of \0 inclusion could bite us. */
ret = calloc(1, len + 2);
if (ret) {
snprintf(ret, len + 1, STRINGIFY_FORMAT_FULL);
}
}
}
igloo_thread_mutex_unlock(&(base->lock));
return ret;
}
igloo_ro_cr_t igloo_ro_compare(igloo_ro_t a, igloo_ro_t b)
{
igloo_ro_base_t *base_a = igloo_RO__GETBASE(a);
igloo_ro_base_t *base_b = igloo_RO__GETBASE(b);
igloo_ro_cr_t ret = igloo_RO_CR__ERROR;
if (base_a == base_b)
return igloo_RO_CR_SAME;
if (!base_a || !base_b)
return igloo_RO_CR__ERROR;
igloo_thread_mutex_lock(&(base_a->lock));
igloo_thread_mutex_lock(&(base_b->lock));
if (!base_a->refc || !base_b->refc) {
igloo_thread_mutex_unlock(&(base_b->lock));
igloo_thread_mutex_unlock(&(base_a->lock));
return igloo_RO_CR__ERROR;
}
if (base_a->type->type_comparecb)
ret = base_a->type->type_comparecb(a, b);
if (ret == igloo_RO_CR__ERROR) {
ret = base_b->type->type_comparecb(b, a);
/* we switched arguments here, so we need to reverse the result */
switch (ret) {
case igloo_RO_CR__ERROR:
case igloo_RO_CR_EQUAL:
case igloo_RO_CR_NOTEQUAL:
/* those are the same in both directions */
break;
case igloo_RO_CR_ALESSTHANB:
ret = igloo_RO_CR_AGREATERTHANB;
break;
case igloo_RO_CR_AGREATERTHANB:
ret = igloo_RO_CR_ALESSTHANB;
break;
default:
/* Cases we do not yet handle or that are not a valid result. */
ret = igloo_RO_CR__ERROR;
break;
}
}
igloo_thread_mutex_unlock(&(base_b->lock));
igloo_thread_mutex_unlock(&(base_a->lock));
return ret;
}