Re: [Sawfish] rep read-line limit |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/sawfish Archives
]
- To: sawfish@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [Sawfish] rep read-line limit
- From: Timo Korvola <Timo.Korvola@xxxxxx>
- Date: Wed, 14 Mar 2012 23:10:34 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:user-agent:references:in-reply-to :mime-version:content-type:message-id; bh=XMWz2SGkx0jLhOuEo0kDdKmKh9u/kS/DTF4nEbDfTN4=; b=WYxyjUOlJ8HXsZXvSqPtpdx/wj8LXXY+QYtR3obG1sewltUcTlOipssgEy+9gSTiqD 9uaoJ6oM1DqqvvTgN7RpS8RrYnoH0uAGbDfsrdtpMmA5caTdnQdupSeMGHAdWkq5Rqos EftQ6D/uBcXd97EEHBladjToounFdsaLzcV6pJCCzctiFhEd0NO9335AZpzmsCTk9fnN eVzICZl57KTTHuAxJ8yR5gYKnwaqgPpyA5qmu0zB1tKApWLOwvFBtA+UitCrFzXcIqx0 JwvKTNzK3rNsuprhi0b2NHI+PJxkjLhuj424sqsBlxwAkeTmEOMp14u2Hln20puF1bfG W43A==
On Wednesday 14 March 2012 15:10:59 Teika Kazura wrote:
> Probably a librep bug. src/streams.c says:
>
> DEFUN("read-line", Fread_line, Sread_line, (repv stream), rep_Subr1)
> /* ..
> char buf[400];
> ..
>
> I don't know well how to fix it. Anyone?
Maybe like this. Not extensively tested though, and may now run out of
memory on very long lines. Another alternative would be a linked list
of fixed-length string buffers, but this realloc approach seemed easier
to code in C.
--
Timo Korvola <URL:http://www.iki.fi/tkorvola>
From 5fde6a78df6d1874ca77f9d65758875f21fc8815 Mon Sep 17 00:00:00 2001
From: Timo Korvola <tkorvola@xxxxxx>
Date: Wed, 14 Mar 2012 22:31:30 +0200
Subject: [PATCH] Cope with long lines in read-line.
Now read-line will read the line to the end or die trying (it is
possible for it to run out of memory).
---
src/streams.c | 71 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 48 insertions(+), 23 deletions(-)
diff --git a/src/streams.c b/src/streams.c
index 950efc5..0711975 100644
--- a/src/streams.c
+++ b/src/streams.c
@@ -653,32 +653,57 @@ DEFUN("read-line", Fread_line, Sread_line, (repv stream), rep_Subr1) /*
::doc:rep.io.streams#read-line::
read-line STREAM
-Read one line of text from STREAM.
+Read one line of text from STREAM. Return it as a string. If the
+line was terminated by a newline (instead of EOF) it is included in
+the return value. If end of file occurs immediately before any
+characters can be read, return nil.
::end:: */
{
- char buf[400];
- if (rep_FILEP(stream) && rep_LOCAL_FILE_P (stream))
- {
- /* Special case for file streams. We can read a line in one go. */
- if (fgets (buf, sizeof (buf), rep_FILE (stream)->file.fh))
- return rep_string_dup (buf);
- else
- return Qnil;
- }
- else
+ int bufsize = 500, offset = 0;
+ char *oldbuf = 0;
+
+ while (1)
{
- char *bufp = buf;
- int len = 0, c;
- while ((c = rep_stream_getc (stream)) != EOF)
- {
- *bufp++ = (char) c;
- len++;
- if ((len >= sizeof (buf) - 1) || (c == '\n'))
- break;
- }
- if (len == 0)
- return Qnil;
- return rep_string_dupn (buf, len);
+ char
+ *fullbuf = realloc(oldbuf, bufsize),
+ *offbuf = fullbuf + offset;
+ int
+ readlen = 0,
+ maxread = bufsize - offset - 1;
+ if (!fullbuf)
+ {
+ free (oldbuf);
+ return rep_mem_error ();
+ }
+ oldbuf = fullbuf;
+ if (rep_FILEP(stream) && rep_LOCAL_FILE_P (stream))
+ {
+ /* Special case for file streams.
+ We can read a line in one go. Or at least something. */
+ if (fgets (offbuf, maxread + 1, rep_FILE (stream)->file.fh))
+ readlen = strlen (offbuf);
+ }
+ else
+ {
+ char *bufp = offbuf;
+ int c;
+ while ((c = rep_stream_getc (stream)) != EOF)
+ {
+ *bufp++ = (char) c;
+ readlen++;
+ if ((readlen >= maxread) || (c == '\n'))
+ break;
+ }
+ }
+ if (offbuf[readlen - 1] == '\n' || readlen < maxread)
+ {
+ int fulllen = offset + readlen;
+ repv rval = fulllen ? rep_string_dupn (fullbuf, fulllen) : Qnil;
+ free(fullbuf);
+ return rval;
+ }
+ offset += maxread;
+ bufsize *= 2;
}
}
--
1.7.2.5