Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2009, 2010 Codethink Limited
3 : : * Copyright © 2011 Collabora Ltd.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General Public
18 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Ryan Lortie <desrt@desrt.ca>
21 : : * Stef Walter <stefw@collabora.co.uk>
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : #include "gbytes.h"
27 : :
28 : : #include <glib/garray.h>
29 : : #include <glib/gstrfuncs.h>
30 : : #include <glib/gatomic.h>
31 : : #include <glib/gtestutils.h>
32 : : #include <glib/gmem.h>
33 : : #include <glib/gmessages.h>
34 : : #include <glib/grefcount.h>
35 : :
36 : : #include <string.h>
37 : :
38 : : #if GLIB_SIZEOF_VOID_P == 8
39 : : # define G_BYTES_MAX_INLINE (128 - sizeof(GBytesInline))
40 : : #else
41 : : # define G_BYTES_MAX_INLINE (64 - sizeof(GBytesInline))
42 : : #endif
43 : :
44 : : /**
45 : : * GBytes: (copy-func g_bytes_ref) (free-func g_bytes_unref)
46 : : *
47 : : * A simple reference counted data type representing an immutable sequence of
48 : : * zero or more bytes from an unspecified origin.
49 : : *
50 : : * The purpose of a `GBytes` is to keep the memory region that it holds
51 : : * alive for as long as anyone holds a reference to the bytes. When
52 : : * the last reference count is dropped, the memory is released. Multiple
53 : : * unrelated callers can use byte data in the `GBytes` without coordinating
54 : : * their activities, resting assured that the byte data will not change or
55 : : * move while they hold a reference.
56 : : *
57 : : * A `GBytes` can come from many different origins that may have
58 : : * different procedures for freeing the memory region. Examples are
59 : : * memory from [func@GLib.malloc], from memory slices, from a
60 : : * [struct@GLib.MappedFile] or memory from other allocators.
61 : : *
62 : : * `GBytes` work well as keys in [struct@GLib.HashTable]. Use
63 : : * [method@GLib.Bytes.equal] and [method@GLib.Bytes.hash] as parameters to
64 : : * [func@GLib.HashTable.new] or [func@GLib.HashTable.new_full].
65 : : * `GBytes` can also be used as keys in a [struct@GLib.Tree] by passing the
66 : : * [method@GLib.Bytes.compare] function to [ctor@GLib.Tree.new].
67 : : *
68 : : * The data pointed to by this bytes must not be modified. For a mutable
69 : : * array of bytes see [struct@GLib.ByteArray]. Use
70 : : * [method@GLib.Bytes.unref_to_array] to create a mutable array for a `GBytes`
71 : : * sequence. To create an immutable `GBytes` from a mutable
72 : : * [struct@GLib.ByteArray], use the [func@GLib.ByteArray.free_to_bytes]
73 : : * function.
74 : : *
75 : : * Since: 2.32
76 : : **/
77 : :
78 : : /* Keep in sync with glib/tests/bytes.c */
79 : : struct _GBytes
80 : : {
81 : : gconstpointer data; /* may be NULL iff (size == 0) */
82 : : gsize size; /* may be 0 */
83 : : gatomicrefcount ref_count;
84 : : GDestroyNotify free_func;
85 : : gpointer user_data;
86 : : };
87 : :
88 : : typedef struct
89 : : {
90 : : GBytes bytes;
91 : : /* Despite no guarantee about alignment in GBytes, it is nice to
92 : : * provide that to ensure that any code which predates support
93 : : * for inline data continues to work without disruption. malloc()
94 : : * on glibc systems would guarantee 2*sizeof(void*) aligned
95 : : * allocations and this matches that.
96 : : */
97 : : gsize padding;
98 : : guint8 inline_data[];
99 : : } GBytesInline;
100 : :
101 : : G_STATIC_ASSERT (G_STRUCT_OFFSET (GBytesInline, inline_data) == (6 * GLIB_SIZEOF_VOID_P));
102 : :
103 : : /**
104 : : * g_bytes_new:
105 : : * @data: (transfer none) (array length=size) (element-type guint8) (nullable):
106 : : * the data to be used for the bytes
107 : : * @size: the size of @data
108 : : *
109 : : * Creates a new [struct@GLib.Bytes] from @data.
110 : : *
111 : : * @data is copied. If @size is 0, @data may be `NULL`.
112 : : *
113 : : * As an optimization, [ctor@GLib.Bytes.new] may avoid an extra allocation by
114 : : * copying the data within the resulting bytes structure if sufficiently small
115 : : * (since GLib 2.84).
116 : : *
117 : : * Returns: (transfer full): a new [struct@GLib.Bytes]
118 : : * Since: 2.32
119 : : */
120 : : GBytes *
121 : 66758 : g_bytes_new (gconstpointer data,
122 : : gsize size)
123 : : {
124 : 66758 : g_return_val_if_fail (data != NULL || size == 0, NULL);
125 : :
126 : 66758 : if (data == NULL || size == 0)
127 : : {
128 : 6 : g_assert (data != NULL || size == 0);
129 : :
130 : 6 : return g_bytes_new_with_free_func (NULL, size, NULL, NULL);
131 : : }
132 : :
133 : 66752 : if (size <= G_BYTES_MAX_INLINE)
134 : : {
135 : : GBytesInline *bytes;
136 : :
137 : 8289 : bytes = g_malloc (sizeof *bytes + size);
138 : 8289 : bytes->bytes.data = bytes->inline_data;
139 : 8289 : bytes->bytes.size = size;
140 : 8289 : bytes->bytes.free_func = NULL;
141 : 8289 : bytes->bytes.user_data = NULL;
142 : 8289 : g_atomic_ref_count_init (&bytes->bytes.ref_count);
143 : :
144 : 8289 : memcpy (bytes->inline_data, data, size);
145 : :
146 : 8289 : return (GBytes *)bytes;
147 : : }
148 : :
149 : 58463 : return g_bytes_new_take (g_memdup2 (data, size), size);
150 : : }
151 : :
152 : : /**
153 : : * g_bytes_new_take:
154 : : * @data: (transfer full) (array length=size) (element-type guint8) (nullable):
155 : : * the data to be used for the bytes
156 : : * @size: the size of @data
157 : : *
158 : : * Creates a new [struct@GLib.Bytes] from @data.
159 : : *
160 : : * After this call, @data belongs to the `GBytes` and may no longer be
161 : : * modified by the caller. The memory of @data has to be dynamically
162 : : * allocated and will eventually be freed with [func@GLib.free].
163 : : *
164 : : * For creating `GBytes` with memory from other allocators, see
165 : : * [ctor@GLib.Bytes.new_with_free_func].
166 : : *
167 : : * @data may be `NULL` if @size is 0.
168 : : *
169 : : * Returns: (transfer full): a new [struct@GLib.Bytes]
170 : : * Since: 2.32
171 : : */
172 : : GBytes *
173 : 69654 : g_bytes_new_take (gpointer data,
174 : : gsize size)
175 : : {
176 : 69654 : return g_bytes_new_with_free_func (data, size, g_free, data);
177 : : }
178 : :
179 : :
180 : : /**
181 : : * g_bytes_new_static: (skip)
182 : : * @data: (transfer full) (array length=size) (element-type guint8) (nullable):
183 : : * the data to be used for the bytes
184 : : * @size: the size of @data
185 : : *
186 : : * Creates a new [struct@GLib.Bytes] from static data.
187 : : *
188 : : * @data must be static (ie: never modified or freed). It may be `NULL` if @size
189 : : * is 0.
190 : : *
191 : : * Returns: (transfer full): a new [struct@GLib.Bytes]
192 : : * Since: 2.32
193 : : */
194 : : GBytes *
195 : 1730 : g_bytes_new_static (gconstpointer data,
196 : : gsize size)
197 : : {
198 : 1730 : return g_bytes_new_with_free_func (data, size, NULL, NULL);
199 : : }
200 : :
201 : : /**
202 : : * g_bytes_new_with_free_func: (skip)
203 : : * @data: (array length=size) (element-type guint8) (nullable):
204 : : * the data to be used for the bytes
205 : : * @size: the size of @data
206 : : * @free_func: the function to call to release the data
207 : : * @user_data: data to pass to @free_func
208 : : *
209 : : * Creates a [struct@GLib.Bytes] from @data.
210 : : *
211 : : * When the last reference is dropped, @free_func will be called with the
212 : : * @user_data argument.
213 : : *
214 : : * @data must not be modified after this call is made until @free_func has
215 : : * been called to indicate that the bytes is no longer in use.
216 : : *
217 : : * @data may be `NULL` if @size is 0.
218 : : *
219 : : * Returns: (transfer full): a new [struct@GLib.Bytes]
220 : : * Since: 2.32
221 : : */
222 : : GBytes *
223 : 89537 : g_bytes_new_with_free_func (gconstpointer data,
224 : : gsize size,
225 : : GDestroyNotify free_func,
226 : : gpointer user_data)
227 : : {
228 : : GBytes *bytes;
229 : :
230 : 89537 : g_return_val_if_fail (data != NULL || size == 0, NULL);
231 : :
232 : 89537 : bytes = g_new (GBytes, 1);
233 : 89537 : bytes->data = data;
234 : 89537 : bytes->size = size;
235 : 89537 : bytes->free_func = free_func;
236 : 89537 : bytes->user_data = user_data;
237 : 89537 : g_atomic_ref_count_init (&bytes->ref_count);
238 : :
239 : 89537 : return (GBytes *)bytes;
240 : : }
241 : :
242 : : /**
243 : : * g_bytes_new_from_bytes: (constructor) (not method):
244 : : * @bytes: a [struct@GLib.Bytes]
245 : : * @offset: offset which subsection starts at
246 : : * @length: length of subsection
247 : : *
248 : : * Creates a [struct@GLib.Bytes] which is a subsection of another `GBytes`.
249 : : *
250 : : * The @offset + @length may not be longer than the size of @bytes.
251 : : *
252 : : * A reference to @bytes will be held by the newly created `GBytes` until
253 : : * the byte data is no longer needed.
254 : : *
255 : : * Since 2.56, if @offset is 0 and @length matches the size of @bytes, then
256 : : * @bytes will be returned with the reference count incremented by 1. If @bytes
257 : : * is a slice of another `GBytes`, then the resulting `GBytes` will reference
258 : : * the same `GBytes` instead of @bytes. This allows consumers to simplify the
259 : : * usage of `GBytes` when asynchronously writing to streams.
260 : : *
261 : : * Returns: (transfer full): a new [struct@GLib.Bytes]
262 : : * Since: 2.32
263 : : */
264 : : GBytes *
265 : 452 : g_bytes_new_from_bytes (GBytes *bytes,
266 : : gsize offset,
267 : : gsize length)
268 : : {
269 : : gchar *base;
270 : :
271 : : /* Note that length may be 0. */
272 : 452 : g_return_val_if_fail (bytes != NULL, NULL);
273 : 452 : g_return_val_if_fail (offset <= bytes->size, NULL);
274 : 452 : g_return_val_if_fail (length <= bytes->size - offset, NULL);
275 : :
276 : : /* Avoid an extra GBytes if all bytes were requested */
277 : 452 : if (offset == 0 && length == bytes->size)
278 : 1 : return g_bytes_ref (bytes);
279 : :
280 : 451 : base = (gchar *)bytes->data + offset;
281 : :
282 : : /* Avoid referencing intermediate GBytes. In practice, this should
283 : : * only loop once.
284 : : */
285 : 453 : while (bytes->free_func == (gpointer)g_bytes_unref)
286 : 2 : bytes = bytes->user_data;
287 : :
288 : 451 : g_return_val_if_fail (bytes != NULL, NULL);
289 : 451 : g_return_val_if_fail (base >= (gchar *)bytes->data, NULL);
290 : 451 : g_return_val_if_fail (base <= (gchar *)bytes->data + bytes->size, NULL);
291 : 451 : g_return_val_if_fail (length <= (gsize) (((gchar *)bytes->data + bytes->size) - base), NULL);
292 : :
293 : 451 : return g_bytes_new_with_free_func (base, length,
294 : 451 : (GDestroyNotify)g_bytes_unref, g_bytes_ref (bytes));
295 : : }
296 : :
297 : : /**
298 : : * g_bytes_get_data:
299 : : * @bytes: a [struct@GLib.Bytes]
300 : : * @size: (out) (optional): location to return size of byte data
301 : : *
302 : : * Get the byte data in the [struct@GLib.Bytes].
303 : : *
304 : : * This data should not be modified.
305 : : *
306 : : * This function will always return the same pointer for a given `GBytes`.
307 : : *
308 : : * `NULL` may be returned if @size is 0. This is not guaranteed, as the `GBytes`
309 : : * may represent an empty string with @data non-`NULL` and @size as 0. `NULL`
310 : : * will not be returned if @size is non-zero.
311 : : *
312 : : * Returns: (transfer none) (array length=size) (element-type guint8) (nullable):
313 : : * a pointer to the byte data
314 : : * Since: 2.32
315 : : */
316 : : gconstpointer
317 : 716536 : g_bytes_get_data (GBytes *bytes,
318 : : gsize *size)
319 : : {
320 : 716536 : g_return_val_if_fail (bytes != NULL, NULL);
321 : 716536 : if (size)
322 : 705918 : *size = bytes->size;
323 : 716536 : return bytes->data;
324 : : }
325 : :
326 : : /**
327 : : * g_bytes_get_size:
328 : : * @bytes: a [struct@GLib.Bytes]
329 : : *
330 : : * Get the size of the byte data in the [struct@GLib.Bytes].
331 : : *
332 : : * This function will always return the same value for a given `GBytes`.
333 : : *
334 : : * Returns: the size
335 : : * Since: 2.32
336 : : */
337 : : gsize
338 : 675331 : g_bytes_get_size (GBytes *bytes)
339 : : {
340 : 675331 : g_return_val_if_fail (bytes != NULL, 0);
341 : 675331 : return bytes->size;
342 : : }
343 : :
344 : :
345 : : /**
346 : : * g_bytes_ref:
347 : : * @bytes: a [struct@GLib.Bytes]
348 : : *
349 : : * Increase the reference count on @bytes.
350 : : *
351 : : * Returns: the [struct@GLib.Bytes]
352 : : * Since: 2.32
353 : : */
354 : : GBytes *
355 : 3259069 : g_bytes_ref (GBytes *bytes)
356 : : {
357 : 3259069 : g_return_val_if_fail (bytes != NULL, NULL);
358 : :
359 : 3259069 : g_atomic_ref_count_inc (&bytes->ref_count);
360 : :
361 : 3259069 : return bytes;
362 : : }
363 : :
364 : : /**
365 : : * g_bytes_unref:
366 : : * @bytes: (nullable): a [struct@GLib.Bytes]
367 : : *
368 : : * Releases a reference on @bytes.
369 : : *
370 : : * This may result in the bytes being freed. If @bytes is `NULL`, it will
371 : : * return immediately.
372 : : *
373 : : * Since: 2.32
374 : : */
375 : : void
376 : 4794947 : g_bytes_unref (GBytes *bytes)
377 : : {
378 : 4794947 : if (bytes == NULL)
379 : 1438217 : return;
380 : :
381 : 3356730 : if (g_atomic_ref_count_dec (&bytes->ref_count))
382 : : {
383 : 97665 : if (bytes->free_func != NULL)
384 : 87553 : bytes->free_func (bytes->user_data);
385 : 97665 : g_free (bytes);
386 : : }
387 : : }
388 : :
389 : : /**
390 : : * g_bytes_equal:
391 : : * @bytes1: (type GLib.Bytes): a pointer to a [struct@GLib.Bytes]
392 : : * @bytes2: (type GLib.Bytes): a pointer to a [struct@GLib.Bytes] to compare with @bytes1
393 : : *
394 : : * Compares the two [struct@GLib.Bytes] values being pointed to and returns
395 : : * `TRUE` if they are equal.
396 : : *
397 : : * This function can be passed to [func@GLib.HashTable.new] as the
398 : : * @key_equal_func parameter, when using non-`NULL` `GBytes` pointers as keys in
399 : : * a [struct@GLib.HashTable].
400 : : *
401 : : * Returns: `TRUE` if the two keys match.
402 : : * Since: 2.32
403 : : */
404 : : gboolean
405 : 13 : g_bytes_equal (gconstpointer bytes1,
406 : : gconstpointer bytes2)
407 : : {
408 : 13 : const GBytes *b1 = bytes1;
409 : 13 : const GBytes *b2 = bytes2;
410 : :
411 : 13 : g_return_val_if_fail (bytes1 != NULL, FALSE);
412 : 13 : g_return_val_if_fail (bytes2 != NULL, FALSE);
413 : :
414 : 23 : return b1->size == b2->size &&
415 : 10 : (b1->size == 0 || memcmp (b1->data, b2->data, b1->size) == 0);
416 : : }
417 : :
418 : : /**
419 : : * g_bytes_hash:
420 : : * @bytes: (type GLib.Bytes): a pointer to a [struct@GLib.Bytes] key
421 : : *
422 : : * Creates an integer hash code for the byte data in the [struct@GLib.Bytes].
423 : : *
424 : : * This function can be passed to [func@GLib.HashTable.new] as the
425 : : * @key_hash_func parameter, when using non-`NULL` `GBytes` pointers as keys in
426 : : * a [struct@GLib.HashTable].
427 : : *
428 : : * Returns: a hash value corresponding to the key.
429 : : * Since: 2.32
430 : : */
431 : : guint
432 : 6 : g_bytes_hash (gconstpointer bytes)
433 : : {
434 : 6 : const GBytes *a = bytes;
435 : : const signed char *p, *e;
436 : 6 : guint32 h = 5381;
437 : :
438 : 6 : g_return_val_if_fail (bytes != NULL, 0);
439 : :
440 : 90 : for (p = (signed char *)a->data, e = (signed char *)a->data + a->size; p != e; p++)
441 : 84 : h = (h << 5) + h + *p;
442 : :
443 : 6 : return h;
444 : : }
445 : :
446 : : /**
447 : : * g_bytes_compare:
448 : : * @bytes1: (type GLib.Bytes): a pointer to a [struct@GLib.Bytes]
449 : : * @bytes2: (type GLib.Bytes): a pointer to a [struct@GLib.Bytes] to compare with @bytes1
450 : : *
451 : : * Compares the two [struct@GLib.Bytes] values.
452 : : *
453 : : * This function can be used to sort `GBytes` instances in lexicographical
454 : : * order.
455 : : *
456 : : * If @bytes1 and @bytes2 have different length but the shorter one is a
457 : : * prefix of the longer one then the shorter one is considered to be less than
458 : : * the longer one. Otherwise the first byte where both differ is used for
459 : : * comparison. If @bytes1 has a smaller value at that position it is
460 : : * considered less, otherwise greater than @bytes2.
461 : : *
462 : : * Returns: a negative value if @bytes1 is less than @bytes2, a positive value
463 : : * if @bytes1 is greater than @bytes2, and zero if @bytes1 is equal to @bytes2
464 : : * Since: 2.32
465 : : */
466 : : gint
467 : 6 : g_bytes_compare (gconstpointer bytes1,
468 : : gconstpointer bytes2)
469 : : {
470 : 6 : const GBytes *b1 = bytes1;
471 : 6 : const GBytes *b2 = bytes2;
472 : : gint ret;
473 : :
474 : 6 : g_return_val_if_fail (bytes1 != NULL, 0);
475 : 6 : g_return_val_if_fail (bytes2 != NULL, 0);
476 : :
477 : 6 : ret = memcmp (b1->data, b2->data, MIN (b1->size, b2->size));
478 : 6 : if (ret == 0 && b1->size != b2->size)
479 : 2 : ret = b1->size < b2->size ? -1 : 1;
480 : 6 : return ret;
481 : : }
482 : :
483 : : static gpointer
484 : 10 : try_steal_and_unref (GBytes *bytes,
485 : : GDestroyNotify free_func,
486 : : gsize *size)
487 : : {
488 : : gpointer result;
489 : :
490 : 10 : if (bytes->free_func != free_func || bytes->data == NULL ||
491 : 5 : bytes->user_data != bytes->data)
492 : 5 : return NULL;
493 : :
494 : : /* Are we the only reference? */
495 : 5 : if (g_atomic_ref_count_compare (&bytes->ref_count, 1))
496 : : {
497 : 3 : *size = bytes->size;
498 : 3 : result = (gpointer)bytes->data;
499 : 3 : g_assert (result != NULL); /* otherwise the case of @bytes being freed can’t be distinguished */
500 : 3 : g_free (bytes);
501 : 3 : return result;
502 : : }
503 : :
504 : 2 : return NULL;
505 : : }
506 : :
507 : :
508 : : /**
509 : : * g_bytes_unref_to_data:
510 : : * @bytes: (transfer full): a [struct@GLib.Bytes]
511 : : * @size: (out): location to place the length of the returned data
512 : : *
513 : : * Unreferences the bytes, and returns a pointer the same byte data
514 : : * contents.
515 : : *
516 : : * As an optimization, the byte data is returned without copying if this was
517 : : * the last reference to @bytes and @bytes was created with
518 : : * [ctor@GLib.Bytes.new], [ctor@GLib.Bytes.new_take] or
519 : : * [func@GLib.ByteArray.free_to_bytes] and the buffer was larger than the size
520 : : * [struct@GLib.Bytes] may internalize within its allocation. In all other cases
521 : : * the data is copied.
522 : : *
523 : : * Returns: (transfer full) (array length=size) (element-type guint8) (not nullable):
524 : : * a pointer to the same byte data, which should be freed with [func@GLib.free]
525 : : * Since: 2.32
526 : : */
527 : : gpointer
528 : 10 : g_bytes_unref_to_data (GBytes *bytes,
529 : : gsize *size)
530 : : {
531 : : gpointer result;
532 : :
533 : 10 : g_return_val_if_fail (bytes != NULL, NULL);
534 : 10 : g_return_val_if_fail (size != NULL, NULL);
535 : :
536 : : /*
537 : : * Optimal path: if this is was the last reference, then we can return
538 : : * the data from this GBytes without copying.
539 : : */
540 : :
541 : 10 : result = try_steal_and_unref (bytes, g_free, size);
542 : 10 : if (result == NULL)
543 : : {
544 : : /*
545 : : * Copy: Non g_malloc (or compatible) allocator, or static memory,
546 : : * so we have to copy, and then unref.
547 : : */
548 : 7 : result = g_memdup2 (bytes->data, bytes->size);
549 : 7 : *size = bytes->size;
550 : 7 : g_bytes_unref (bytes);
551 : : }
552 : :
553 : 10 : return result;
554 : : }
555 : :
556 : : /**
557 : : * g_bytes_unref_to_array:
558 : : * @bytes: (transfer full): a [struct@GLib.Bytes]
559 : : *
560 : : * Unreferences the bytes, and returns a new mutable [struct@GLib.ByteArray]
561 : : * containing the same byte data.
562 : : *
563 : : * As an optimization, the byte data is transferred to the array without copying
564 : : * if this was the last reference to @bytes and @bytes was created with
565 : : * [ctor@GLib.Bytes.new], [ctor@GLib.Bytes.new_take] or
566 : : * [func@GLib.ByteArray.free_to_bytes] and the buffer was larger than the size
567 : : * [struct@GLib.Bytes] may internalize within its allocation. In all other cases
568 : : * the data is copied.
569 : : *
570 : : * Do not use it if @bytes contains more than %G_MAXUINT
571 : : * bytes. [struct@GLib.ByteArray] stores the length of its data in `guint`,
572 : : * which may be shorter than `gsize`, that @bytes is using.
573 : : *
574 : : * Returns: (transfer full): a new mutable [struct@GLib.ByteArray] containing
575 : : * the same byte data
576 : : * Since: 2.32
577 : : */
578 : : GByteArray *
579 : 4 : g_bytes_unref_to_array (GBytes *bytes)
580 : : {
581 : : gpointer data;
582 : : gsize size;
583 : :
584 : 4 : g_return_val_if_fail (bytes != NULL, NULL);
585 : :
586 : 4 : data = g_bytes_unref_to_data (bytes, &size);
587 : 4 : return g_byte_array_new_take (data, size);
588 : : }
589 : :
590 : : /**
591 : : * g_bytes_get_region:
592 : : * @bytes: a [struct@GLib.Bytes]
593 : : * @element_size: a non-zero element size
594 : : * @offset: an offset to the start of the region within the @bytes
595 : : * @n_elements: the number of elements in the region
596 : : *
597 : : * Gets a pointer to a region in @bytes.
598 : : *
599 : : * The region starts at @offset many bytes from the start of the data
600 : : * and contains @n_elements many elements of @element_size size.
601 : : *
602 : : * @n_elements may be zero, but @element_size must always be non-zero.
603 : : * Ideally, @element_size is a static constant (eg: `sizeof` a struct).
604 : : *
605 : : * This function does careful bounds checking (including checking for
606 : : * arithmetic overflows) and returns a non-`NULL` pointer if the
607 : : * specified region lies entirely within the @bytes. If the region is
608 : : * in some way out of range, or if an overflow has occurred, then `NULL`
609 : : * is returned.
610 : : *
611 : : * Note: it is possible to have a valid zero-size region. In this case,
612 : : * the returned pointer will be equal to the base pointer of the data of
613 : : * @bytes, plus @offset. This will be non-`NULL` except for the case
614 : : * where @bytes itself was a zero-sized region. Since it is unlikely
615 : : * that you will be using this function to check for a zero-sized region
616 : : * in a zero-sized @bytes, `NULL` effectively always means ‘error’.
617 : : *
618 : : * Returns: (nullable): the requested region, or `NULL` in case of an error
619 : : * Since: 2.70
620 : : */
621 : : gconstpointer
622 : 10 : g_bytes_get_region (GBytes *bytes,
623 : : gsize element_size,
624 : : gsize offset,
625 : : gsize n_elements)
626 : : {
627 : : gsize total_size;
628 : : gsize end_offset;
629 : :
630 : 10 : g_return_val_if_fail (element_size > 0, NULL);
631 : :
632 : : /* No other assertion checks here. If something is wrong then we will
633 : : * simply crash (via NULL dereference or divide-by-zero).
634 : : */
635 : :
636 : 10 : if (!g_size_checked_mul (&total_size, element_size, n_elements))
637 : 2 : return NULL;
638 : :
639 : 8 : if (!g_size_checked_add (&end_offset, offset, total_size))
640 : 2 : return NULL;
641 : :
642 : : /* We now have:
643 : : *
644 : : * 0 <= offset <= end_offset
645 : : *
646 : : * So we need only check that end_offset is within the range of the
647 : : * size of @bytes and we're good to go.
648 : : */
649 : :
650 : 6 : if (end_offset > bytes->size)
651 : 3 : return NULL;
652 : :
653 : : /* We now have:
654 : : *
655 : : * 0 <= offset <= end_offset <= bytes->size
656 : : */
657 : :
658 : 3 : return ((guchar *) bytes->data) + offset;
659 : : }
|