#ifndef GU_SEQ_H_ #define GU_SEQ_H_ #include #include typedef struct GuBuf GuBuf; typedef GuOpaque() GuSeq; GuSeq gu_empty_seq(); GuSeq gu_make_seq(size_t elem_size, size_t len, GuPool* pool); #define gu_new_seq(T, N, POOL) \ gu_make_seq(sizeof(T), (N), (POOL)) static inline size_t gu_seq_length(GuSeq seq) { GuWord w = seq.w_; size_t tag = gu_tagged_tag(w); if (tag == 0) { GuWord* p = gu_tagged_ptr(w); return (size_t) (p[-1] >> 1); } return tag; } static inline void* gu_seq_data(GuSeq seq) { GuWord w = seq.w_; int tag = gu_tagged_tag(w); void* ptr = gu_tagged_ptr(w); if (tag == 0) { GuWord* p = ptr; if (p[-1] & 0x1) { return *(uint8_t**) ptr; } } return ptr; } static inline bool gu_seq_is_null(GuSeq seq) { return (gu_tagged_ptr(seq.w_)) == NULL; } #define gu_seq_index(SEQ, T, I) \ (&((T*)gu_seq_data(SEQ))[I]) #define gu_seq_get(SEQ, T, I) \ (*gu_seq_index(SEQ, T, I)) #define gu_seq_set(SEQ, T, I, V) \ GU_BEGIN \ (*gu_seq_index(SEQ, T, I) = (V)); \ GU_END GuBuf* gu_seq_buf(GuSeq seq); GuSeq gu_buf_seq(GuBuf* buf); GuBuf* gu_make_buf(size_t elem_size, GuPool* pool); #define gu_new_buf(T, POOL) \ gu_make_buf(sizeof(T), (POOL)) size_t gu_buf_length(GuBuf* buf); size_t gu_buf_avail(GuBuf* buf); void* gu_buf_data(GuBuf* buf); #define gu_buf_index(BUF, T, I) \ (&((T*)gu_buf_data(BUF))[I]) #define gu_buf_get(BUF, T, I) \ (*gu_buf_index(BUF, T, I)) #define gu_buf_set(BUF, T, I) \ GU_BEGIN \ (*gu_buf_index(BUF, T, I) = (V)); \ GU_END void gu_buf_push_n(GuBuf* buf, const void* elems, size_t n_elems); void* gu_buf_extend_n(GuBuf* buf, size_t n_elems); void* gu_buf_extend(GuBuf* buf); #define gu_buf_push(BUF, T, VAL) \ GU_BEGIN \ ((*(T*)gu_buf_extend(BUF)) = (VAL)); \ GU_END void gu_buf_pop_n(GuBuf* buf, size_t n_elems, void* data_out); const void* gu_buf_trim_n(GuBuf* buf, size_t n_elems); const void* gu_buf_trim(GuBuf* buf); #define gu_buf_pop(BUF, T) \ (*(T*)gu_buf_trim(BUF)) void gu_seq_resize_tail(GuSeq seq, ptrdiff_t change); // Using a buffer as a heap void gu_buf_heap_push(GuBuf *buf, GuOrder *order, void *value); void gu_buf_heap_pop(GuBuf *buf, GuOrder *order, void* data_out); void gu_buf_heap_replace(GuBuf *buf, GuOrder *order, void *value, void *data_out); void gu_buf_heapify(GuBuf *buf, GuOrder *order); #if 0 void gu_buf_resize_head(GuBuf* buf, ptrdiff_t change); void gu_buf_unshift(GuBuf* buf, const void* data, size_t size); void gu_buf_shift(GuBuf* buf, size_t size, void* data_out); #endif GuSeq gu_buf_freeze(GuBuf* buf, GuPool* pool); extern const GuSeq gu_null_seq; #define GU_NULL_SEQ { .w_ = (GuWord)(void*)NULL } typedef GuSeq GuChars; typedef GuSeq GuBytes; typedef GuBuf GuCharBuf; typedef GuBuf GuByteBuf; char* gu_chars_str(GuChars chars, GuPool* pool); #endif // GU_SEQ_H_ #if defined(GU_OUT_H_) && !defined(GU_SEQ_H_OUT_) #define GU_SEQ_H_OUT_ GuOut* gu_buf_out(GuBuf* buf, GuPool* pool); #endif #if defined(GU_TYPE_H_) && !defined(GU_SEQ_H_TYPE_) #define GU_SEQ_H_TYPE_ extern GU_DECLARE_KIND(GuSeq); extern GU_DECLARE_KIND(GuBuf); struct GuSeqType { GuType_GuOpaque opaque_base; GuType* elem_type; }; typedef const struct GuSeqType GuSeqType, GuType_GuSeq; #define GU_TYPE_INIT_GuSeq(k_, t_, elem_type_) { \ .opaque_base = GU_TYPE_INIT_GuOpaque(k_, t_, _), \ .elem_type = elem_type_, \ } typedef struct GuBufType GuBufType, GuType_GuBuf; struct GuBufType { GuType_abstract abstract_base; GuType* elem_type; }; #define GU_TYPE_INIT_GuBuf(KIND, BUF_T, ELEM_T) { \ .abstract_base = GU_TYPE_INIT_abstract(KIND, BUF_T, _), \ .elem_type = ELEM_T \ } extern GU_DECLARE_TYPE(GuChars, GuSeq); extern GU_DECLARE_TYPE(GuBytes, GuSeq); #endif