⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_buffer.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
字号:
/* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> *		 2005-2006 Eric Anholt <eric@anholt.net> *		 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor,  * Boston, MA  02110-1301  USA */#ifndef HAVE_CONFIG_H#include "config.h"#endif#include <swfdec_buffer.h>#include <glib.h>#include <string.h>#include <swfdec_debug.h>#include <liboil/liboil.h>/*** gtk-doc ***//** * SECTION:SwfdecBuffer * @title: SwfdecBuffer * @short_description: memory region handling * * To allow for easy sharing of memory regions, #SwfdecBuffer was created.  * Every buffer refers to a memory region and its size and takes care of  * freeing that region when the buffer is no longer needed. They are  * reference countedto make it easy to refer to the same region from various * independant parts of your code. Buffers also support some advanced  * functionalities like extracting parts of the buffer using  * swfdec_buffer_new_subbuffer() or using mmapped files with  * swfdec_buffer_new_from_file() without the need for a different API. * * A #SwfdecBufferQueue is a queue of continuous buffers that allows reading * its data in chunks of pre-defined sizes. It is used to transform a data  * stream that was provided by buffers of random sizes to buffers of the right * size. *//*** SwfdecBuffer ***//** * swfdec_buffer_new: * * Creates a new #SwfdecBuffer to be filled by the user. Use like this: * <informalexample><programlisting>SwfdecBuffer *buffer = swfdec_buffer_new (); * buffer->data = mydata; * buffer->length = mydata_length; * buffer->free = mydata_freefunc;</programlisting></informalexample> * * Returns: a new #SwfdecBuffer referencing nothing. **/SwfdecBuffer *swfdec_buffer_new (void){  SwfdecBuffer *buffer;  buffer = g_new0 (SwfdecBuffer, 1);  buffer->ref_count = 1;  return buffer;}static voidswfdec_buffer_free_mem (SwfdecBuffer * buffer, void *priv){  g_free (buffer->data);}/** * swfdec_buffer_new_and_alloc: * @size: amount of bytes to allocate * * Creates a new buffer and allocates new memory of @size bytes to be used with  * the buffer. * * Returns: a new #SwfdecBuffer with buffer->data pointing to new data **/SwfdecBuffer *swfdec_buffer_new_and_alloc (unsigned int size){  SwfdecBuffer *buffer = swfdec_buffer_new ();  buffer->data = g_malloc (size);  buffer->length = size;  buffer->free = swfdec_buffer_free_mem;  return buffer;}/** * swfdec_buffer_new_and_alloc0: * @size: amount of bytes to allocate * * Createsa new buffer just like swfdec_buffer_new_and_alloc(), but ensures  * that the returned data gets initialized to be 0. * * Returns: a new #SwfdecBuffer with buffer->data pointing to new data **/SwfdecBuffer *swfdec_buffer_new_and_alloc0 (unsigned int size){  SwfdecBuffer *buffer = swfdec_buffer_new ();  buffer->data = g_malloc0 (size);  buffer->length = size;  buffer->free = swfdec_buffer_free_mem;  return buffer;}/** * swfdec_buffer_new_for_data: * @data: memory region allocated with g_malloc() * @size: size of @data in bytes * * Takes ownership of @data and creates a new buffer managing it. * * Returns: a new #SwfdecBuffer pointing to @data **/SwfdecBuffer *swfdec_buffer_new_for_data (unsigned char *data, unsigned int size){  SwfdecBuffer *buffer;    g_return_val_if_fail (data != NULL, NULL);  g_return_val_if_fail (size > 0, NULL);  buffer = swfdec_buffer_new ();  buffer->data = data;  buffer->length = size;  buffer->free = swfdec_buffer_free_mem;  return buffer;}static voidswfdec_buffer_free_subbuffer (SwfdecBuffer * buffer, void *priv){  swfdec_buffer_unref (buffer->parent);}/** * swfdec_buffer_new_subbuffer: * @buffer: #SwfdecBuffer managing the region of memory * @offset: starting offset into data * @length: amount of bytes to manage * * Creates a #SwfdecBuffer for managing a partial section of the memory pointed * to by @buffer. * * Returns: a new #SwfdecBuffer managing the indicated region. **/SwfdecBuffer *swfdec_buffer_new_subbuffer (SwfdecBuffer * buffer, unsigned int offset, unsigned int 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 (buffer->parent) {    swfdec_buffer_ref (buffer->parent);    subbuffer->parent = buffer->parent;  } else {    swfdec_buffer_ref (buffer);    subbuffer->parent = buffer;  }  g_assert (subbuffer->parent->parent == NULL);  subbuffer->data = buffer->data + offset;  subbuffer->length = length;  subbuffer->free = swfdec_buffer_free_subbuffer;  return subbuffer;}static voidswfdec_buffer_free_mapped (SwfdecBuffer * buffer, void *priv){  g_mapped_file_free (priv);}/** * swfdec_buffer_new_from_file: * @filename: file to read * @error: return location for a #GError or %NULL * * Tries to create a buffer for the given @filename using a #GMappedFile. If * the creation fails, %NULL is returned and @error is set. The error can be * any of the errors that are valid from g_mapped_file_new(). * * Returns: a new #SwfdecBuffer or %NULL on failure **/SwfdecBuffer *swfdec_buffer_new_from_file (const char *filename, GError **error){  GMappedFile *file;  SwfdecBuffer *buffer;  g_return_val_if_fail (filename != NULL, NULL);  file = g_mapped_file_new (filename, FALSE, error);  if (file == NULL) {    return NULL;  }  buffer = swfdec_buffer_new ();  buffer->data = (unsigned char *) g_mapped_file_get_contents (file),   buffer->length = g_mapped_file_get_length (file);  buffer->free = swfdec_buffer_free_mapped;  buffer->priv = file;  return buffer;}/** * swfdec_buffer_ref: * @buffer: a #SwfdecBuffer * * increases the reference count of @buffer by one. * * Returns: The passed in @buffer. **/SwfdecBuffer *swfdec_buffer_ref (SwfdecBuffer * buffer){  g_return_val_if_fail (buffer != NULL, NULL);  g_return_val_if_fail (buffer->ref_count > 0, NULL);  buffer->ref_count++;  return buffer;}/** * swfdec_buffer_unref: * @buffer: a #SwfdecBuffer * * Decreases the reference count of @buffer by one. If no reference to this * buffer exists anymore, the buffer and the memory it manages are freed. **/voidswfdec_buffer_unref (SwfdecBuffer * buffer){  g_return_if_fail (buffer != NULL);  g_return_if_fail (buffer->ref_count > 0);  buffer->ref_count--;  if (buffer->ref_count == 0) {    if (buffer->free)      buffer->free (buffer, buffer->priv);    g_free (buffer);  }}/*** SwfdecBuffer ***/SwfdecBufferQueue *swfdec_buffer_queue_new (void){  return g_new0 (SwfdecBufferQueue, 1);}intswfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue){  return queue->depth;}intswfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue){  return queue->offset;}voidswfdec_buffer_queue_clear (SwfdecBufferQueue *queue){  g_list_foreach (queue->buffers, (GFunc) swfdec_buffer_unref, NULL);  g_list_free (queue->buffers);  memset (queue, 0, sizeof (SwfdecBufferQueue));}voidswfdec_buffer_queue_free (SwfdecBufferQueue * queue){  swfdec_buffer_queue_clear (queue);  g_free (queue);}voidswfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer){  g_return_if_fail (queue != NULL);  g_return_if_fail (buffer != NULL);  if (buffer->length == 0) {    swfdec_buffer_unref (buffer);    return;  }  queue->buffers = g_list_append (queue->buffers, buffer);  queue->depth += buffer->length;}SwfdecBuffer *swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue){  SwfdecBuffer *buffer;  g_return_val_if_fail (queue != NULL, NULL);  if (queue->buffers == NULL)    return NULL;  buffer = queue->buffers->data;  return swfdec_buffer_queue_pull (queue, buffer->length);}SwfdecBuffer *swfdec_buffer_queue_pull (SwfdecBufferQueue * queue, unsigned int length){  GList *g;  SwfdecBuffer *newbuffer;  SwfdecBuffer *buffer;  SwfdecBuffer *subbuffer;  g_return_val_if_fail (queue != NULL, NULL);  g_return_val_if_fail (length > 0, NULL);  if (queue->depth < length)     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 {    unsigned int 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) {        unsigned int 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_peek: * @queue: a #SwfdecBufferQueue to read from * @length: amount of bytes to peek * * Creates a new buffer with the first @length bytes from @queue, but unlike  * swfdec_buffer_queue_pull(), does not remove them from @queue. * * 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_peek (SwfdecBufferQueue * queue, unsigned int length){  GList *g;  SwfdecBuffer *newbuffer;  SwfdecBuffer *buffer;  unsigned int 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;        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);    }  }  return newbuffer;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -