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