hop-2012/sexp.h

100 lines
2.8 KiB
C

#ifndef cmsg_sexp_h
#define cmsg_sexp_h
typedef struct sexp_data_t_ {
refcount_t refcount;
cmsg_bytes_t data;
} sexp_data_t;
typedef enum sexp_type_t_ {
SEXP_BYTES,
SEXP_SLICE,
SEXP_DISPLAY_HINT,
SEXP_PAIR
} sexp_type_t;
typedef struct sexp_t_ {
refcount_t refcount;
sexp_type_t kind;
union {
cmsg_bytes_t bytes;
struct {
sexp_data_t *data;
size_t offset;
size_t length;
} slice;
struct {
struct sexp_t_ *head;
struct sexp_t_ *tail;
} pair; /* and display-hint */
} data;
} sexp_t;
extern void sexp_data_destructor(sexp_data_t *data);
extern void sexp_destructor(sexp_t *x);
extern sexp_data_t *sexp_data_copy(cmsg_bytes_t body, size_t offset, size_t length);
extern sexp_data_t *sexp_data_alias(cmsg_bytes_t body);
extern sexp_t *sexp_bytes(cmsg_bytes_t bytes);
extern sexp_t *sexp_slice(sexp_data_t *data, size_t offset, size_t length);
extern sexp_t *sexp_display_hint(sexp_t *hint, sexp_t *body);
extern sexp_t *sexp_cons(sexp_t *head, sexp_t *tail);
#define sexp_simple_stringp(x) ({ \
sexp_t *__x = (x); \
(__x != NULL) && ((__x->kind == SEXP_BYTES) || (__x->kind == SEXP_SLICE)); \
})
#define sexp_stringp(x) ({ \
sexp_t *__x = (x); \
sexp_simple_stringp(__x) || ((__x != NULL) && (__x->kind == SEXP_DISPLAY_HINT)); \
}
#define sexp_pairp(x) ({ \
sexp_t *__x = (x); \
(__x != NULL) && (__x->kind == SEXP_PAIR); \
})
extern cmsg_bytes_t sexp_data(sexp_t *x);
#define sexp_head(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_PAIR); __x->data.pair.head;})
#define sexp_tail(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_PAIR); __x->data.pair.tail;})
#define sexp_hint(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_DISPLAY_HINT); __x->data.pair.head;})
#define sexp_body(x) ({sexp_t *__x = (x); assert(__x->kind == SEXP_DISPLAY_HINT); __x->data.pair.tail;})
#define sexp_setter_(x,y,fieldname) \
({ \
sexp_t *__x = (x); \
sexp_t *__y = (y); \
sexp_t *__old; \
assert(__x->kind == SEXP_PAIR); \
INCREF(__y); \
__old = __x->data.pair.fieldname; \
__x->data.pair.fieldname = __y; \
DECREF(__old, sexp_destructor); \
__x; \
})
#define sexp_sethead(x,y) sexp_setter_(x,y,head)
#define sexp_settail(x,y) sexp_setter_(x,y,tail)
#define sexp_push(stackvar,val) \
({ \
sexp_t *__oldstack = stackvar; \
stackvar = INCREF(sexp_cons((val), stackvar)); \
DECREF(__oldstack, sexp_destructor); \
stackvar; \
})
#define sexp_pop(stackvar) \
({ \
sexp_t *__nextstack = INCREF(sexp_tail(stackvar)); \
sexp_t *__val = INCREF(sexp_head(stackvar)); \
DECREF(stackvar, sexp_destructor); \
stackvar = __nextstack; \
UNGRAB(__val); \
__val; \
})
#endif