glib/glib/gbuffer.c
2010-02-07 15:43:06 -05:00

208 lines
4.9 KiB
C

/*
* Copyright © 2009, 2010 Codethink Limited
*
* 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 of the licence, 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
#include "gbuffer.h"
#include <glib/gstrfuncs.h>
#include <glib/gatomic.h>
#include <glib/gmem.h>
#include "galias.h"
typedef struct
{
GBuffer buffer;
GDestroyNotify user_destroy;
gpointer user_data;
} GUserNotifyBuffer;
static void
g_buffer_free_gfree (GBuffer *buffer)
{
g_free ((gpointer) buffer->data);
g_slice_free (GBuffer, buffer);
}
/* < private >
* g_buffer_new_from_data:
* @data: the data to be used for the buffer
* @size: the size of @data
* @returns: a reference to a new #GBuffer
*
* Creates a new #GBuffer from @data.
*
* @data is copied.
*/
GBuffer *
g_buffer_new_from_data (gconstpointer data,
gsize size)
{
GBuffer *buffer;
buffer = g_slice_new (GBuffer);
buffer->data = g_memdup (data, size);
buffer->size = size;
buffer->free_func = g_buffer_free_gfree;
buffer->ref_count = 1;
return buffer;
}
/* < private >
* g_buffer_new_take_data:
* @data: the data to be used for the buffer
* @size: the size of @data
* returns: a reference to a new #GBuffer
*
* Creates a new #GBuffer from @data.
*
* @data must have been created by a call to g_malloc(), g_malloc0() or
* g_realloc() or by one of the many functions that wrap these calls
* (such as g_new(), g_strdup(), etc).
*
* After this call, @data belongs to the buffer and may no longer be
* modified by the caller. g_free() will be called on @data when the
* buffer is no longer in use.
*/
GBuffer *
g_buffer_new_take_data (gpointer data,
gsize size)
{
GBuffer *buffer;
buffer = g_slice_new (GBuffer);
buffer->data = data;
buffer->size = size;
buffer->free_func = g_buffer_free_gfree;
buffer->ref_count = 1;
return buffer;
}
static void
g_buffer_free (GBuffer *buffer)
{
g_slice_free (GBuffer, buffer);
}
/* < private >
* g_buffer_new_from_static_data:
* @data: the data to be used for the buffer
* @size: the size of @data
* @returns: a reference to a new #GBuffer
*
* Creates a new #GBuffer from static data.
*
* @data must be static (ie: never modified or freed).
*/
GBuffer *
g_buffer_new_from_static_data (gconstpointer data,
gsize size)
{
GBuffer *buffer;
buffer = g_slice_new (GBuffer);
buffer->data = data;
buffer->size = size;
buffer->free_func = g_buffer_free;
buffer->ref_count = 1;
return buffer;
}
static void
g_buffer_free_usernotify (GBuffer *buffer)
{
GUserNotifyBuffer *ubuffer = (GUserNotifyBuffer *) buffer;
ubuffer->user_destroy (ubuffer->user_data);
g_slice_free (GBuffer, buffer);
}
/* < private >
* g_buffer_new_from_pointer:
* @data: the data to be used for the buffer
* @size: the size of @data
* @notify: the function to call to release the data
* @user_data: the data to pass to @notify
* @returns: a reference to a new #GBuffer
*
* Creates a #GBuffer from @data.
*
* When the last reference is dropped, @notify will be called on
* @user_data.
*
* @data must not be modified after this call is made, until @notify has
* been called to indicate that the buffer is no longer in use.
*/
GBuffer *
g_buffer_new_from_pointer (gconstpointer data,
gsize size,
GDestroyNotify notify,
gpointer user_data)
{
GUserNotifyBuffer *ubuffer;
ubuffer = g_slice_new (GUserNotifyBuffer);
ubuffer->buffer.data = data;
ubuffer->buffer.size = size;
ubuffer->buffer.free_func = g_buffer_free_usernotify;
ubuffer->buffer.ref_count = 1;
ubuffer->user_destroy = notify;
ubuffer->user_data = user_data;
return (GBuffer *) ubuffer;
}
/* < private >
* g_buffer_ref:
* @buffer: a #GBuffer
* @returns: @buffer
*
* Increase the reference count on @buffer.
*/
GBuffer *
g_buffer_ref (GBuffer *buffer)
{
g_atomic_int_inc (&buffer->ref_count);
return buffer;
}
/* < private >
* g_buffer_unref:
* @buffer: a #GBuffer
*
* Releases a reference on @buffer. This may result in the buffer being
* freed.
*/
void
g_buffer_unref (GBuffer *buffer)
{
if (g_atomic_int_dec_and_test (&buffer->ref_count))
if (buffer->free_func != NULL)
buffer->free_func (buffer);
}