133 lines
3.3 KiB
C
133 lines
3.3 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 release_sexp_cache(void);
|
|
|
|
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);
|
|
|
|
static inline int sexp_simple_stringp(sexp_t *x) {
|
|
return (x != NULL) && ((x->kind == SEXP_BYTES) || (x->kind == SEXP_SLICE));
|
|
}
|
|
|
|
static inline int sexp_stringp(sexp_t *x) {
|
|
return sexp_simple_stringp(x) || ((x != NULL) && (x->kind == SEXP_DISPLAY_HINT));
|
|
}
|
|
|
|
static inline int sexp_pairp(sexp_t *x) {
|
|
return (x != NULL) && (x->kind == SEXP_PAIR);
|
|
}
|
|
|
|
extern cmsg_bytes_t sexp_data(sexp_t *x);
|
|
|
|
static inline sexp_t *sexp_head(sexp_t *x) {
|
|
assert(x->kind == SEXP_PAIR);
|
|
return x->data.pair.head;
|
|
}
|
|
|
|
static inline sexp_t *sexp_tail(sexp_t *x) {
|
|
assert(x->kind == SEXP_PAIR);
|
|
return x->data.pair.tail;
|
|
}
|
|
|
|
static inline sexp_t *sexp_hint(sexp_t *x) {
|
|
assert(x->kind == SEXP_DISPLAY_HINT);
|
|
return x->data.pair.head;
|
|
}
|
|
|
|
static inline sexp_t *sexp_body(sexp_t *x) {
|
|
assert(x->kind == SEXP_DISPLAY_HINT);
|
|
return x->data.pair.tail;
|
|
}
|
|
|
|
#define sexp_setter_(settername,fieldname) \
|
|
static inline sexp_t *settername(sexp_t *x, sexp_t *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); \
|
|
return x; \
|
|
}
|
|
|
|
sexp_setter_(sexp_sethead, head)
|
|
sexp_setter_(sexp_settail, tail)
|
|
|
|
static inline sexp_t *sexp_push(sexp_t *oldstack, sexp_t *val) {
|
|
sexp_t *newstack = INCREF(sexp_cons(val, oldstack));
|
|
DECREF(oldstack, sexp_destructor);
|
|
return newstack;
|
|
}
|
|
|
|
static inline sexp_t *sexp_pop(sexp_t *oldstack, sexp_t **valp) {
|
|
sexp_t *nextstack = INCREF(sexp_tail(oldstack));
|
|
sexp_t *val = INCREF(sexp_head(oldstack));
|
|
DECREF(oldstack, sexp_destructor);
|
|
UNGRAB(val);
|
|
if (valp != NULL) {
|
|
*valp = val;
|
|
}
|
|
return nextstack;
|
|
}
|
|
|
|
static inline sexp_t *sexp_listtail(sexp_t *list, size_t dropcount) {
|
|
while (dropcount) {
|
|
list = sexp_tail(list);
|
|
dropcount--;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
static inline sexp_t *sexp_listref(sexp_t *list, size_t index) {
|
|
return sexp_head(sexp_listtail(list, index));
|
|
}
|
|
|
|
extern sexp_t *sexp_assoc(sexp_t *list, cmsg_bytes_t key);
|
|
extern size_t sexp_length(sexp_t *list);
|
|
|
|
extern sexp_t *sexp_new_queue(void);
|
|
extern int sexp_queue_emptyp(sexp_t *q);
|
|
extern void sexp_queue_pushback(sexp_t *q, sexp_t *x);
|
|
extern void sexp_enqueue(sexp_t *q, sexp_t *x);
|
|
extern sexp_t *sexp_dequeue(sexp_t *q);
|
|
|
|
#endif
|