Merge remote-tracking branch 'gvdb/master'
[platform/upstream/glib.git] / glib / gbuffer.c
1 /*
2  * Copyright © 2009, 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include "gbuffer.h"
25
26 #include <glib/gstrfuncs.h>
27 #include <glib/gatomic.h>
28 #include <glib/gmem.h>
29
30
31 typedef struct
32 {
33   GBuffer buffer;
34
35   GDestroyNotify user_destroy;
36   gpointer user_data;
37 } GUserNotifyBuffer;
38
39 static void
40 g_buffer_free_gfree (GBuffer *buffer)
41 {
42   g_free ((gpointer) buffer->data);
43   g_slice_free (GBuffer, buffer);
44 }
45
46 /* < private >
47  * g_buffer_new_from_data:
48  * @data: the data to be used for the buffer
49  * @size: the size of @data
50  * @returns: a reference to a new #GBuffer
51  *
52  * Creates a new #GBuffer from @data.
53  *
54  * @data is copied.
55  */
56
57 GBuffer *
58 g_buffer_new_from_data (gconstpointer data,
59                         gsize         size)
60 {
61   GBuffer *buffer;
62
63   buffer = g_slice_new (GBuffer);
64   buffer->data = g_memdup (data, size);
65   buffer->size = size;
66   buffer->free_func = g_buffer_free_gfree;
67   buffer->ref_count = 1;
68
69   return buffer;
70 }
71
72 /* < private >
73  * g_buffer_new_take_data:
74  * @data: the data to be used for the buffer
75  * @size: the size of @data
76  * returns: a reference to a new #GBuffer
77  *
78  * Creates a new #GBuffer from @data.
79  *
80  * @data must have been created by a call to g_malloc(), g_malloc0() or
81  * g_realloc() or by one of the many functions that wrap these calls
82  * (such as g_new(), g_strdup(), etc).
83  *
84  * After this call, @data belongs to the buffer and may no longer be
85  * modified by the caller.  g_free() will be called on @data when the
86  * buffer is no longer in use.
87  */
88 GBuffer *
89 g_buffer_new_take_data (gpointer data,
90                         gsize    size)
91 {
92   GBuffer *buffer;
93
94   buffer = g_slice_new (GBuffer);
95   buffer->data = data;
96   buffer->size = size;
97   buffer->free_func = g_buffer_free_gfree;
98   buffer->ref_count = 1;
99
100   return buffer;
101 }
102
103 static void
104 g_buffer_free (GBuffer *buffer)
105 {
106   g_slice_free (GBuffer, buffer);
107 }
108
109 /* < private >
110  * g_buffer_new_from_static_data:
111  * @data: the data to be used for the buffer
112  * @size: the size of @data
113  * @returns: a reference to a new #GBuffer
114  *
115  * Creates a new #GBuffer from static data.
116  *
117  * @data must be static (ie: never modified or freed).
118  */
119 GBuffer *
120 g_buffer_new_from_static_data (gconstpointer data,
121                                gsize         size)
122 {
123   GBuffer *buffer;
124
125   buffer = g_slice_new (GBuffer);
126   buffer->data = data;
127   buffer->size = size;
128   buffer->free_func = g_buffer_free;
129   buffer->ref_count = 1;
130
131   return buffer;
132 }
133
134 static void
135 g_buffer_free_usernotify (GBuffer *buffer)
136 {
137   GUserNotifyBuffer *ubuffer = (GUserNotifyBuffer *) buffer;
138
139   ubuffer->user_destroy (ubuffer->user_data);
140   g_slice_free (GUserNotifyBuffer, ubuffer);
141 }
142
143 /* < private >
144  * g_buffer_new_from_pointer:
145  * @data: the data to be used for the buffer
146  * @size: the size of @data
147  * @notify: the function to call to release the data
148  * @user_data: the data to pass to @notify
149  * @returns: a reference to a new #GBuffer
150  *
151  * Creates a #GBuffer from @data.
152  *
153  * When the last reference is dropped, @notify will be called on
154  * @user_data.
155  *
156  * @data must not be modified after this call is made, until @notify has
157  * been called to indicate that the buffer is no longer in use.
158  */
159 GBuffer *
160 g_buffer_new_from_pointer (gconstpointer  data,
161                            gsize          size,
162                            GDestroyNotify notify,
163                            gpointer       user_data)
164 {
165   GUserNotifyBuffer *ubuffer;
166
167   ubuffer = g_slice_new (GUserNotifyBuffer);
168   ubuffer->buffer.data = data;
169   ubuffer->buffer.size = size;
170   ubuffer->buffer.free_func = g_buffer_free_usernotify;
171   ubuffer->buffer.ref_count = 1;
172   ubuffer->user_destroy = notify;
173   ubuffer->user_data = user_data;
174
175   return (GBuffer *) ubuffer;
176 }
177
178 /* < private >
179  * g_buffer_ref:
180  * @buffer: a #GBuffer
181  * @returns: @buffer
182  *
183  * Increase the reference count on @buffer.
184  */
185 GBuffer *
186 g_buffer_ref (GBuffer *buffer)
187 {
188   g_atomic_int_inc (&buffer->ref_count);
189
190   return buffer;
191 }
192
193 /* < private >
194  * g_buffer_unref:
195  * @buffer: a #GBuffer
196  *
197  * Releases a reference on @buffer.  This may result in the buffer being
198  * freed.
199  */
200 void
201 g_buffer_unref (GBuffer *buffer)
202 {
203   if (g_atomic_int_dec_and_test (&buffer->ref_count))
204     if (buffer->free_func != NULL)
205       buffer->free_func (buffer);
206 }