[Swfdec-commits] swfdec/swfdec_buffer.c swfdec/swfdec_buffer.h

Benjamin Otte company at kemper.freedesktop.org
Fri Feb 1 01:22:38 PST 2008


 swfdec/swfdec_buffer.c |  218 +++++++++++++++++++++++--------------------------
 swfdec/swfdec_buffer.h |   18 ++--
 2 files changed, 115 insertions(+), 121 deletions(-)

New commits:
commit 8a4b634f626c44a080b1642670ec17a441929f53
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 1 10:22:01 2008 +0100

    rewrite SwfdecBufferQueue into a peek/flush model
    
    The only thing I don't like about it now is that we ref/unref it.
    I think from a usage POV it makes more sense to copy the whole queue as most
    people want to modify it.

diff --git a/swfdec/swfdec_buffer.c b/swfdec/swfdec_buffer.c
index 9ad80fb..b50fb2d 100644
--- a/swfdec/swfdec_buffer.c
+++ b/swfdec/swfdec_buffer.c
@@ -189,15 +189,17 @@ swfdec_buffer_free_subbuffer (unsigned char *data, gpointer priv)
  * Returns: a new #SwfdecBuffer managing the indicated region.
  **/
 SwfdecBuffer *
-swfdec_buffer_new_subbuffer (SwfdecBuffer * buffer, gsize offset, gsize length)
+swfdec_buffer_new_subbuffer (SwfdecBuffer *buffer, gsize offset, gsize length)
 {
   SwfdecBuffer *subbuffer;
   
   g_return_val_if_fail (buffer != NULL, NULL);
   g_return_val_if_fail (offset + length <= buffer->length, NULL);
 
-  subbuffer = swfdec_buffer_new ();
+  if (offset == 0 && length == buffer->length)
+    return swfdec_buffer_ref (buffer);
 
+  subbuffer = swfdec_buffer_new ();
   subbuffer->priv = swfdec_buffer_ref (swfdec_buffer_get_super (buffer));
   subbuffer->data = buffer->data + offset;
   subbuffer->length = length;
@@ -360,7 +362,7 @@ swfdec_buffer_queue_new (void)
  *
  * Returns: amount of bytes in @queue.
  **/
-guint
+gsize
 swfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue)
 {
   g_return_val_if_fail (queue != NULL, 0);
@@ -377,7 +379,7 @@ swfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue)
  *
  * Returns: Number of bytes that were already pulled from this queue.
  **/
-guint
+gsize
 swfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue)
 {
   g_return_val_if_fail (queue != NULL, 0);
@@ -386,6 +388,41 @@ swfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue)
 }
 
 /**
+ * swfdec_buffer_queue_flush:
+ * @queue: a #SwfdecBufferQueue
+ * @n_bytes: amount of bytes to flush from the queue
+ *
+ * Removes the first @n_bytes bytes from the queue.
+ */
+void
+swfdec_buffer_queue_flush (SwfdecBufferQueue *queue, gsize n_bytes)
+{
+  g_return_if_fail (queue != NULL);
+  g_return_if_fail (n_bytes <= queue->depth);
+
+  queue->depth -= n_bytes;
+  queue->offset += n_bytes;
+
+  SWFDEC_LOG ("flushing %zu bytes (%zu left)", n_bytes, queue->depth);
+
+  while (n_bytes > 0) {
+    SwfdecBuffer *buffer = queue->first_buffer->data;
+
+    if (buffer->length <= n_bytes) {
+      n_bytes -= buffer->length;
+      queue->first_buffer = g_slist_remove (queue->first_buffer, buffer);
+    } else {
+      queue->first_buffer->data = swfdec_buffer_new_subbuffer (buffer, 
+	  n_bytes, buffer->length - n_bytes);
+      n_bytes = 0;
+    }
+    swfdec_buffer_unref (buffer);
+  }
+  if (queue->first_buffer == NULL)
+    queue->last_buffer = NULL;
+}
+
+/**
  * swfdec_buffer_queue_clear:
  * @queue: a #SwfdecBufferQueue
  *
@@ -397,9 +434,12 @@ swfdec_buffer_queue_clear (SwfdecBufferQueue *queue)
 {
   g_return_if_fail (queue != NULL);
 
-  g_list_foreach (queue->buffers, (GFunc) swfdec_buffer_unref, NULL);
-  g_list_free (queue->buffers);
-  memset (queue, 0, sizeof (SwfdecBufferQueue));
+  g_slist_foreach (queue->first_buffer, (GFunc) swfdec_buffer_unref, NULL);
+  g_slist_free (queue->first_buffer);
+  queue->first_buffer = NULL;
+  queue->last_buffer = NULL;
+  queue->depth = 0;
+  queue->offset = 0;
 }
 
 /**
@@ -421,32 +461,57 @@ swfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer)
     swfdec_buffer_unref (buffer);
     return;
   }
-  queue->buffers = g_list_append (queue->buffers, buffer);
+  queue->last_buffer = g_slist_append (queue->last_buffer, buffer);
+  if (queue->first_buffer == NULL) {
+    queue->first_buffer = queue->last_buffer;
+  } else {
+    queue->last_buffer = queue->last_buffer->next;
+  }
   queue->depth += buffer->length;
 }
 
 /**
- * swfdec_buffer_queue_pull_buffer:
- * @queue: a #SwfdecBufferQueue
+ * swfdec_buffer_queue_peek:
+ * @queue: a #SwfdecBufferQueue to read from
+ * @length: amount of bytes to peek
  *
- * Pulls the first buffer out of @queue and returns it. This function is 
- * equivalent to calling swfdec_buffer_queue_pull() with the size of the
- * first buffer in it.
+ * Creates a new buffer with the first @length bytes from @queue, but unlike 
+ * swfdec_buffer_queue_pull(), does not remove them from @queue.
  *
- * Returns: The first buffer in @queue or %NULL if @queue is empty.
+ * Returns: NULL if the requested amount of data wasn't available or a new 
+ *          readonly #SwfdecBuffer. Use swfdec_buffer_unref() after use.
  **/
 SwfdecBuffer *
-swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue)
+swfdec_buffer_queue_peek (SwfdecBufferQueue * queue, gsize length)
 {
+  GSList *g;
+  SwfdecBuffer *newbuffer;
   SwfdecBuffer *buffer;
 
   g_return_val_if_fail (queue != NULL, NULL);
-  if (queue->buffers == NULL)
+
+  if (queue->depth < length)
     return NULL;
 
-  buffer = queue->buffers->data;
+  SWFDEC_LOG ("peeking %zu, %zu available", length, queue->depth);
+
+  g = queue->first_buffer;
+  buffer = g->data;
+  if (buffer->length >= length) {
+    newbuffer = swfdec_buffer_new_subbuffer (buffer, 0, length);
+  } else {
+    gsize offset;
+    newbuffer = swfdec_buffer_new_and_alloc (length);
+    for (offset = 0; offset < length; offset += buffer->length) {
+      gsize amount = MIN (length - offset, buffer->length);
+      oil_copy_u8 (newbuffer->data + offset, buffer->data, amount);
+      offset += amount;
+      g = g->next;
+      buffer = g->data;
+    }
+  }
 
-  return swfdec_buffer_queue_pull (queue, buffer->length);
+  return newbuffer;
 }
 
 /**
@@ -464,64 +529,16 @@ swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue)
 SwfdecBuffer *
 swfdec_buffer_queue_pull (SwfdecBufferQueue * queue, guint length)
 {
-  GList *g;
-  SwfdecBuffer *newbuffer;
-  SwfdecBuffer *buffer;
-  SwfdecBuffer *subbuffer;
+  SwfdecBuffer *ret;
 
   g_return_val_if_fail (queue != NULL, NULL);
-  g_return_val_if_fail (length > 0, NULL);
 
-  if (queue->depth < length) 
+  ret = swfdec_buffer_queue_peek (queue, length);
+  if (ret == NULL)
     return NULL;
 
-  /* FIXME: This function should share code with swfdec_buffer_queue_peek */
-  SWFDEC_LOG ("pulling %d, %d available", length, queue->depth);
-
-  g = g_list_first (queue->buffers);
-  buffer = g->data;
-
-  if (buffer->length > length) {
-    newbuffer = swfdec_buffer_new_subbuffer (buffer, 0, length);
-
-    subbuffer = swfdec_buffer_new_subbuffer (buffer, length,
-        buffer->length - length);
-    g->data = subbuffer;
-    swfdec_buffer_unref (buffer);
-  } else if (buffer->length == length) {
-    queue->buffers = g_list_remove (queue->buffers, buffer);
-    newbuffer = buffer;
-  } else {
-    guint offset = 0;
-
-    newbuffer = swfdec_buffer_new_and_alloc (length);
-
-    while (offset < length) {
-      g = g_list_first (queue->buffers);
-      buffer = g->data;
-
-      if (buffer->length > length - offset) {
-        guint n = length - offset;
-
-        oil_copy_u8 (newbuffer->data + offset, buffer->data, n);
-        subbuffer = swfdec_buffer_new_subbuffer (buffer, n, buffer->length - n);
-        g->data = subbuffer;
-        swfdec_buffer_unref (buffer);
-        offset += n;
-      } else {
-        oil_copy_u8 (newbuffer->data + offset, buffer->data, buffer->length);
-
-        queue->buffers = g_list_delete_link (queue->buffers, g);
-        offset += buffer->length;
-	swfdec_buffer_unref (buffer);
-      }
-    }
-  }
-
-  queue->depth -= length;
-  queue->offset += length;
-
-  return newbuffer;
+  swfdec_buffer_queue_flush (queue, length);
+  return ret;
 }
 
 /**
@@ -541,63 +558,38 @@ swfdec_buffer_queue_peek_buffer (SwfdecBufferQueue * queue)
   SwfdecBuffer *buffer;
 
   g_return_val_if_fail (queue != NULL, NULL);
-  if (queue->buffers == NULL)
+
+  if (queue->first_buffer == NULL)
     return NULL;
 
-  buffer = queue->buffers->data;
+  buffer = queue->first_buffer->data;
+  SWFDEC_LOG ("peeking one buffer: %zu bytes, %zu available", buffer->length, queue->depth);
 
-  return swfdec_buffer_queue_peek (queue, buffer->length);
+  return swfdec_buffer_ref (buffer);
 }
 
 /**
- * swfdec_buffer_queue_peek:
- * @queue: a #SwfdecBufferQueue to read from
- * @length: amount of bytes to peek
+ * swfdec_buffer_queue_pull_buffer:
+ * @queue: a #SwfdecBufferQueue
  *
- * Creates a new buffer with the first @length bytes from @queue, but unlike 
- * swfdec_buffer_queue_pull(), does not remove them from @queue.
+ * Pulls the first buffer out of @queue and returns it. This function is 
+ * equivalent to calling swfdec_buffer_queue_pull() with the size of the
+ * first buffer in it.
  *
- * Returns: NULL if the requested amount of data wasn't available or a new 
- *          readonly #SwfdecBuffer. Use swfdec_buffer_unref() after use.
+ * Returns: The first buffer in @queue or %NULL if @queue is empty.
  **/
 SwfdecBuffer *
-swfdec_buffer_queue_peek (SwfdecBufferQueue * queue, guint length)
+swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue *queue)
 {
-  GList *g;
-  SwfdecBuffer *newbuffer;
   SwfdecBuffer *buffer;
-  guint offset = 0;
 
-  g_return_val_if_fail (length > 0, NULL);
-
-  if (queue->depth < length)
-    return NULL;
-
-  SWFDEC_LOG ("peeking %d, %d available", length, queue->depth);
-
-  g = g_list_first (queue->buffers);
-  buffer = g->data;
-  if (buffer->length > length) {
-    newbuffer = swfdec_buffer_new_subbuffer (buffer, 0, length);
-  } else {
-    newbuffer = swfdec_buffer_new_and_alloc (length);
-    while (offset < length) {
-      buffer = g->data;
-
-      if (buffer->length > length - offset) {
-        int n = length - offset;
+  g_return_val_if_fail (queue != NULL, NULL);
 
-        oil_copy_u8 (newbuffer->data + offset, buffer->data, n);
-        offset += n;
-      } else {
-        oil_copy_u8 (newbuffer->data + offset, buffer->data, buffer->length);
-        offset += buffer->length;
-      }
-      g = g_list_next (g);
-    }
-  }
+  buffer = swfdec_buffer_queue_peek_buffer (queue);
+  if (buffer)
+    swfdec_buffer_queue_flush (queue, buffer->length);
 
-  return newbuffer;
+  return buffer;
 }
 
 /**
diff --git a/swfdec/swfdec_buffer.h b/swfdec/swfdec_buffer.h
index 84e4bd6..1b851b6 100644
--- a/swfdec/swfdec_buffer.h
+++ b/swfdec/swfdec_buffer.h
@@ -48,11 +48,12 @@ GType swfdec_buffer_get_type  (void);
 struct _SwfdecBufferQueue
 {
   /*< private >*/
-  GList *buffers;
-  guint depth;
-  guint offset;
+  GSList *	first_buffer;		/* pointer to first buffer */
+  GSList *	last_buffer;		/* pointer to last buffer (for fast appending) */
+  gsize		depth;			/* amount of bytes in the queue */
+  gsize		offset;			/* amount of data already flushed out of the queue */
   
-  int ref_count;
+  int		ref_count;
 };
 
 #define SWFDEC_TYPE_BUFFER_QUEUE swfdec_buffer_queue_get_type()
@@ -70,15 +71,16 @@ SwfdecBuffer *swfdec_buffer_get_super (SwfdecBuffer *buffer);
 void swfdec_buffer_unref (SwfdecBuffer * buffer);
 
 SwfdecBufferQueue *swfdec_buffer_queue_new (void);
+void swfdec_buffer_queue_flush (SwfdecBufferQueue *queue, gsize n_bytes);
 void swfdec_buffer_queue_clear (SwfdecBufferQueue *queue);
-guint swfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue);
-guint swfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue);
+gsize swfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue);
+gsize swfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue);
 void swfdec_buffer_queue_push (SwfdecBufferQueue * queue,
     SwfdecBuffer * buffer);
-SwfdecBuffer *swfdec_buffer_queue_pull (SwfdecBufferQueue * queue, guint length);
+SwfdecBuffer *swfdec_buffer_queue_pull (SwfdecBufferQueue * queue, gsize length);
 SwfdecBuffer *swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue);
 char *swfdec_buffer_queue_pull_text (SwfdecBufferQueue *queue, guint version);
-SwfdecBuffer *swfdec_buffer_queue_peek (SwfdecBufferQueue * queue, guint length);
+SwfdecBuffer *swfdec_buffer_queue_peek (SwfdecBufferQueue * queue, gsize length);
 SwfdecBuffer *swfdec_buffer_queue_peek_buffer (SwfdecBufferQueue * queue);
 SwfdecBufferQueue *swfdec_buffer_queue_ref (SwfdecBufferQueue * queue);
 void swfdec_buffer_queue_unref (SwfdecBufferQueue * queue);


More information about the Swfdec-commits mailing list