utils.h: Some utility functions and macros
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
ab12467c3f
commit
3f4c05720d
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
static inline const char *
|
||||
skip_space_const(const char *src) {
|
||||
if (!src)
|
||||
return NULL;
|
||||
while (*src && isspace(*src))
|
||||
src++;
|
||||
return src;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
skip_space_mut(char *src) {
|
||||
if (!src)
|
||||
return NULL;
|
||||
while (*src && isspace(*src))
|
||||
src++;
|
||||
return src;
|
||||
}
|
||||
|
||||
#define skip_space(x) _Generic((x), \
|
||||
char *: skip_space_mut, \
|
||||
const char *: skip_space_const \
|
||||
)(x)
|
||||
|
||||
/// RC_TYPE generates a reference counted type from `type`
|
||||
///
|
||||
/// parameters:
|
||||
/// name = the generated type will be called `name`_t.
|
||||
/// ctor = the constructor of `type`, will be called when
|
||||
/// a value of `type` is created. should take one
|
||||
/// argument of `type *`.
|
||||
/// dtor = the destructor. will be called when all reference
|
||||
/// is gone. has same signature as ctor
|
||||
/// Q = function qualifier. this is the qualifier that
|
||||
/// will be put before generated functions
|
||||
//
|
||||
/// functions generated:
|
||||
/// `name`_new: create a new reference counted object of `type`
|
||||
/// `name`_ref: increment the reference counter, return a
|
||||
/// reference to the object
|
||||
/// `name`_unref: decrement the reference counter. take a `type **`
|
||||
/// because it needs to nullify the reference.
|
||||
#define RC_TYPE(type, name, ctor, dtor, Q) \
|
||||
typedef struct { \
|
||||
type inner; \
|
||||
int ref_count; \
|
||||
} name##_internal_t; \
|
||||
typedef type name##_t; \
|
||||
Q type *name##_new(void) { \
|
||||
name##_internal_t *ret = malloc(sizeof(name##_internal_t)); \
|
||||
ctor((type *)ret); \
|
||||
ret->ref_count = 1; \
|
||||
return (type *)ret; \
|
||||
} \
|
||||
Q type *name##_ref(type *a) { \
|
||||
__auto_type b = (name##_internal_t *)a; \
|
||||
b->ref_count++; \
|
||||
return a; \
|
||||
} \
|
||||
Q void name##_unref(type **a) { \
|
||||
__auto_type b = (name##_internal_t *)*a; \
|
||||
if (!b) \
|
||||
return; \
|
||||
b->ref_count--; \
|
||||
if (!b->ref_count) {\
|
||||
dtor((type *)b); \
|
||||
free(b); \
|
||||
} \
|
||||
*a = NULL; \
|
||||
}
|
||||
|
||||
/// Generate prototypes for functions generated by RC_TYPE
|
||||
#define RC_TYPE_PROTO(type, name) \
|
||||
typedef type name##_t; \
|
||||
type *name##_new(void); \
|
||||
void name##_ref(type *a); \
|
||||
void name##_unref(type **a);
|
Loading…
Reference in New Issue