summaryrefslogtreecommitdiff
path: root/libsoup/soup-filter-input-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/soup-filter-input-stream.c')
-rw-r--r--libsoup/soup-filter-input-stream.c53
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);
}