summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parser.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/parser.c b/parser.c
index b6b0560c..a3520a15 100644
--- a/parser.c
+++ b/parser.c
@@ -77,6 +77,8 @@
#define SHADOW_TAB_SIZE 16
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
val parser_s, unique_s, circref_s;
val listener_hist_len_s, listener_multi_line_p_s, listener_sel_inclusive_p_s;
val listener_pprint_s, listener_greedy_eval_s, listener_auto_compound_s;
@@ -2240,6 +2242,28 @@ static ucnum shadow_put_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
return ops->put_buf(stream, ptr, len, pos);
}
+static ucnum shadow_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
+{
+ val self = lit("fill-buf");
+ struct strm_base *s = coerce(struct strm_base *, stream->co.handle);
+ struct shadow_context *sc = coerce(struct shadow_context *, s->shadow_obj);
+
+ if (convert(size_t, len) != len || len > INT_PTR_MAX)
+ uw_throwf(error_s, lit("~a: buffer too large"), self, nao);
+ if (pos >= len) {
+ return len;
+ } else {
+ size_t room = len - pos;
+ size_t avail = sc->size - sc->index;
+ size_t copy = min(room, avail);
+ memcpy(ptr + pos, sc->buf + sc->index, copy);
+ sc->index += copy;
+ if (copy == avail)
+ shadow_detach(stream);
+ return pos + copy;
+ }
+}
+
static val shadow_close(val stream, val throw_on_error)
{
struct strm_ops *ops = shadow_detach(stream);
@@ -2275,7 +2299,7 @@ static struct strm_ops shadow_ops_template =
shadow_put_string, shadow_put_char, shadow_put_byte,
generic_get_line, shadow_get_char, shadow_get_byte,
shadow_unget_char, shadow_unget_byte,
- shadow_put_buf, generic_fill_buf,
+ shadow_put_buf, shadow_fill_buf,
shadow_close, shadow_flush, shadow_seek, shadow_truncate,
0, 0,
0, 0, 0, 0);