diff options
Diffstat (limited to 'libsoup/soup-filter-input-stream.c')
-rw-r--r-- | libsoup/soup-filter-input-stream.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c index 79159c38..8067b882 100644 --- a/libsoup/soup-filter-input-stream.c +++ b/libsoup/soup-filter-input-stream.c @@ -22,6 +22,8 @@ struct _SoupFilterInputStreamPrivate { GByteArray *buf; + gboolean need_more; + gboolean in_read_until; }; static void soup_filter_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); @@ -78,7 +80,10 @@ soup_filter_input_stream_read_fn (GInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - if (fstream->priv->buf) { + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { return read_from_buf (fstream, buffer, count); } else { return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, @@ -92,7 +97,7 @@ soup_filter_input_stream_is_readable (GPollableInputStream *stream) { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - if (fstream->priv->buf) + if (fstream->priv->buf && !fstream->priv->need_more) return TRUE; else return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream)); @@ -106,7 +111,10 @@ soup_filter_input_stream_read_nonblocking (GPollableInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - if (fstream->priv->buf) { + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { return read_from_buf (fstream, buffer, count); } else { return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, @@ -122,7 +130,7 @@ soup_filter_input_stream_create_source (GPollableInputStream *stream, SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); GSource *base_source, *pollable_source; - if (fstream->priv->buf) + if (fstream->priv->buf && !fstream->priv->need_more) base_source = g_timeout_source_new (0); else base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream), cancellable); @@ -177,7 +185,7 @@ soup_filter_input_stream_read_line (SoupFilterInputStream *fstream, { return soup_filter_input_stream_read_until (fstream, buffer, length, "\n", 1, blocking, - got_line, + TRUE, got_line, cancellable, error); } @@ -188,6 +196,7 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, const void *boundary, gsize boundary_length, gboolean blocking, + gboolean include_boundary, gboolean *got_boundary, GCancellable *cancellable, GError **error) @@ -195,11 +204,13 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, gssize nread; guint8 *p, *buf, *end; gboolean eof = FALSE; + GError *my_error = NULL; g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (fstream), -1); - g_return_val_if_fail (boundary_length < length, -1); + g_return_val_if_fail (!include_boundary || (boundary_length < length), -1); *got_boundary = FALSE; + fstream->priv->need_more = FALSE; if (!fstream->priv->buf || fstream->priv->buf->len < boundary_length) { guint prev_len; @@ -211,10 +222,12 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, g_byte_array_set_size (fstream->priv->buf, length); buf = fstream->priv->buf->data; - nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, + fstream->priv->in_read_until = TRUE; + nread = g_pollable_stream_read (G_INPUT_STREAM (fstream), buf + prev_len, length - prev_len, blocking, - cancellable, error); + cancellable, &my_error); + fstream->priv->in_read_until = FALSE; if (nread <= 0) { if (prev_len) fstream->priv->buf->len = prev_len; @@ -225,8 +238,17 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (nread == 0 && prev_len) eof = TRUE; - else + else { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + fstream->priv->need_more = TRUE; + if (my_error) + g_propagate_error (error, my_error); + return nread; + } + + if (my_error) + g_propagate_error (error, my_error); } else fstream->priv->buf->len = prev_len + nread; } else @@ -237,8 +259,10 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (!eof) end -= boundary_length; for (p = buf; p <= end; p++) { - if (!memcmp (p, boundary, boundary_length)) { - p += boundary_length; + if (*p == *(guint8*)boundary && + !memcmp (p, boundary, boundary_length)) { + if (include_boundary) + p += boundary_length; *got_boundary = TRUE; break; } @@ -247,9 +271,10 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (!*got_boundary && fstream->priv->buf->len < length && !eof) goto fill_buffer; - /* Return everything up to 'p' (which is either just after the - * boundary, @boundary_len - 1 bytes before the end of the - * buffer, or end-of-file). + /* Return everything up to 'p' (which is either just after the boundary if + * include_boundary is TRUE, just before the boundary if include_boundary is + * FALSE, @boundary_len - 1 bytes before the end of the buffer, or end-of- + * file). */ return read_from_buf (fstream, buffer, p - buf); } |