diff --git a/http/socket_buf.c b/http/socket_buf.c
index da32e5e..b6133ac 100644
--- a/http/socket_buf.c
+++ b/http/socket_buf.c
@@ -51,8 +51,8 @@ s_socket_buf * socket_buf_init (s_socket_buf *sb, t_socket sockfd,
assert(! "socket_buf_init: buf_rw_init_alloc");
return NULL;
}
- tmp.buf_rw.r.user_ptr = sb;
- tmp.buf_rw.w.user_ptr = sb;
+ tmp.buf_rw.r->user_ptr = sb;
+ tmp.buf_rw.w->user_ptr = sb;
if (! buf_rw_fd_open(&tmp.buf_rw, sockfd)) {
err_puts("socket_buf_init: buf_rw_fd_open");
assert(! "socket_buf_init: buf_rw_fd_open");
diff --git a/lib/kc3/0.1/buf_rw.kc3 b/lib/kc3/0.1/buf_rw.kc3
index 9faea82..d30b7c1 100644
--- a/lib/kc3/0.1/buf_rw.kc3
+++ b/lib/kc3/0.1/buf_rw.kc3
@@ -1,7 +1,7 @@
defmodule BufRW do
- defstruct [r: %Buf{},
- w: %Buf{}]
+ defstruct [r: (Ptr) 0,
+ w: (Ptr) 0]
def init_alloc = cfn BufRW "buf_rw_init_alloc" (Result, Uw)
diff --git a/lib/kc3/0.1/http/request.kc3 b/lib/kc3/0.1/http/request.kc3
index 1debeed..f33ffbb 100644
--- a/lib/kc3/0.1/http/request.kc3
+++ b/lib/kc3/0.1/http/request.kc3
@@ -7,6 +7,6 @@ defmodule HTTP.Request do
dlopen(__DIR__ + "../http.so")
- def buf_parse = cfn HTTP.Request "http_request_buf_parse" (Result, Buf)
+ def buf_parse = cfn HTTP.Request "http_request_buf_parse" (Result, Ptr)
end
diff --git a/lib/kc3/0.1/http/response.kc3 b/lib/kc3/0.1/http/response.kc3
index 8630e6b..10664e7 100644
--- a/lib/kc3/0.1/http/response.kc3
+++ b/lib/kc3/0.1/http/response.kc3
@@ -12,6 +12,6 @@ defmodule HTTP.Response do
{(U16) 404, "Not Found"},
{(U16) 500, "Internal Server Error"}]
- def buf_write = cfn Sw "http_response_buf_write" (HTTP.Response, Buf)
+ def buf_write = cfn Sw "http_response_buf_write" (HTTP.Response, Ptr)
end
diff --git a/libkc3/buf.c b/libkc3/buf.c
index ee09959..01c4b44 100644
--- a/libkc3/buf.c
+++ b/libkc3/buf.c
@@ -191,13 +191,23 @@ s_buf * buf_init (s_buf *buf, bool p_free, uw size, char *p)
s_buf tmp = {0};
assert(buf);
tmp.free = p_free;
- tmp.line = 0;
tmp.ptr.pchar = p;
tmp.size = size;
*buf = tmp;
return buf;
}
+s_buf * buf_init_const (s_buf *buf, uw size, const char *p)
+{
+ s_buf tmp = {0};
+ assert(buf);
+ tmp.ptr.pchar = (char *) p;
+ tmp.read_only = true;
+ tmp.size = size;
+ *buf = tmp;
+ return buf;
+}
+
s_buf * buf_init_1 (s_buf *buf, bool p_free, char *p)
{
uw len;
@@ -211,6 +221,20 @@ s_buf * buf_init_1 (s_buf *buf, bool p_free, char *p)
return buf;
}
+s_buf * buf_init_1_const (s_buf *buf, const char *p)
+{
+ uw len;
+ s_buf tmp = {0};
+ assert(buf);
+ assert(p);
+ len = strlen(p);
+ buf_init(&tmp, false, len, (char *) p);
+ tmp.read_only = true;
+ tmp.wpos = len;
+ *buf = tmp;
+ return buf;
+}
+
s_buf * buf_init_1_copy (s_buf *buf, const char *p)
{
uw size;
@@ -258,6 +282,17 @@ s_buf * buf_init_str (s_buf *buf, bool p_free, s_str *p)
return buf;
}
+s_buf * buf_init_str_const (s_buf *buf, const s_str *p)
+{
+ s_buf tmp = {0};
+ assert(buf);
+ assert(p);
+ buf_init_const(&tmp, p->size, p->ptr.pchar);
+ tmp.wpos = p->size;
+ *buf = tmp;
+ return buf;
+}
+
s_buf * buf_init_str_copy (s_buf *buf, const s_str *str)
{
s_buf tmp = {0};
@@ -496,9 +531,14 @@ sw buf_peek_s64 (s_buf *buf, s64 *p)
sw buf_peek_str (s_buf *buf, const s_str *src)
{
+ sw r;
sw size;
assert(buf);
assert(src);
+ if (! src->size)
+ return 0;
+ if ((r = buf_refill(buf, src->size)) < 0)
+ return r;
if (buf->rpos > buf->wpos) {
assert(buf->rpos <= buf->wpos);
return -1;
@@ -892,16 +932,38 @@ sw buf_refill (s_buf *buf, sw size)
{
sw r = buf->wpos - buf->rpos;
assert(buf);
- if (size <= 0)
+ if (buf->read_only)
return r;
- if (buf->rpos + size > buf->wpos &&
- (r = buf_refill_compact(buf)) >= 0 &&
- buf->refill)
- while ((r = buf->refill(buf)) > 0 &&
- buf->wpos - buf->rpos < (uw) size)
- ;
- if (r >= 0)
- r = buf->wpos - buf->rpos;
+ if (size < 0) {
+ err_puts("buf_refill: size < 0");
+ assert(! "buf_refill: size < 0");
+ return -1;
+ }
+ if (! size) {
+ err_puts("buf_refill: size = 0");
+ assert(! "buf_refill: size = 0");
+ return 0;
+ }
+ if (buf->rpos + size > buf->wpos) {
+ if ((r = buf_refill_compact(buf)) < 0) {
+ err_puts("buf_refill: buf_refill_compact");
+ assert(! "buf_refill: buf_refill_compact");
+ return r;
+ }
+ if (buf->refill)
+ while (1) {
+ if ((r = buf->refill(buf)) < 0) {
+ err_puts("buf_refill: buf->refill");
+ assert(! "buf_refill: buf->refill");
+ return r;
+ }
+ if (! r)
+ return -1;
+ if (buf->wpos - buf->rpos >= (uw) size)
+ break;
+ }
+ }
+ r = buf->wpos - buf->rpos;
return r;
}
@@ -909,7 +971,10 @@ sw buf_refill_compact (s_buf *buf)
{
uw min_rpos;
s_buf_save *save;
+ uw size;
assert(buf);
+ if (buf->read_only)
+ return 0;
min_rpos = buf_save_min_rpos(buf);
if (min_rpos > buf->wpos) {
assert(min_rpos <= buf->wpos);
@@ -925,7 +990,6 @@ sw buf_refill_compact (s_buf *buf)
buf->wpos = 0;
}
else {
- uw size;
size = buf->wpos - min_rpos;
assert(size < buf->size);
memmove(buf->ptr.p,
diff --git a/libkc3/buf.h b/libkc3/buf.h
index c4cfc5f..30e8a5c 100644
--- a/libkc3/buf.h
+++ b/libkc3/buf.h
@@ -28,10 +28,13 @@
/* Stack-allocation compatible functions, call buf_clean after use. */
void buf_clean (s_buf *buf);
s_buf * buf_init (s_buf *buf, bool p_free, uw size, char *p);
+s_buf * buf_init_const (s_buf *buf, uw size, const char *p);
s_buf * buf_init_1 (s_buf *buf, bool p_free, char *p);
+s_buf * buf_init_1_const (s_buf *buf, const char *p);
s_buf * buf_init_alloc (s_buf *buf, uw size);
s_buf * buf_init_copy (s_buf *buf, const s_buf *src);
s_buf * buf_init_str (s_buf *buf, bool free, s_str *p);
+s_buf * buf_init_str_const (s_buf *buf, const s_str *p);
s_buf * buf_init_str_copy (s_buf *buf, const s_str *str);
/* Heap-allocation compatible functions, call buf_delete after use. */
diff --git a/libkc3/buf_fd.c b/libkc3/buf_fd.c
index 3f76262..b05abef 100644
--- a/libkc3/buf_fd.c
+++ b/libkc3/buf_fd.c
@@ -57,18 +57,38 @@ sw buf_fd_open_r_refill (s_buf *buf)
uw size;
assert(buf);
assert(buf->user_ptr);
- if (buf->rpos > buf->wpos ||
- buf->wpos > buf->size)
+ if (buf->rpos > buf->wpos) {
+ err_puts("buf_fd_open_r_refill: buf->rpos > buf->wpos");
+ assert(! "buf_fd_open_r_refill: buf->rpos > buf->wpos");
return -1;
+ }
+ if (buf->wpos > buf->size) {
+ err_puts("buf_fd_open_r_refill: buf->wpos > buf->size");
+ assert(! "buf_fd_open_r_refill: buf->wpos > buf->size");
+ return -1;
+ }
size = buf->size - buf->wpos;
fd = ((s_buf_fd *) (buf->user_ptr))->fd;
//r = read(fd, buf->ptr.pchar + buf->wpos, size);
- if (ioctl(fd, FIONREAD, &avail) == -1 ||
- avail <= 0)
+ if (ioctl(fd, FIONREAD, &avail) == -1) {
+ err_puts("buf_fd_open_r_refill: ioctl FIONREAD: -1");
+ return -1;
+ }
+ if (avail < 0) {
+ err_write_1("buf_fd_open_r_refill: avail: ");
+ err_inspect_s32(&avail);
return -1;
+ }
+ if (! avail)
+ return 0;
if ((uw) avail > size)
avail = size;
r = read(fd, buf->ptr.pchar + buf->wpos, avail);
+ if (r < 0) {
+ err_puts("buf_fd_open_r_refill: read");
+ assert(! "buf_fd_open_r_refill: read");
+ return r;
+ }
if (buf->wpos + r > buf->size) {
err_puts("buf_fd_open_r_refill: buffer overflow");
assert(! "buf_fd_open_r_refill: buffer overflow");
diff --git a/libkc3/buf_file.c b/libkc3/buf_file.c
index 12390fa..063e4a5 100644
--- a/libkc3/buf_file.c
+++ b/libkc3/buf_file.c
@@ -68,9 +68,16 @@ sw buf_file_open_r_refill (s_buf *buf)
uw size;
assert(buf);
assert(buf->user_ptr);
- if (buf->rpos > buf->wpos ||
- buf->wpos > buf->size)
+ if (buf->rpos > buf->wpos) {
+ err_puts("buf_file_open_r_refill: buf->rpos > buf->wpos");
+ assert(! "buf_file_open_r_refill: buf->rpos > buf->wpos");
return -1;
+ }
+ if (buf->wpos >= buf->size) {
+ err_puts("buf_file_open_r_refill: buf->wpos >= buf->size");
+ assert(! "buf_file_open_r_refill: buf->wpos >= buf->size");
+ return -1;
+ }
size = buf->size - buf->wpos;
r = fread(buf->ptr.pchar + buf->wpos, 1, size,
((s_buf_file *) (buf->user_ptr))->fp);
diff --git a/libkc3/buf_getc.c b/libkc3/buf_getc.c
index e281314..37d46a1 100644
--- a/libkc3/buf_getc.c
+++ b/libkc3/buf_getc.c
@@ -56,7 +56,7 @@ sw buf_getc_refill (s_buf *buf)
return -1;
fp = buf->user_ptr;
if (feof(fp))
- return -1;
+ return 0;
while (buf->wpos < buf->size &&
c != '\n' &&
(c = getc(fp)) != EOF &&
diff --git a/libkc3/buf_parse.c b/libkc3/buf_parse.c
index 757d94a..51b08c5 100644
--- a/libkc3/buf_parse.c
+++ b/libkc3/buf_parse.c
@@ -408,42 +408,47 @@ sw buf_parse_block (s_buf *buf, s_block *block)
{
sw r;
sw result = 0;
+ s_buf_save save;
bool short_form = false;
assert(buf);
assert(block);
+ buf_save_init(buf, &save);
if ((r = buf_read_sym(buf, &g_sym_do)) < 0)
- return r;
+ goto clean;
if (! r) {
short_form = true;
if ((r = buf_read_1(buf, "{")) <= 0)
- return r;
+ goto clean;
}
result += r;
if ((r = buf_parse_comments(buf)) < 0) {
err_puts("buf_parse_block: buf_parse_comments");
assert(! "buf_parse_block: buf_parse_comments");
- return r;
+ goto restore;
}
result += r;
- if ((r = buf_ignore_spaces(buf)) < 0) {
- err_puts("buf_parse_block: buf_ignore_spaces");
- assert(! "buf_parse_block: buf_ignore_spaces");
- return r;
- }
+ if ((r = buf_ignore_spaces(buf)) <= 0)
+ goto restore;
result += r;
if ((r = buf_parse_block_inner(buf, short_form, block)) < 0) {
err_puts("buf_parse_block: buf_parse_block_inner < 0");
err_inspect_buf(buf);
assert(! "buf_parse_block: buf_parse_block_inner < 0");
- return r;
+ goto restore;
}
if (! r) {
err_puts("buf_parse_block: buf_parse_block_inner = 0");
assert(! "buf_parse_block: buf_parse_block_inner = 0");
- return -1;
+ goto restore;
}
result += r;
- return result;
+ r = result;
+ goto clean;
+ restore:
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
}
sw buf_parse_block_inner (s_buf *buf, bool short_form, s_block *block)
@@ -1087,7 +1092,7 @@ sw buf_parse_call_paren (s_buf *buf, s_call *dest)
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
result += r;
- if ((r = buf_parse_tag(buf, &tmp.arguments->tag)) <= 0)
+ if ((r = buf_parse_tag_primary(buf, &tmp.arguments->tag)) <= 0)
goto restore;
result += r;
if ((r = buf_ignore_spaces(buf)) < 0)
@@ -1812,7 +1817,7 @@ sw buf_parse_fn_pattern (s_buf *buf, s_list **dest)
goto ok;
}
while (1) {
- if ((r = buf_parse_tag(buf, &tag)) <= 0)
+ if ((r = buf_parse_tag_primary_2(buf, &tag)) <= 0)
goto clean;
result += r;
*tail = list_new(NULL);
@@ -3664,6 +3669,7 @@ sw buf_parse_tag (s_buf *buf, s_tag *dest)
if ((r = buf_parse_tag_special_operator(buf, dest)) != 0 ||
(r = buf_parse_tag_brackets(buf, dest)) != 0 ||
(r = buf_parse_tag_call_op(buf, dest)) != 0 ||
+ (r = buf_parse_tag_block(buf, dest)) != 0 ||
(r = buf_parse_tag_primary(buf, dest)) != 0)
goto end;
end:
@@ -4005,7 +4011,6 @@ sw buf_parse_tag_primary_2 (s_buf *buf, s_tag *dest)
(r = buf_parse_tag_map(buf, dest)) != 0 ||
(r = buf_parse_tag_str(buf, dest)) != 0 ||
(r = buf_parse_tag_tuple(buf, dest)) != 0 ||
- (r = buf_parse_tag_block(buf, dest)) != 0 ||
(r = buf_parse_tag_cfn(buf, dest)) != 0 ||
(r = buf_parse_tag_fn(buf, dest)) != 0 ||
(r = buf_parse_tag_struct(buf, dest)) != 0 ||
diff --git a/libkc3/buf_parse.h b/libkc3/buf_parse.h
index 264decb..1b55cfb 100644
--- a/libkc3/buf_parse.h
+++ b/libkc3/buf_parse.h
@@ -106,6 +106,7 @@ sw buf_parse_sym (s_buf *buf, const s_sym **dest);
sw buf_parse_sym_str (s_buf *buf, s_str *dest);
sw buf_parse_tag (s_buf *buf, s_tag *dest);
sw buf_parse_tag_array (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_block (s_buf *buf, s_tag *dest);
sw buf_parse_tag_bool (s_buf *buf, s_tag *dest);
sw buf_parse_tag_brackets (s_buf *buf, s_tag *dest);
sw buf_parse_tag_call (s_buf *buf, s_tag *dest);
diff --git a/libkc3/buf_rw.c b/libkc3/buf_rw.c
index e8cf2d9..aeec0d8 100644
--- a/libkc3/buf_rw.c
+++ b/libkc3/buf_rw.c
@@ -18,16 +18,16 @@
void buf_rw_clean (s_buf_rw *buf_rw)
{
assert(buf_rw);
- buf_clean(&buf_rw->w);
- buf_clean(&buf_rw->r);
+ buf_delete(buf_rw->w);
+ buf_delete(buf_rw->r);
}
void buf_rw_fd_close (s_buf_rw *buf_rw)
{
assert(buf_rw);
- buf_fd_close(&buf_rw->r);
- buf_fd_close(&buf_rw->w);
+ buf_fd_close(buf_rw->r);
+ buf_fd_close(buf_rw->w);
}
s_buf_rw * buf_rw_fd_open (s_buf_rw *buf_rw, s32 fd)
@@ -35,10 +35,10 @@ s_buf_rw * buf_rw_fd_open (s_buf_rw *buf_rw, s32 fd)
s_buf_rw tmp = {0};
assert(buf_rw);
tmp = *buf_rw;
- if (! buf_fd_open_r(&tmp.r, fd))
+ if (! buf_fd_open_r(tmp.r, fd))
return NULL;
- if (! buf_fd_open_w(&tmp.w, fd)) {
- buf_fd_close(&tmp.r);
+ if (! buf_fd_open_w(tmp.w, fd)) {
+ buf_fd_close(tmp.r);
return NULL;
}
*buf_rw = tmp;
@@ -48,10 +48,10 @@ s_buf_rw * buf_rw_fd_open (s_buf_rw *buf_rw, s32 fd)
s_buf_rw * buf_rw_init_alloc (s_buf_rw *buf_rw, uw size)
{
s_buf_rw tmp = {0};
- if (! buf_init_alloc(&tmp.r, size))
+ if (! (tmp.r = buf_new_alloc(size)))
return NULL;
- if (! buf_init_alloc(&tmp.w, size)) {
- buf_clean(&tmp.r);
+ if (! (tmp.w = buf_new_alloc(size))) {
+ buf_delete(tmp.r);
return NULL;
}
*buf_rw = tmp;
diff --git a/libkc3/list.c b/libkc3/list.c
index 70b960f..ea25edb 100644
--- a/libkc3/list.c
+++ b/libkc3/list.c
@@ -205,7 +205,7 @@ s_list * list_new_1 (const char *p)
{
s_buf buf;
s_list *list;
- buf_init_1(&buf, false, (char *) p);
+ buf_init_1_const(&buf, p);
if (buf_parse_list(&buf, &list) != (sw) strlen(p)) {
err_puts("list_new_1: invalid list");
assert(! "list_new_1: invalid list");
diff --git a/libkc3/types.h b/libkc3/types.h
index 8826665..5825f3d 100644
--- a/libkc3/types.h
+++ b/libkc3/types.h
@@ -349,6 +349,7 @@ struct buf {
bool free;
sw line;
u_ptr_w ptr;
+ bool read_only;
sw (*refill) (s_buf *buf);
uw rpos;
s_buf_save *save;
@@ -398,8 +399,8 @@ struct struct_type {
/* 3 */
struct buf_rw {
- s_buf r;
- s_buf w;
+ s_buf *r;
+ s_buf *w;
};
struct call {
diff --git a/libkc3/u.c.in b/libkc3/u.c.in
index a2a253b..4aae172 100644
--- a/libkc3/u.c.in
+++ b/libkc3/u.c.in
@@ -112,8 +112,7 @@ u_bits$ * u_bits$_init_str (u_bits$ *u, const s_str *str)
{
s_buf buf;
u_bits$ tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_u_bits$(&buf, &tmp) <= 0) {
err_puts("u_bits$_init_str: buf_parse_u_bits$");
assert(! "u_bits$_init_str: buf_parse_u_bits$");
diff --git a/libkc3/u16.c b/libkc3/u16.c
index 09facdb..b093681 100644
--- a/libkc3/u16.c
+++ b/libkc3/u16.c
@@ -112,8 +112,7 @@ u16 * u16_init_str (u16 *u, const s_str *str)
{
s_buf buf;
u16 tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_u16(&buf, &tmp) <= 0) {
err_puts("u16_init_str: buf_parse_u16");
assert(! "u16_init_str: buf_parse_u16");
diff --git a/libkc3/u32.c b/libkc3/u32.c
index afc7db9..d10e282 100644
--- a/libkc3/u32.c
+++ b/libkc3/u32.c
@@ -112,8 +112,7 @@ u32 * u32_init_str (u32 *u, const s_str *str)
{
s_buf buf;
u32 tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_u32(&buf, &tmp) <= 0) {
err_puts("u32_init_str: buf_parse_u32");
assert(! "u32_init_str: buf_parse_u32");
diff --git a/libkc3/u64.c b/libkc3/u64.c
index 74aebdf..c909495 100644
--- a/libkc3/u64.c
+++ b/libkc3/u64.c
@@ -112,8 +112,7 @@ u64 * u64_init_str (u64 *u, const s_str *str)
{
s_buf buf;
u64 tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_u64(&buf, &tmp) <= 0) {
err_puts("u64_init_str: buf_parse_u64");
assert(! "u64_init_str: buf_parse_u64");
diff --git a/libkc3/u8.c b/libkc3/u8.c
index 3f1d1a8..9f5a414 100644
--- a/libkc3/u8.c
+++ b/libkc3/u8.c
@@ -112,8 +112,7 @@ u8 * u8_init_str (u8 *u, const s_str *str)
{
s_buf buf;
u8 tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_u8(&buf, &tmp) <= 0) {
err_puts("u8_init_str: buf_parse_u8");
assert(! "u8_init_str: buf_parse_u8");
diff --git a/libkc3/uw.c b/libkc3/uw.c
index 78ac3e7..3db6bab 100644
--- a/libkc3/uw.c
+++ b/libkc3/uw.c
@@ -112,8 +112,7 @@ uw * uw_init_str (uw *u, const s_str *str)
{
s_buf buf;
uw tmp = 0;
- buf_init(&buf, false, str->size, (char *) str->ptr.pchar);
- buf.wpos = str->size;
+ buf_init_str_const(&buf, str);
if (buf_parse_uw(&buf, &tmp) <= 0) {
err_puts("uw_init_str: buf_parse_uw");
assert(! "uw_init_str: buf_parse_uw");
diff --git a/test/buf_parse_test.c b/test/buf_parse_test.c
index c235416..027187e 100644
--- a/test/buf_parse_test.c
+++ b/test/buf_parse_test.c
@@ -259,7 +259,7 @@
s_buf buf; \
s_list *dest = NULL; \
test_context("buf_parse_list(" # test ")"); \
- buf_init_1(&buf, false, (test)); \
+ buf_init_1_const(&buf, (test)); \
TEST_EQ(buf_parse_list(&buf, &dest), strlen(test)); \
list_delete_all(dest); \
test_context(NULL); \