[libsoup] soup-http-input-stream: use a list of SoupBuffers instead a custom buffer



commit 399c6105b7eda992d521cb55c96ededbbb456187
Author: Sergio Villar Senin <svillar igalia com>
Date:   Fri Sep 16 16:55:10 2011 +0200

    soup-http-input-stream: use a list of SoupBuffers instead a custom buffer
    
    We store now a list of SoupBuffers pending to be read. That would save us
    several realloc() and memcpy() if the client does not read from the stream
    quickly enough.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=659255

 libsoup/soup-http-input-stream.c |   62 ++++++++++++++++----------------------
 1 files changed, 26 insertions(+), 36 deletions(-)
---
diff --git a/libsoup/soup-http-input-stream.c b/libsoup/soup-http-input-stream.c
index 6aa153d..a28ea46 100644
--- a/libsoup/soup-http-input-stream.c
+++ b/libsoup/soup-http-input-stream.c
@@ -51,8 +51,7 @@ typedef struct {
 	SoupHTTPInputStreamCallback finished_cb;
 	SoupHTTPInputStreamCallback cancelled_cb;
 
-	guchar *leftover_buffer;
-	gsize leftover_bufsize, leftover_offset;
+	GQueue *leftover_queue;
 
 	guchar *caller_buffer;
 	gsize caller_bufsize, caller_nread;
@@ -120,7 +119,9 @@ soup_http_input_stream_finalize (GObject *object)
 	g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_http_input_stream_got_chunk), stream);
 	g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (soup_http_input_stream_finished), stream);
 	g_object_unref (priv->msg);
-	g_free (priv->leftover_buffer);
+
+	g_queue_foreach (priv->leftover_queue, (GFunc) soup_buffer_free, NULL);
+	g_queue_free (priv->leftover_queue);
 
 	if (G_OBJECT_CLASS (soup_http_input_stream_parent_class)->finalize)
 		(*G_OBJECT_CLASS (soup_http_input_stream_parent_class)->finalize)(object);
@@ -157,7 +158,9 @@ soup_http_input_stream_seekable_iface_init (GSeekableIface *seekable_iface)
 static void
 soup_http_input_stream_init (SoupHTTPInputStream *stream)
 {
-	;
+	SoupHTTPInputStreamPrivate *priv = SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
+
+	priv->leftover_queue = g_queue_new ();
 }
 
 static void
@@ -261,12 +264,8 @@ soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer,
 	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
 		return;
 
-	/* Sanity check */
-	if (priv->caller_bufsize == 0 || priv->leftover_bufsize != 0)
-		g_warning ("soup_http_input_stream_got_chunk called again before previous chunk was processed");
-
 	/* Copy what we can into priv->caller_buffer */
-	if (priv->caller_bufsize > priv->caller_nread) {
+	if (priv->caller_bufsize > priv->caller_nread && priv->leftover_queue->length == 0) {
 		gsize nread = MIN (chunk_size, priv->caller_bufsize - priv->caller_nread);
 
 		memcpy (priv->caller_buffer + priv->caller_nread, chunk, nread);
@@ -277,20 +276,13 @@ soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer,
 	}
 
 	if (chunk_size > 0) {
-		/* Copy the rest into priv->leftover_buffer. If
-		 * there's already some data there, realloc and
-		 * append. Otherwise just copy.
-		 */
-		if (priv->leftover_bufsize) {
-			priv->leftover_buffer = g_realloc (priv->leftover_buffer,
-							   priv->leftover_bufsize + chunk_size);
-			memcpy (priv->leftover_buffer + priv->leftover_bufsize,
-				chunk, chunk_size);
-			priv->leftover_bufsize += chunk_size;
+		if (priv->leftover_queue->length > 0) {
+			g_queue_push_tail (priv->leftover_queue, soup_buffer_copy (chunk_buffer));
 		} else {
-			priv->leftover_bufsize = chunk_size;
-			priv->leftover_buffer = g_memdup (chunk, chunk_size);
-			priv->leftover_offset = 0;
+			g_queue_push_head (priv->leftover_queue,
+					   soup_buffer_new_subbuffer (chunk_buffer,
+								      chunk_buffer->length - chunk_size,
+								      chunk_size));
 		}
 	}
 
@@ -385,19 +377,17 @@ read_from_leftover (SoupHTTPInputStreamPrivate *priv,
 		    gpointer buffer, gsize bufsize)
 {
 	gsize nread;
+	SoupBuffer *soup_buffer = (SoupBuffer *) g_queue_peek_head (priv->leftover_queue);
+	gboolean fits_in_buffer = soup_buffer->length <= bufsize;
 
-	if (priv->leftover_bufsize - priv->leftover_offset <= bufsize) {
-		nread = priv->leftover_bufsize - priv->leftover_offset;
-		memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
-
-		g_free (priv->leftover_buffer);
-		priv->leftover_buffer = NULL;
-		priv->leftover_bufsize = priv->leftover_offset = 0;
-	} else {
-		nread = bufsize;
-		memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
-		priv->leftover_offset += nread;
-	}
+	nread = fits_in_buffer ? soup_buffer->length : bufsize;
+	memcpy (buffer, soup_buffer->data, nread);
+
+	g_queue_pop_head (priv->leftover_queue);
+	if (!fits_in_buffer)
+		g_queue_push_head (priv->leftover_queue,
+				   soup_buffer_new_subbuffer (soup_buffer, nread, soup_buffer->length - nread));
+	soup_buffer_free (soup_buffer);
 
 	priv->offset += nread;
 	return nread;
@@ -490,7 +480,7 @@ soup_http_input_stream_read (GInputStream  *stream,
 	SoupHTTPInputStreamPrivate *priv = SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
 
 	/* If there is data leftover from a previous read, return it. */
-	if (priv->leftover_bufsize)
+	if (priv->leftover_queue->length)
 		return read_from_leftover (priv, buffer, count);
 
 	if (priv->finished)
@@ -701,7 +691,7 @@ soup_http_input_stream_read_async (GInputStream        *stream,
 					    callback, user_data,
 					    soup_http_input_stream_read_async);
 
-	if (priv->leftover_bufsize) {
+	if (priv->leftover_queue->length) {
 		gsize nread = read_from_leftover (priv, buffer, count);
 		g_simple_async_result_set_op_res_gssize (result, nread);
 		g_simple_async_result_complete_in_idle (result);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]