summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream.c82
-rw-r--r--stream.h4
-rw-r--r--strudel.c14
-rw-r--r--txr.124
4 files changed, 78 insertions, 46 deletions
diff --git a/stream.c b/stream.c
index 5d040e5d..7120fd78 100644
--- a/stream.c
+++ b/stream.c
@@ -192,16 +192,18 @@ static noreturn val unimpl_unget_byte(val stream, int byte)
unimpl(stream, lit("unget-byte"));
}
-static noreturn val unimpl_put_buf(val stream, val buf, cnum pos)
+static noreturn ucnum unimpl_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
- (void) buf;
+ (void) ptr;
+ (void) len;
(void) pos;
unimpl(stream, lit("put-buf"));
}
-static noreturn val unimpl_fill_buf(val stream, val buf, cnum pos)
+static noreturn ucnum unimpl_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
- (void) buf;
+ (void) ptr;
+ (void) len;
(void) pos;
unimpl(stream, lit("fill-buf"));
}
@@ -347,15 +349,13 @@ static val null_get_fd(val stream)
return nil;
}
-static val generic_put_buf(val stream, val buf, cnum pos)
+static ucnum generic_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
- val self = lit("put-buf");
struct strm_ops *ops = coerce(struct strm_ops *, stream->co.ops);
- cnum len = c_num(length_buf(buf)), i;
- mem_t *ptr = buf_get(buf, self);
+ ucnum i;
if (pos >= len)
- return num(len);
+ return len;
for (i = pos; i < len; i++)
ops->put_byte(stream, *ptr++);
@@ -363,15 +363,13 @@ static val generic_put_buf(val stream, val buf, cnum pos)
if (i > len)
i = len;
- return num(i);
+ return i;
}
-static val generic_fill_buf(val stream, val buf, cnum pos)
+static ucnum generic_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
- val self = lit("fill-buf");
struct strm_ops *ops = coerce(struct strm_ops *, stream->co.ops);
- cnum len = c_num(length_buf(buf)), i;
- mem_t *ptr = buf_get(buf, self);
+ ucnum i;
for (i = pos; i < len; i++) {
val byte = ops->get_byte(stream);
@@ -383,7 +381,7 @@ static val generic_fill_buf(val stream, val buf, cnum pos)
if (i > len)
i = len;
- return num(i);
+ return i;
}
void fill_stream_ops(struct strm_ops *ops)
@@ -898,44 +896,40 @@ static val stdio_unget_byte(val stream, int byte)
: stdio_maybe_error(stream, lit("writing"));
}
-static val stdio_put_buf(val stream, val buf, cnum pos)
+static ucnum stdio_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
val self = lit("put-buf");
- ucnum len = c_unum(length_buf(buf));
- mem_t *ptr = buf_get(buf, self);
struct stdio_handle *h = coerce(struct stdio_handle *, stream->co.handle);
if (convert(size_t, len) != len || len > INT_PTR_MAX)
uw_throwf(error_s, lit("~a: buffer too large"), self, nao);
- if (convert(ucnum, pos) >= len)
- return num(len);
+ if (pos >= len)
+ return len;
errno = 0;
if (h->f != 0) {
cnum nwrit = fwrite(ptr + pos, 1, len - pos, h->f);
if (nwrit > 0)
- return num(pos + nwrit);
+ return pos + nwrit;
}
stdio_maybe_error(stream, lit("writing"));
- return zero;
+ return 0;
}
-static val stdio_fill_buf(val stream, val buf, cnum pos)
+static ucnum stdio_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
val self = lit("fill-buf");
- ucnum len = c_unum(length_buf(buf));
- mem_t *ptr = buf_get(buf, self);
struct stdio_handle *h = coerce(struct stdio_handle *, stream->co.handle);
if (convert(size_t, len) != len || len > INT_PTR_MAX)
uw_throwf(error_s, lit("~a: buffer too large"), self, nao);
- if (convert(ucnum, pos) >= len)
- return num(len);
+ if (pos >= len)
+ return len;
errno = 0;
if (h->f != 0) {
cnum nread = fread(ptr + pos, 1, len - pos, h->f);
if (nread > 0)
- return num(pos + nread);
+ return pos + nread;
}
stdio_maybe_read_error(stream);
- return num(pos);
+ return pos;
}
static val stdio_close(val stream, val throw_on_error)
@@ -2712,16 +2706,16 @@ static val delegate_unget_byte(val stream, int byte)
return s->target_ops->unget_byte(s->target_stream, byte);
}
-static val delegate_put_buf(val stream, val buf, cnum pos)
+static ucnum delegate_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
struct delegate_base *s = coerce(struct delegate_base *, stream->co.handle);
- return s->target_ops->put_buf(s->target_stream, buf, pos);
+ return s->target_ops->put_buf(s->target_stream, ptr, len, pos);
}
-static val delegate_fill_buf(val stream, val buf, cnum pos)
+static ucnum delegate_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
struct delegate_base *s = coerce(struct delegate_base *, stream->co.handle);
- return s->target_ops->fill_buf(s->target_stream, buf, pos);
+ return s->target_ops->fill_buf(s->target_stream, ptr, len, pos);
}
static val delegate_close(val stream, val throw_on_error)
@@ -3008,32 +3002,40 @@ val put_buf(val buf, val pos_in, val stream_in)
{
val self = lit("put-buf");
val stream = default_arg(stream_in, std_output);
- cnum pos = c_num(default_arg(pos_in, zero));
+ ucnum pos = c_unum(default_arg(pos_in, zero));
+ ucnum len = c_unum(length_buf(buf));
+ mem_t *ptr = buf_get(buf, self);
struct strm_ops *ops = coerce(struct strm_ops *,
cobj_ops(self, stream, stream_s));
- return ops->put_buf(stream, buf, pos);
+
+ return unum(ops->put_buf(stream, ptr, len, pos));
}
val fill_buf(val buf, val pos_in, val stream_in)
{
val self = lit("fill-buf");
val stream = default_arg(stream_in, std_input);
- cnum pos = c_num(default_arg(pos_in, zero));
+ ucnum pos = c_unum(default_arg(pos_in, zero));
+ ucnum len = c_unum(length_buf(buf));
+ mem_t *ptr = buf_get(buf, self);
struct strm_ops *ops = coerce(struct strm_ops *,
cobj_ops(self, stream, stream_s));
- return ops->fill_buf(stream, buf, pos);
+ return unum(ops->fill_buf(stream, ptr, len, pos));
}
val fill_buf_adjust(val buf, val pos_in, val stream_in)
{
val self = lit("fill-buf-adjust");
val stream = default_arg(stream_in, std_input);
- cnum pos = c_num(default_arg(pos_in, zero));
+ ucnum pos = c_unum(default_arg(pos_in, zero));
+ val alloc_size = buf_alloc_size(buf);
+ ucnum len = c_unum(alloc_size);
+ mem_t *ptr = buf_get(buf, self);
val readpos;
struct strm_ops *ops = coerce(struct strm_ops *,
cobj_ops(self, stream, stream_s));
- buf_set_length(buf, buf_alloc_size(buf), zero);
- readpos = ops->fill_buf(stream, buf, pos);
+ buf_set_length(buf, alloc_size, zero);
+ readpos = unum(ops->fill_buf(stream, ptr, len, pos));
buf_set_length(buf, readpos, zero);
return readpos;
}
diff --git a/stream.h b/stream.h
index 3cfb0f8b..ba905871 100644
--- a/stream.h
+++ b/stream.h
@@ -69,8 +69,8 @@ struct strm_ops {
val (*get_byte)(val);
val (*unget_char)(val, val);
val (*unget_byte)(val, int);
- val (*put_buf)(val, val, cnum);
- val (*fill_buf)(val, val, cnum);
+ ucnum (*put_buf)(val, mem_t *, ucnum len, ucnum pos);
+ ucnum (*fill_buf)(val, mem_t *, ucnum len, ucnum pos);
val (*close)(val, val);
val (*flush)(val);
val (*seek)(val, val, enum strm_whence);
diff --git a/strudel.c b/strudel.c
index 5aa4f67e..e36389b7 100644
--- a/strudel.c
+++ b/strudel.c
@@ -37,6 +37,8 @@
#include "gc.h"
#include "eval.h"
#include "struct.h"
+#include "arith.h"
+#include "buf.h"
#include "strudel.h"
struct strudel_base { /* stru-ct del-egate :) */
@@ -120,20 +122,24 @@ static val strudel_unget_byte(val stream, int byte)
return funcall2(meth, obj, num_fast(byte));
}
-static val strudel_put_buf(val stream, val buf, cnum pos)
+static ucnum strudel_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
struct strudel_base *sb = coerce(struct strudel_base *, stream->co.handle);
+ obj_t buf_obj;
+ val buf = init_borrowed_buf(&buf_obj, unum(len), ptr);
val obj = sb->obj;
val meth = slot(obj, put_buf_s);
- return funcall3(meth, obj, buf, num(pos));
+ return c_unum(funcall3(meth, obj, buf, num(pos)));
}
-static val strudel_fill_buf(val stream, val buf, cnum pos)
+static ucnum strudel_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
{
struct strudel_base *sb = coerce(struct strudel_base *, stream->co.handle);
+ obj_t buf_obj;
+ val buf = init_borrowed_buf(&buf_obj, unum(len), ptr);
val obj = sb->obj;
val meth = slot(obj, fill_buf_s);
- return funcall3(meth, obj, buf, num(pos));
+ return c_unum(funcall3(meth, obj, buf, num(pos)));
}
static val strudel_close(val stream, val throw_on_error)
diff --git a/txr.1 b/txr.1
index ea70cf2f..5b77a5f5 100644
--- a/txr.1
+++ b/txr.1
@@ -52509,6 +52509,18 @@ description of the
.code put-buf
stream I/O function.
+Note: there is a severe restriction on the use of the
+.meta buf
+argument. The buffer object denoted by the
+.meta buf
+argument may be specially allocated and have a lifetime
+which is scoped to the method invocation. The
+.code put-buf
+method shall not permit the
+.meta buf
+object to be used beyond the duration of the method
+invocaton.
+
.coNP Method @ fill-buf
.synb
.mets << stream .(fill-buf buf pos)
@@ -52522,6 +52534,18 @@ description of the
.code fill-buf
stream I/O function.
+Note: there is a severe restriction on the use of the
+.meta buf
+argument. The buffer object denoted by the
+.meta buf
+argument may be specially allocted and have a lifetime
+which is scoped to the method invocation. The
+.code put-buf
+method shall not permit the
+.meta buf
+object to be used beyond the duration of the method
+invocaton.
+
.coNP Method @ close
.synb
.mets << stream .(close offs whence)