mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-24 20:12:51 -06:00
a major refactoring in the C runtime. GuList is now removed and replaced with GuSeq. The GuSeq/GuBuf API is simplified
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 University of Helsinki.
|
||||
*
|
||||
* This file is part of libgu.
|
||||
*
|
||||
* Libgu is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Libgu is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libgu. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gu/list.h>
|
||||
#include <gu/assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static const int gu_list_empty = 0;
|
||||
|
||||
void* gu_list_alloc(GuPool* pool, size_t base_size, size_t elem_size,
|
||||
int n_elems, size_t alignment)
|
||||
{
|
||||
gu_assert(n_elems >= 0);
|
||||
if (n_elems == 0) {
|
||||
return (void*) &gu_list_empty;
|
||||
}
|
||||
// XXX: use gu_flex_size, use offset of elems
|
||||
void* p = gu_malloc_aligned(pool, base_size + elem_size * n_elems,
|
||||
alignment);
|
||||
*(int*) p = n_elems;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
GU_DEFINE_KIND(GuList, abstract);
|
||||
|
||||
// GU_DEFINE_TYPE(GuStrs, GuList, gu_type(GuStr));
|
||||
// GU_DEFINE_TYPE(GuStrsP, pointer, gu_type(GuStrs));
|
||||
|
||||
void*
|
||||
gu_list_type_alloc(GuListType* ltype, int n_elems, GuPool* pool)
|
||||
{
|
||||
return gu_list_alloc(pool, ltype->size,
|
||||
gu_type_size(ltype->elem_type),
|
||||
n_elems, ltype->align);
|
||||
}
|
||||
|
||||
void*
|
||||
gu_list_type_index(GuListType* ltype, void* list, int i)
|
||||
{
|
||||
uint8_t* p = list;
|
||||
return &p[ltype->elems_offset + i * gu_type_size(ltype->elem_type)];
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 University of Helsinki.
|
||||
*
|
||||
* This file is part of libgu.
|
||||
*
|
||||
* Libgu is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Libgu is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libgu. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Lists.
|
||||
*/
|
||||
|
||||
#ifndef GU_LIST_H_
|
||||
#define GU_LIST_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
|
||||
|
||||
#define GuList(t) \
|
||||
struct { \
|
||||
const int len; \
|
||||
t elems[]; \
|
||||
}
|
||||
|
||||
void* gu_list_alloc(GuPool* pool, size_t base_size, size_t elem_size,
|
||||
int n_elems, size_t alignment);
|
||||
|
||||
#define gu_new_list(t, pool, n) \
|
||||
((t*) gu_list_alloc(pool, \
|
||||
sizeof(t), \
|
||||
sizeof(((t*)NULL)->elems[0]), \
|
||||
(n), \
|
||||
gu_flex_alignof(t)))
|
||||
|
||||
static inline int
|
||||
gu_list_length(const void* list)
|
||||
{
|
||||
return *(const int*) list;
|
||||
}
|
||||
|
||||
#define gu_list_elems(lst) \
|
||||
((lst)->elems)
|
||||
|
||||
#define gu_list_index(lst, i) \
|
||||
(gu_list_elems(lst)[i])
|
||||
|
||||
typedef GuList(void*) GuPointers;
|
||||
//typedef GuList(uint8_t) GuBytes;
|
||||
|
||||
typedef GuList(int) GuInts;
|
||||
|
||||
|
||||
#define GuListN(t_, len_) \
|
||||
struct { \
|
||||
int len; \
|
||||
t elems[len_]; \
|
||||
}
|
||||
|
||||
#define gu_list_(qual_, t_, ...) \
|
||||
((qual_ GuList(t_) *) \
|
||||
((qual_ GuListN(t_, (sizeof((t_[]){__VA_ARGS__}) / sizeof(t_)))[]){ \
|
||||
__VA_ARGS__ \
|
||||
}))
|
||||
|
||||
#define gu_list(t_, ...) \
|
||||
gu_list_(, t_, __VA_ARGS__)
|
||||
|
||||
#define gu_clist(t_, ...) \
|
||||
gu_list_(const, t_, __VA_ARGS__)
|
||||
|
||||
#define GuSList(t) \
|
||||
const struct { \
|
||||
int len; \
|
||||
t* elems; \
|
||||
}
|
||||
|
||||
#define GU_SLIST_0 { .len = 0, .elems = NULL }
|
||||
|
||||
#define GU_SLIST(t, ...) \
|
||||
{ \
|
||||
.len = GU_ARRAY_LEN(t,GU_ID({__VA_ARGS__})), \
|
||||
.elems = ((t[]){__VA_ARGS__}) \
|
||||
}
|
||||
|
||||
|
||||
#include <gu/type.h>
|
||||
|
||||
//
|
||||
// list
|
||||
//
|
||||
|
||||
typedef const struct GuListType GuListType, GuType_GuList;
|
||||
|
||||
struct GuListType {
|
||||
GuType_abstract abstract_base;
|
||||
size_t size;
|
||||
size_t align;
|
||||
GuType* elem_type;
|
||||
ptrdiff_t elems_offset;
|
||||
};
|
||||
|
||||
#define GU_TYPE_INIT_GuList(k_, t_, elem_type_) { \
|
||||
.abstract_base = GU_TYPE_INIT_abstract(k_, t_, _), \
|
||||
.size = sizeof(t_), \
|
||||
.align = gu_alignof(t_), \
|
||||
.elem_type = elem_type_, \
|
||||
.elems_offset = offsetof(t_, elems) \
|
||||
}
|
||||
|
||||
extern GU_DECLARE_KIND(GuList);
|
||||
|
||||
void*
|
||||
gu_list_type_alloc(GuListType* ltype, int n_elems, GuPool* pool);
|
||||
|
||||
void*
|
||||
gu_list_type_index(GuListType* ltype, void* list, int i);
|
||||
|
||||
#include <gu/str.h>
|
||||
|
||||
|
||||
typedef GuList(GuStr) GuStrs;
|
||||
typedef GuStrs* GuStrsP;
|
||||
|
||||
extern GU_DECLARE_TYPE(GuStrs, GuList);
|
||||
extern GU_DECLARE_TYPE(GuStrsP, pointer);
|
||||
|
||||
|
||||
#endif // GU_LIST_H_
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <gu/seq.h>
|
||||
#include <gu/out.h>
|
||||
#include <gu/utf8.h>
|
||||
#include <gu/str.h>
|
||||
|
||||
static bool
|
||||
gu_out_is_buffering(GuOut* out)
|
||||
|
||||
@@ -1,35 +1,27 @@
|
||||
#include <gu/out.h>
|
||||
#include <gu/seq.h>
|
||||
#include <gu/fun.h>
|
||||
#include <gu/str.h>
|
||||
#include <gu/assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct GuSeq {
|
||||
size_t len;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
struct GuBuf {
|
||||
uint8_t* data;
|
||||
GuSeq* seq;
|
||||
size_t elem_size;
|
||||
size_t avail_len;
|
||||
GuFinalizer fin;
|
||||
};
|
||||
|
||||
GuBuf*
|
||||
gu_seq_buf(GuSeq seq)
|
||||
{
|
||||
gu_require(gu_tagged_tag(seq.w_) == 0);
|
||||
return gu_word_ptr(seq.w_);
|
||||
}
|
||||
|
||||
GuSeq
|
||||
gu_buf_seq(GuBuf* buf)
|
||||
{
|
||||
return (GuSeq) { .w_ = gu_ptr_word(buf) };
|
||||
}
|
||||
|
||||
size_t
|
||||
gu_buf_length(GuBuf* dyn)
|
||||
gu_buf_length(GuBuf* buf)
|
||||
{
|
||||
return (size_t)(((GuWord*)(void*)dyn)[-1] >> 1);
|
||||
return buf->seq->len;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -38,58 +30,82 @@ gu_buf_avail(GuBuf* buf)
|
||||
return buf->avail_len;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gu_buf_set_length(GuBuf* dyn, size_t new_len)
|
||||
{
|
||||
((GuWord*)(void*)dyn)[-1] = ((GuWord) new_len) << 1 | 0x1;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_buf_fini(GuFinalizer* fin)
|
||||
{
|
||||
GuBuf* buf = gu_container(fin, GuBuf, fin);
|
||||
gu_mem_buf_free(buf->data);
|
||||
if (buf->avail_len > 0)
|
||||
gu_mem_buf_free(buf->seq);
|
||||
}
|
||||
|
||||
GuBuf*
|
||||
gu_make_buf(size_t elem_size, GuPool* pool)
|
||||
{
|
||||
GuBuf* buf = gu_new_prefixed(unsigned, GuBuf, pool);
|
||||
gu_buf_set_length(buf, 0);
|
||||
GuBuf* buf = gu_new(GuBuf, pool);
|
||||
buf->seq = gu_empty_seq();
|
||||
buf->elem_size = elem_size;
|
||||
buf->data = NULL;
|
||||
buf->avail_len = 0;
|
||||
buf->fin.fn = gu_buf_fini;
|
||||
gu_pool_finally(pool, &buf->fin);
|
||||
gu_buf_set_length(buf, 0);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const GuWord gu_empty_seq_[2] = {0, 0};
|
||||
|
||||
GuSeq
|
||||
gu_empty_seq() {
|
||||
return (GuSeq) { gu_tagged((void*)&gu_empty_seq_[1], 0) };
|
||||
size_t
|
||||
gu_seq_length(GuSeq* seq)
|
||||
{
|
||||
return seq->len;
|
||||
}
|
||||
|
||||
GuSeq
|
||||
void*
|
||||
gu_seq_data(GuSeq* seq)
|
||||
{
|
||||
return seq->data;
|
||||
}
|
||||
|
||||
static GuSeq gu_empty_seq_ = {0};
|
||||
|
||||
GuSeq*
|
||||
gu_empty_seq() {
|
||||
return &gu_empty_seq_;
|
||||
}
|
||||
|
||||
GuSeq*
|
||||
gu_make_seq(size_t elem_size, size_t length, GuPool* pool)
|
||||
{
|
||||
size_t size = elem_size * length;
|
||||
if (0 < length && length <= GU_TAG_MAX) {
|
||||
void* buf = gu_malloc(pool, size);
|
||||
return (GuSeq) { gu_tagged(buf, length) };
|
||||
} else if (size == 0) {
|
||||
GuSeq* seq = gu_malloc(pool, sizeof(GuSeq) + elem_size * length);
|
||||
seq->len = length;
|
||||
return seq;
|
||||
}
|
||||
|
||||
GuSeq*
|
||||
gu_alloc_seq_(size_t elem_size, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return gu_empty_seq();
|
||||
} else {
|
||||
void* buf = gu_malloc_prefixed(pool,
|
||||
gu_alignof(GuWord),
|
||||
sizeof(GuWord),
|
||||
0, size);
|
||||
((GuWord*) buf)[-1] = ((GuWord) length) << 1;
|
||||
return (GuSeq) { gu_tagged(buf, 0) };
|
||||
}
|
||||
|
||||
size_t real_size;
|
||||
GuSeq* seq = gu_mem_buf_alloc(sizeof(GuSeq) + elem_size * length, &real_size);
|
||||
seq->len = (real_size - sizeof(GuSeq)) / elem_size;
|
||||
return seq;
|
||||
}
|
||||
|
||||
GuSeq*
|
||||
gu_realloc_seq_(GuSeq* seq, size_t elem_size, size_t length)
|
||||
{
|
||||
size_t real_size;
|
||||
GuSeq* new_seq = (seq == NULL || seq == gu_empty_seq()) ?
|
||||
gu_mem_buf_alloc(sizeof(GuSeq) + elem_size * length, &real_size) :
|
||||
gu_mem_buf_realloc(seq, sizeof(GuSeq) + elem_size * length, &real_size);
|
||||
new_seq->len = (real_size - sizeof(GuSeq)) / elem_size;
|
||||
return new_seq;
|
||||
}
|
||||
|
||||
void
|
||||
gu_seq_free(GuSeq* seq)
|
||||
{
|
||||
if (seq == NULL || seq == gu_empty_seq())
|
||||
return;
|
||||
gu_mem_buf_free(seq);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -98,17 +114,30 @@ gu_buf_require(GuBuf* buf, size_t req_len)
|
||||
if (req_len <= buf->avail_len) {
|
||||
return;
|
||||
}
|
||||
size_t req_size = buf->elem_size * req_len;
|
||||
|
||||
size_t req_size = sizeof(GuSeq) + buf->elem_size * req_len;
|
||||
size_t real_size;
|
||||
buf->data = gu_mem_buf_realloc(buf->data, req_size,
|
||||
&real_size);
|
||||
buf->avail_len = real_size / buf->elem_size;
|
||||
|
||||
if (buf->seq == NULL || buf->seq == gu_empty_seq()) {
|
||||
buf->seq = gu_mem_buf_alloc(req_size, &real_size);
|
||||
buf->seq->len = 0;
|
||||
} else {
|
||||
buf->seq = gu_mem_buf_realloc(buf->seq, req_size, &real_size);
|
||||
}
|
||||
|
||||
buf->avail_len = (real_size - sizeof(GuSeq)) / buf->elem_size;
|
||||
}
|
||||
|
||||
void*
|
||||
gu_buf_data(GuBuf* buf)
|
||||
{
|
||||
return buf->data;
|
||||
return &buf->seq->data;
|
||||
}
|
||||
|
||||
GuSeq*
|
||||
gu_buf_data_seq(GuBuf* buf)
|
||||
{
|
||||
return buf->seq;
|
||||
}
|
||||
|
||||
void*
|
||||
@@ -117,8 +146,8 @@ gu_buf_extend_n(GuBuf* buf, size_t n_elems)
|
||||
size_t len = gu_buf_length(buf);
|
||||
size_t new_len = len + n_elems;
|
||||
gu_buf_require(buf, new_len);
|
||||
gu_buf_set_length(buf, new_len);
|
||||
return &buf->data[buf->elem_size * len];
|
||||
buf->seq->len = new_len;
|
||||
return &buf->seq->data[buf->elem_size * len];
|
||||
}
|
||||
|
||||
void*
|
||||
@@ -130,7 +159,6 @@ gu_buf_extend(GuBuf* buf)
|
||||
void
|
||||
gu_buf_push_n(GuBuf* buf, const void* data, size_t n_elems)
|
||||
{
|
||||
|
||||
void* p = gu_buf_extend_n(buf, n_elems);
|
||||
memcpy(p, data, buf->elem_size * n_elems);
|
||||
}
|
||||
@@ -140,8 +168,8 @@ gu_buf_trim_n(GuBuf* buf, size_t n_elems)
|
||||
{
|
||||
gu_require(n_elems <= gu_buf_length(buf));
|
||||
size_t new_len = gu_buf_length(buf) - n_elems;
|
||||
gu_buf_set_length(buf, new_len);
|
||||
return &buf->data[buf->elem_size * new_len];
|
||||
buf->seq->len = new_len;
|
||||
return &buf->seq->data[buf->elem_size * new_len];
|
||||
}
|
||||
|
||||
const void*
|
||||
@@ -153,7 +181,7 @@ gu_buf_trim(GuBuf* buf)
|
||||
void
|
||||
gu_buf_flush(GuBuf* buf)
|
||||
{
|
||||
gu_buf_set_length(buf, 0);
|
||||
buf->seq->len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -163,11 +191,11 @@ gu_buf_pop_n(GuBuf* buf, size_t n_elems, void* data_out)
|
||||
memcpy(data_out, p, buf->elem_size * n_elems);
|
||||
}
|
||||
|
||||
GuSeq
|
||||
GuSeq*
|
||||
gu_buf_freeze(GuBuf* buf, GuPool* pool)
|
||||
{
|
||||
size_t len = gu_buf_length(buf);
|
||||
GuSeq seq = gu_make_seq(buf->elem_size, len, pool);
|
||||
GuSeq* seq = gu_make_seq(buf->elem_size, len, pool);
|
||||
void* bufdata = gu_buf_data(buf);
|
||||
void* seqdata = gu_seq_data(seq);
|
||||
memcpy(seqdata, bufdata, buf->elem_size * len);
|
||||
@@ -182,32 +210,32 @@ gu_quick_sort(GuBuf *buf, GuOrder *order, int left, int right)
|
||||
|
||||
void* pivot = alloca(buf->elem_size);
|
||||
memcpy(pivot,
|
||||
&buf->data[buf->elem_size * left],
|
||||
&buf->seq->data[buf->elem_size * left],
|
||||
buf->elem_size);
|
||||
while (left < right) {
|
||||
|
||||
while ((order->compare(order, &buf->data[buf->elem_size * right], pivot) >= 0) && (left < right))
|
||||
while ((order->compare(order, &buf->seq->data[buf->elem_size * right], pivot) >= 0) && (left < right))
|
||||
right--;
|
||||
|
||||
if (left != right) {
|
||||
memcpy(&buf->data[buf->elem_size * left],
|
||||
&buf->data[buf->elem_size * right],
|
||||
memcpy(&buf->seq->data[buf->elem_size * left],
|
||||
&buf->seq->data[buf->elem_size * right],
|
||||
buf->elem_size);
|
||||
left++;
|
||||
}
|
||||
|
||||
while ((order->compare(order, &buf->data[buf->elem_size * left], pivot) <= 0) && (left < right))
|
||||
while ((order->compare(order, &buf->seq->data[buf->elem_size * left], pivot) <= 0) && (left < right))
|
||||
left++;
|
||||
|
||||
if (left != right) {
|
||||
memcpy(&buf->data[buf->elem_size * right],
|
||||
&buf->data[buf->elem_size * left],
|
||||
memcpy(&buf->seq->data[buf->elem_size * right],
|
||||
&buf->seq->data[buf->elem_size * left],
|
||||
buf->elem_size);
|
||||
right--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&buf->data[buf->elem_size * left],
|
||||
memcpy(&buf->seq->data[buf->elem_size * left],
|
||||
pivot,
|
||||
buf->elem_size);
|
||||
int index = left;
|
||||
@@ -235,7 +263,7 @@ gu_buf_binsearch(GuBuf *buf, GuOrder *order, void *value)
|
||||
|
||||
while (i <= j) {
|
||||
size_t k = (i+j) / 2;
|
||||
int cmp = order->compare(order, value, &buf->data[buf->elem_size * k]);
|
||||
int cmp = order->compare(order, value, &buf->seq->data[buf->elem_size * k]);
|
||||
|
||||
if (cmp < 0) {
|
||||
j = k-1;
|
||||
@@ -243,7 +271,7 @@ gu_buf_binsearch(GuBuf *buf, GuOrder *order, void *value)
|
||||
i = k+1;
|
||||
} else {
|
||||
memcpy(value,
|
||||
&buf->data[buf->elem_size * k],
|
||||
&buf->seq->data[buf->elem_size * k],
|
||||
buf->elem_size);
|
||||
return true;
|
||||
}
|
||||
@@ -258,16 +286,16 @@ gu_heap_siftdown(GuBuf *buf, GuOrder *order,
|
||||
{
|
||||
while (pos > startpos) {
|
||||
int parentpos = (pos - 1) >> 1;
|
||||
void *parent = &buf->data[buf->elem_size * parentpos];
|
||||
void *parent = &buf->seq->data[buf->elem_size * parentpos];
|
||||
|
||||
if (order->compare(order, value, parent) >= 0)
|
||||
break;
|
||||
|
||||
memcpy(&buf->data[buf->elem_size * pos], parent, buf->elem_size);
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos], parent, buf->elem_size);
|
||||
pos = parentpos;
|
||||
}
|
||||
|
||||
memcpy(&buf->data[buf->elem_size * pos], value, buf->elem_size);
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos], value, buf->elem_size);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -282,13 +310,13 @@ gu_heap_siftup(GuBuf *buf, GuOrder *order,
|
||||
int rightpos = childpos + 1;
|
||||
if (rightpos < endpos &&
|
||||
order->compare(order,
|
||||
&buf->data[buf->elem_size * childpos],
|
||||
&buf->data[buf->elem_size * rightpos]) >= 0) {
|
||||
&buf->seq->data[buf->elem_size * childpos],
|
||||
&buf->seq->data[buf->elem_size * rightpos]) >= 0) {
|
||||
childpos = rightpos;
|
||||
}
|
||||
|
||||
memcpy(&buf->data[buf->elem_size * pos],
|
||||
&buf->data[buf->elem_size * childpos], buf->elem_size);
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos],
|
||||
&buf->seq->data[buf->elem_size * childpos], buf->elem_size);
|
||||
pos = childpos;
|
||||
childpos = 2*pos + 1;
|
||||
}
|
||||
@@ -309,7 +337,7 @@ gu_buf_heap_pop(GuBuf *buf, GuOrder *order, void* data_out)
|
||||
const void* last = gu_buf_trim(buf); // raises an error if empty
|
||||
|
||||
if (gu_buf_length(buf) > 0) {
|
||||
memcpy(data_out, buf->data, buf->elem_size);
|
||||
memcpy(data_out, buf->seq->data, buf->elem_size);
|
||||
gu_heap_siftup(buf, order, last, 0);
|
||||
} else {
|
||||
memcpy(data_out, last, buf->elem_size);
|
||||
@@ -321,7 +349,7 @@ gu_buf_heap_replace(GuBuf *buf, GuOrder *order, void *value, void *data_out)
|
||||
{
|
||||
gu_require(gu_buf_length(buf) > 0);
|
||||
|
||||
memcpy(data_out, buf->data, buf->elem_size);
|
||||
memcpy(data_out, buf->seq->data, buf->elem_size);
|
||||
gu_heap_siftup(buf, order, value, 0);
|
||||
}
|
||||
|
||||
@@ -332,7 +360,7 @@ gu_buf_heapify(GuBuf *buf, GuOrder *order)
|
||||
void *value = alloca(buf->elem_size);
|
||||
|
||||
for (size_t i = 0; i < middle; i++) {
|
||||
memcpy(value, &buf->data[buf->elem_size * i], buf->elem_size);
|
||||
memcpy(value, &buf->seq->data[buf->elem_size * i], buf->elem_size);
|
||||
gu_heap_siftup(buf, order, value, i);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +398,7 @@ gu_buf_outbuf_begin(GuOutStream* stream, size_t req, size_t* sz_out, GuExn* err)
|
||||
size_t avail = buf->avail_len;
|
||||
gu_assert(len < avail);
|
||||
*sz_out = esz * (avail - len);
|
||||
return &buf->data[len * esz];
|
||||
return &buf->seq->data[len * esz];
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -383,7 +411,7 @@ gu_buf_outbuf_end(GuOutStream* stream, size_t sz, GuExn* err)
|
||||
size_t elem_size = buf->elem_size;
|
||||
gu_require(sz % elem_size == 0);
|
||||
gu_require(sz < elem_size * (len - buf->avail_len));
|
||||
gu_buf_set_length(buf, len + (sz / elem_size));
|
||||
buf->seq->len = len + (sz / elem_size);
|
||||
}
|
||||
|
||||
GuOut*
|
||||
@@ -398,23 +426,16 @@ gu_buf_out(GuBuf* buf, GuPool* pool)
|
||||
return gu_new_out(&bout->stream, pool);
|
||||
}
|
||||
|
||||
const GuSeq
|
||||
gu_null_seq = GU_NULL_SEQ;
|
||||
|
||||
|
||||
#include <gu/type.h>
|
||||
|
||||
GU_DEFINE_KIND(GuSeq, GuOpaque);
|
||||
GU_DEFINE_KIND(GuBuf, abstract);
|
||||
|
||||
GU_DEFINE_TYPE(GuChars, GuSeq, gu_type(char));
|
||||
GU_DEFINE_TYPE(GuBytes, GuSeq, gu_type(uint8_t));
|
||||
|
||||
char*
|
||||
gu_chars_str(GuChars chars, GuPool* pool)
|
||||
gu_char_buf_str(GuCharBuf* chars, GuPool* pool)
|
||||
{
|
||||
size_t len = gu_seq_length(chars);
|
||||
char* data = gu_seq_data(chars);
|
||||
size_t len = gu_buf_length(chars);
|
||||
char* data = gu_buf_data(chars);
|
||||
char* str = gu_new_str(len, pool);
|
||||
memcpy(str, data, len);
|
||||
return str;
|
||||
|
||||
@@ -2,54 +2,40 @@
|
||||
#define GU_SEQ_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
#include <gu/bits.h>
|
||||
|
||||
|
||||
typedef struct GuBuf GuBuf;
|
||||
|
||||
typedef GuOpaque() GuSeq;
|
||||
typedef struct GuSeq GuSeq;
|
||||
|
||||
GuSeq
|
||||
GuSeq*
|
||||
gu_empty_seq();
|
||||
|
||||
GuSeq
|
||||
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;
|
||||
}
|
||||
GuSeq*
|
||||
gu_alloc_seq_(size_t elem_size, size_t length);
|
||||
|
||||
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;
|
||||
}
|
||||
#define gu_alloc_seq(T, N) \
|
||||
gu_alloc_seq_(sizeof(T), (N))
|
||||
|
||||
static inline bool
|
||||
gu_seq_is_null(GuSeq seq)
|
||||
{
|
||||
return (gu_tagged_ptr(seq.w_)) == NULL;
|
||||
}
|
||||
GuSeq*
|
||||
gu_realloc_seq_(GuSeq* seq, size_t elem_size, size_t length);
|
||||
|
||||
#define gu_realloc_seq(S, T, N) \
|
||||
gu_realloc_seq_(S, sizeof(T), (N))
|
||||
|
||||
void
|
||||
gu_seq_free(GuSeq* seq);
|
||||
|
||||
size_t
|
||||
gu_seq_length(GuSeq* seq);
|
||||
|
||||
void*
|
||||
gu_seq_data(GuSeq* seq);
|
||||
|
||||
|
||||
#define gu_seq_index(SEQ, T, I) \
|
||||
@@ -64,14 +50,6 @@ gu_seq_is_null(GuSeq seq)
|
||||
GU_END
|
||||
|
||||
|
||||
|
||||
|
||||
GuBuf*
|
||||
gu_seq_buf(GuSeq seq);
|
||||
|
||||
GuSeq
|
||||
gu_buf_seq(GuBuf* buf);
|
||||
|
||||
GuBuf*
|
||||
gu_make_buf(size_t elem_size, GuPool* pool);
|
||||
|
||||
@@ -87,6 +65,9 @@ gu_buf_avail(GuBuf* buf);
|
||||
void*
|
||||
gu_buf_data(GuBuf* buf);
|
||||
|
||||
GuSeq*
|
||||
gu_buf_data_seq(GuBuf* buf);
|
||||
|
||||
#define gu_buf_index(BUF, T, I) \
|
||||
(&((T*)gu_buf_data(BUF))[I])
|
||||
|
||||
@@ -149,31 +130,14 @@ 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
|
||||
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);
|
||||
gu_char_buf_str(GuCharBuf* chars, GuPool* pool);
|
||||
|
||||
#endif // GU_SEQ_H_
|
||||
|
||||
@@ -216,8 +180,5 @@ struct GuBufType {
|
||||
.elem_type = ELEM_T \
|
||||
}
|
||||
|
||||
extern GU_DECLARE_TYPE(GuChars, GuSeq);
|
||||
extern GU_DECLARE_TYPE(GuBytes, GuSeq);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -504,5 +504,4 @@ GuHasher gu_string_hasher[1] = {
|
||||
|
||||
|
||||
GU_DEFINE_TYPE(GuString, GuOpaque, _);
|
||||
GU_DEFINE_TYPE(GuStrings, GuSeq, gu_type(GuString));
|
||||
GU_DEFINE_KIND(GuStringMap, GuMap);
|
||||
|
||||
@@ -103,11 +103,6 @@ gu_string_cmp(GuString s1, GuString s2);
|
||||
extern GU_DECLARE_TYPE(GuString, GuOpaque);
|
||||
# endif
|
||||
|
||||
# if defined(GU_SEQ_H_) && !defined(GU_STRING_H_SEQ_TYPE_)
|
||||
# define GU_STRING_H_SEQ_TYPE_
|
||||
extern GU_DECLARE_TYPE(GuStrings, GuSeq);
|
||||
# endif
|
||||
|
||||
# if defined(GU_MAP_H_TYPE_) && !defined(GU_STRING_H_MAP_TYPE_)
|
||||
# define GU_STRING_H_MAP_TYPE_
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ typedef GuType_alias GuType_referenced;
|
||||
|
||||
|
||||
|
||||
#include <gu/list.h>
|
||||
#include <gu/mem.h>
|
||||
|
||||
//
|
||||
// struct
|
||||
@@ -221,7 +221,10 @@ struct GuMember {
|
||||
struct GuStructRepr {
|
||||
GuType_repr repr_base;
|
||||
const char* name;
|
||||
GuSList(GuMember) members;
|
||||
struct {
|
||||
int len;
|
||||
GuMember* elems;
|
||||
} members;
|
||||
};
|
||||
|
||||
extern GU_DECLARE_KIND(struct);
|
||||
@@ -259,7 +262,10 @@ extern GU_DECLARE_KIND(struct);
|
||||
#define GU_TYPE_INIT_struct(k_, t_, ...) { \
|
||||
.repr_base = GU_TYPE_INIT_repr(k_, t_, _), \
|
||||
.name = #t_, \
|
||||
.members = GU_SLIST(GuMember, __VA_ARGS__) \
|
||||
.members = { \
|
||||
.len = GU_ARRAY_LEN(GuMember,GU_ID({__VA_ARGS__})), \
|
||||
.elems = ((GuMember[]){__VA_ARGS__}) \
|
||||
} \
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -367,7 +373,10 @@ typedef const struct GuEnumType GuEnumType, GuType_enum;
|
||||
|
||||
struct GuEnumType {
|
||||
GuType_repr repr_base;
|
||||
GuSList(GuEnumConstant) constants;
|
||||
struct {
|
||||
int len;
|
||||
GuEnumConstant* elems;
|
||||
} constants;
|
||||
};
|
||||
|
||||
#define GU_ENUM_C(t_, x) { \
|
||||
@@ -378,7 +387,10 @@ struct GuEnumType {
|
||||
|
||||
#define GU_TYPE_INIT_enum(k_, t_, ...) { \
|
||||
.repr_base = GU_TYPE_INIT_repr(k_, t_, _), \
|
||||
.constants = GU_SLIST(GuEnumConstant, __VA_ARGS__) \
|
||||
.constants = { \
|
||||
.len = GU_ARRAY_LEN(GuEnumConstant,GU_ID({__VA_ARGS__})), \
|
||||
.elems = ((GuEnumConstant[]){__VA_ARGS__}) \
|
||||
} \
|
||||
}
|
||||
|
||||
GuEnumConstant*
|
||||
@@ -402,14 +414,22 @@ struct GuTypeTableEntry {
|
||||
typedef const struct GuTypeTable GuTypeTable;
|
||||
|
||||
struct GuTypeTable {
|
||||
GuSList(const GuTypeTable*) parents;
|
||||
GuSList(GuTypeTableEntry) entries;
|
||||
struct {
|
||||
int len;
|
||||
GuTypeTable** elems;
|
||||
} parents;
|
||||
struct {
|
||||
int len;
|
||||
GuTypeTableEntry* elems;
|
||||
} entries;
|
||||
};
|
||||
|
||||
#define GU_TYPETABLE(parents_, ...) { \
|
||||
.parents = parents_, \
|
||||
.entries = GU_SLIST(GuTypeTableEntry, \
|
||||
__VA_ARGS__) \
|
||||
.entries = { \
|
||||
.len = GU_ARRAY_LEN(GuTypeTableEntry,GU_ID({__VA_ARGS__})), \
|
||||
.elems = ((GuTypeTableEntry[]){__VA_ARGS__}) \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct GuTypeMap GuTypeMap;
|
||||
|
||||
@@ -148,7 +148,10 @@ struct GuConstructor {
|
||||
|
||||
|
||||
|
||||
typedef GuSList(GuConstructor) GuConstructors;
|
||||
typedef struct {
|
||||
int len;
|
||||
GuConstructor* elems;
|
||||
} GuConstructors;
|
||||
|
||||
typedef const struct GuVariantType GuVariantType, GuType_GuVariant;
|
||||
|
||||
@@ -159,7 +162,10 @@ struct GuVariantType {
|
||||
|
||||
#define GU_TYPE_INIT_GuVariant(k_, t_, ...) { \
|
||||
.repr_base = GU_TYPE_INIT_repr(k_, GuVariant, _), \
|
||||
.ctors = GU_SLIST(GuConstructor, __VA_ARGS__) \
|
||||
.ctors = { \
|
||||
.len = GU_ARRAY_LEN(GuConstructor,GU_ID({__VA_ARGS__})), \
|
||||
.elems = ((GuConstructor[]){__VA_ARGS__}) \
|
||||
} \
|
||||
}
|
||||
|
||||
extern GU_DECLARE_KIND(GuVariant);
|
||||
|
||||
Reference in New Issue
Block a user