summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buf.c4
-rw-r--r--buf.h4
-rw-r--r--stream.c30
-rw-r--r--stream.h1
-rw-r--r--txr.123
5 files changed, 60 insertions, 2 deletions
diff --git a/buf.c b/buf.c
index 09bdd0ee..c59c282a 100644
--- a/buf.c
+++ b/buf.c
@@ -397,7 +397,7 @@ val buf_put_buf(val dbuf, val sbuf, val pos)
return sbuf;
}
-static void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
+void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
{
struct buf *b = buf_handle(buf, self);
cnum p = buf_check_index(b, pos, self);
@@ -589,7 +589,7 @@ val buf_put_cptr(val buf, val pos, val cptr)
return cptr;
}
-static void buf_get_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
+void buf_get_bytes(val buf, val pos, mem_t *ptr, cnum size, val self)
{
struct buf *b = buf_handle(buf, self);
cnum p = buf_check_index(b, pos, self);
diff --git a/buf.h b/buf.h
index 578bc5aa..bafd1bd4 100644
--- a/buf.h
+++ b/buf.h
@@ -41,6 +41,8 @@ val replace_buf(val buf, val items, val from, val to);
val buf_list(val list);
val buf_put_buf(val dbuf, val sbuf, val pos);
+void buf_put_bytes(val buf, val pos, mem_t *ptr, cnum size, val self);
+
#if HAVE_I8
val buf_put_i8(val buf, val pos, val num);
val buf_put_u8(val buf, val pos, val num);
@@ -73,6 +75,8 @@ val buf_put_float(val buf, val pos, val num);
val buf_put_double(val buf, val pos, val num);
val buf_put_cptr(val buf, val pos, val cptr);
+void buf_get_bytes(val buf, val pos, mem_t *ptr, cnum size, val self);
+
#if HAVE_I8
val buf_get_i8(val buf, val pos);
val buf_get_u8(val buf, val pos);
diff --git a/stream.c b/stream.c
index ae8f384e..5d040e5d 100644
--- a/stream.c
+++ b/stream.c
@@ -3038,6 +3038,35 @@ val fill_buf_adjust(val buf, val pos_in, val stream_in)
return readpos;
}
+val get_line_as_buf(val stream_in)
+{
+ val self = lit("get-line-as-buf");
+ val stream = default_arg(stream_in, std_input);
+ struct strm_ops *ops = coerce(struct strm_ops *,
+ cobj_ops(self, stream, stream_s));
+ val buf = make_buf(zero, nil, num_fast(128));
+ unsigned char bytes[128];
+ size_t count = 0;
+
+ for (;;) {
+ val b = ops->get_byte(stream);
+ if (b == nil || b == num('\n'))
+ break;
+ bytes[count++] = c_num(b);
+
+ if (count == sizeof bytes) {
+ buf_put_bytes(buf, length_buf(buf), bytes, count, self);
+ count = 0;
+ }
+ }
+
+ if (count > 0)
+ buf_put_bytes(buf, length_buf(buf), bytes, count, self);
+
+ buf_trim(buf);
+ return buf;
+}
+
struct fmt {
size_t minsize;
const char *dec;
@@ -4964,6 +4993,7 @@ void stream_init(void)
reg_fun(unget_byte_s, func_n2o(unget_byte, 1));
reg_fun(put_buf_s, func_n3o(put_buf, 1));
reg_fun(fill_buf_s, func_n3o(fill_buf, 1));
+ reg_fun(intern(lit("get-line-as-buf"), user_package), func_n1o(get_line_as_buf, 0));
reg_fun(intern(lit("fill-buf-adjust"), user_package), func_n3o(fill_buf_adjust, 1));
reg_fun(intern(lit("flush-stream"), user_package), func_n1o(flush_stream, 0));
reg_fun(intern(lit("seek-stream"), user_package), func_n3(seek_stream));
diff --git a/stream.h b/stream.h
index 5a628d9b..3cfb0f8b 100644
--- a/stream.h
+++ b/stream.h
@@ -199,6 +199,7 @@ val unget_byte(val byte, val stream);
val put_buf(val buf, val pos, val stream);
val fill_buf(val buf, val pos, val stream);
val fill_buf_adjust(val buf, val pos, val stream);
+val get_line_as_buf(val stream);
val vformat(val stream, val string, va_list);
val vformat_to_string(val string, va_list);
val format(val stream, val string, ...);
diff --git a/txr.1 b/txr.1
index 5309290f..404da89a 100644
--- a/txr.1
+++ b/txr.1
@@ -25120,6 +25120,29 @@ Finally, if the operation succeeds, then
.code fill-buf-adjust
adjusts the length of the buffer to match the position that is returned.
+.coNP Function @ get-line-as-buf
+.synb
+.mets (get-line-as-buf <> [ stream ])
+.syne
+.desc
+The
+.code get-line-as-buf
+reads bytes from
+.meta stream
+as if using the
+.code get-byte
+function, until either a the newline character is encountered, or else the end
+of input is encountered. The bytes which are read, exclusive of the newline
+character, are returned in a new buffer object. The newline character, if it
+occurs, is consumed.
+
+If
+.meta stream
+is omitted, it defaults to
+.codn *stdin* .
+
+The stream is required to support byte input.
+
.coNP Functions @ file-get-buf and @ command-get-buf
.synb
.mets (file-get-buf < name >> [ max-bytes <> [ skip-bytes ]])