102 lines
2.8 KiB
C
102 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 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);
|
|
|
|
#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
|