1 /* GStreamer byte reader
3 * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4 * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #define GST_BYTE_READER_DISABLE_INLINES
27 #include "gstbytereader.h"
32 * SECTION:gstbytereader
33 * @short_description: Reads different integer, string and floating point
34 * types from a memory buffer
36 * #GstByteReader provides a byte reader that can read different integer and
37 * floating point types from a memory buffer. It provides functions for reading
38 * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
39 * and functions for reading little/big endian floating points numbers of
40 * 32 and 64 bits. It also provides functions to read NUL-terminated strings
41 * in various character encodings.
45 * gst_byte_reader_new:
46 * @data: (in) (transfer none) (array length=size): data from which the
47 * #GstByteReader should read
48 * @size: Size of @data in bytes
50 * Create a new #GstByteReader instance, which will read from @data.
52 * Free-function: gst_byte_reader_free
54 * Returns: (transfer full): a new #GstByteReader instance
57 gst_byte_reader_new (const guint8 * data, guint size)
59 GstByteReader *ret = g_slice_new0 (GstByteReader);
68 * gst_byte_reader_free:
69 * @reader: (in) (transfer full): a #GstByteReader instance
71 * Frees a #GstByteReader instance, which was previously allocated by
72 * gst_byte_reader_new().
75 gst_byte_reader_free (GstByteReader * reader)
77 g_return_if_fail (reader != NULL);
79 g_slice_free (GstByteReader, reader);
83 * gst_byte_reader_init:
84 * @reader: a #GstByteReader instance
85 * @data: (in) (transfer none) (array length=size): data from which
86 * the #GstByteReader should read
87 * @size: Size of @data in bytes
89 * Initializes a #GstByteReader instance to read from @data. This function
90 * can be called on already initialized instances.
93 gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
95 g_return_if_fail (reader != NULL);
103 * gst_byte_reader_set_pos:
104 * @reader: a #GstByteReader instance
105 * @pos: The new position in bytes
107 * Sets the new position of a #GstByteReader instance to @pos in bytes.
109 * Returns: %TRUE if the position could be set successfully, %FALSE
113 gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
115 g_return_val_if_fail (reader != NULL, FALSE);
117 if (pos > reader->size)
126 * gst_byte_reader_get_pos:
127 * @reader: a #GstByteReader instance
129 * Returns the current position of a #GstByteReader instance in bytes.
131 * Returns: The current position of @reader in bytes.
134 gst_byte_reader_get_pos (const GstByteReader * reader)
136 return _gst_byte_reader_get_pos_inline (reader);
140 * gst_byte_reader_get_remaining:
141 * @reader: a #GstByteReader instance
143 * Returns the remaining number of bytes of a #GstByteReader instance.
145 * Returns: The remaining number of bytes of @reader instance.
148 gst_byte_reader_get_remaining (const GstByteReader * reader)
150 return _gst_byte_reader_get_remaining_inline (reader);
154 * gst_byte_reader_get_size:
155 * @reader: a #GstByteReader instance
157 * Returns the total number of bytes of a #GstByteReader instance.
159 * Returns: The total number of bytes of @reader instance.
162 gst_byte_reader_get_size (const GstByteReader * reader)
164 return _gst_byte_reader_get_size_inline (reader);
167 #define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline
168 #define gst_byte_reader_get_size _gst_byte_reader_get_size_inline
171 * gst_byte_reader_skip:
172 * @reader: a #GstByteReader instance
173 * @nbytes: the number of bytes to skip
175 * Skips @nbytes bytes of the #GstByteReader instance.
177 * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
180 gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
182 return _gst_byte_reader_skip_inline (reader, nbytes);
186 * gst_byte_reader_get_uint8:
187 * @reader: a #GstByteReader instance
188 * @val: (out): Pointer to a #guint8 to store the result
190 * Read an unsigned 8 bit integer into @val and update the current position.
192 * Returns: %TRUE if successful, %FALSE otherwise.
196 * gst_byte_reader_get_int8:
197 * @reader: a #GstByteReader instance
198 * @val: (out): Pointer to a #gint8 to store the result
200 * Read a signed 8 bit integer into @val and update the current position.
202 * Returns: %TRUE if successful, %FALSE otherwise.
206 * gst_byte_reader_peek_uint8:
207 * @reader: a #GstByteReader instance
208 * @val: (out): Pointer to a #guint8 to store the result
210 * Read an unsigned 8 bit integer into @val but keep the current position.
212 * Returns: %TRUE if successful, %FALSE otherwise.
216 * gst_byte_reader_peek_int8:
217 * @reader: a #GstByteReader instance
218 * @val: (out): Pointer to a #gint8 to store the result
220 * Read a signed 8 bit integer into @val but keep the current position.
222 * Returns: %TRUE if successful, %FALSE otherwise.
226 * gst_byte_reader_get_uint16_le:
227 * @reader: a #GstByteReader instance
228 * @val: (out): Pointer to a #guint16 to store the result
230 * Read an unsigned 16 bit little endian integer into @val
231 * and update the current position.
233 * Returns: %TRUE if successful, %FALSE otherwise.
237 * gst_byte_reader_get_int16_le:
238 * @reader: a #GstByteReader instance
239 * @val: (out): Pointer to a #gint16 to store the result
241 * Read a signed 16 bit little endian integer into @val
242 * and update the current position.
244 * Returns: %TRUE if successful, %FALSE otherwise.
248 * gst_byte_reader_peek_uint16_le:
249 * @reader: a #GstByteReader instance
250 * @val: (out): Pointer to a #guint16 to store the result
252 * Read an unsigned 16 bit little endian integer into @val
253 * but keep the current position.
255 * Returns: %TRUE if successful, %FALSE otherwise.
259 * gst_byte_reader_peek_int16_le:
260 * @reader: a #GstByteReader instance
261 * @val: (out): Pointer to a #gint16 to store the result
263 * Read a signed 16 bit little endian integer into @val
264 * but keep the current position.
266 * Returns: %TRUE if successful, %FALSE otherwise.
270 * gst_byte_reader_get_uint16_be:
271 * @reader: a #GstByteReader instance
272 * @val: (out): Pointer to a #guint16 to store the result
274 * Read an unsigned 16 bit big endian integer into @val
275 * and update the current position.
277 * Returns: %TRUE if successful, %FALSE otherwise.
281 * gst_byte_reader_get_int16_be:
282 * @reader: a #GstByteReader instance
283 * @val: (out): Pointer to a #gint16 to store the result
285 * Read a signed 16 bit big endian integer into @val
286 * and update the current position.
288 * Returns: %TRUE if successful, %FALSE otherwise.
292 * gst_byte_reader_peek_uint16_be:
293 * @reader: a #GstByteReader instance
294 * @val: (out): Pointer to a #guint16 to store the result
296 * Read an unsigned 16 bit big endian integer into @val
297 * but keep the current position.
299 * Returns: %TRUE if successful, %FALSE otherwise.
303 * gst_byte_reader_peek_int16_be:
304 * @reader: a #GstByteReader instance
305 * @val: (out): Pointer to a #gint16 to store the result
307 * Read a signed 16 bit big endian integer into @val
308 * but keep the current position.
310 * Returns: %TRUE if successful, %FALSE otherwise.
314 * gst_byte_reader_get_uint24_le:
315 * @reader: a #GstByteReader instance
316 * @val: (out): Pointer to a #guint32 to store the result
318 * Read an unsigned 24 bit little endian integer into @val
319 * and update the current position.
321 * Returns: %TRUE if successful, %FALSE otherwise.
325 * gst_byte_reader_get_int24_le:
326 * @reader: a #GstByteReader instance
327 * @val: (out): Pointer to a #gint32 to store the result
329 * Read a signed 24 bit little endian integer into @val
330 * and update the current position.
332 * Returns: %TRUE if successful, %FALSE otherwise.
336 * gst_byte_reader_peek_uint24_le:
337 * @reader: a #GstByteReader instance
338 * @val: (out): Pointer to a #guint32 to store the result
340 * Read an unsigned 24 bit little endian integer into @val
341 * but keep the current position.
343 * Returns: %TRUE if successful, %FALSE otherwise.
347 * gst_byte_reader_peek_int24_le:
348 * @reader: a #GstByteReader instance
349 * @val: (out): Pointer to a #gint32 to store the result
351 * Read a signed 24 bit little endian integer into @val
352 * but keep the current position.
354 * Returns: %TRUE if successful, %FALSE otherwise.
358 * gst_byte_reader_get_uint24_be:
359 * @reader: a #GstByteReader instance
360 * @val: (out): Pointer to a #guint32 to store the result
362 * Read an unsigned 24 bit big endian integer into @val
363 * and update the current position.
365 * Returns: %TRUE if successful, %FALSE otherwise.
369 * gst_byte_reader_get_int24_be:
370 * @reader: a #GstByteReader instance
371 * @val: (out): Pointer to a #gint32 to store the result
373 * Read a signed 24 bit big endian integer into @val
374 * and update the current position.
376 * Returns: %TRUE if successful, %FALSE otherwise.
380 * gst_byte_reader_peek_uint24_be:
381 * @reader: a #GstByteReader instance
382 * @val: (out): Pointer to a #guint32 to store the result
384 * Read an unsigned 24 bit big endian integer into @val
385 * but keep the current position.
387 * Returns: %TRUE if successful, %FALSE otherwise.
391 * gst_byte_reader_peek_int24_be:
392 * @reader: a #GstByteReader instance
393 * @val: (out): Pointer to a #gint32 to store the result
395 * Read a signed 24 bit big endian integer into @val
396 * but keep the current position.
398 * Returns: %TRUE if successful, %FALSE otherwise.
403 * gst_byte_reader_get_uint32_le:
404 * @reader: a #GstByteReader instance
405 * @val: (out): Pointer to a #guint32 to store the result
407 * Read an unsigned 32 bit little endian integer into @val
408 * and update the current position.
410 * Returns: %TRUE if successful, %FALSE otherwise.
414 * gst_byte_reader_get_int32_le:
415 * @reader: a #GstByteReader instance
416 * @val: (out): Pointer to a #gint32 to store the result
418 * Read a signed 32 bit little endian integer into @val
419 * and update the current position.
421 * Returns: %TRUE if successful, %FALSE otherwise.
425 * gst_byte_reader_peek_uint32_le:
426 * @reader: a #GstByteReader instance
427 * @val: (out): Pointer to a #guint32 to store the result
429 * Read an unsigned 32 bit little endian integer into @val
430 * but keep the current position.
432 * Returns: %TRUE if successful, %FALSE otherwise.
436 * gst_byte_reader_peek_int32_le:
437 * @reader: a #GstByteReader instance
438 * @val: (out): Pointer to a #gint32 to store the result
440 * Read a signed 32 bit little endian integer into @val
441 * but keep the current position.
443 * Returns: %TRUE if successful, %FALSE otherwise.
447 * gst_byte_reader_get_uint32_be:
448 * @reader: a #GstByteReader instance
449 * @val: (out): Pointer to a #guint32 to store the result
451 * Read an unsigned 32 bit big endian integer into @val
452 * and update the current position.
454 * Returns: %TRUE if successful, %FALSE otherwise.
458 * gst_byte_reader_get_int32_be:
459 * @reader: a #GstByteReader instance
460 * @val: (out): Pointer to a #gint32 to store the result
462 * Read a signed 32 bit big endian integer into @val
463 * and update the current position.
465 * Returns: %TRUE if successful, %FALSE otherwise.
469 * gst_byte_reader_peek_uint32_be:
470 * @reader: a #GstByteReader instance
471 * @val: (out): Pointer to a #guint32 to store the result
473 * Read an unsigned 32 bit big endian integer into @val
474 * but keep the current position.
476 * Returns: %TRUE if successful, %FALSE otherwise.
480 * gst_byte_reader_peek_int32_be:
481 * @reader: a #GstByteReader instance
482 * @val: (out): Pointer to a #gint32 to store the result
484 * Read a signed 32 bit big endian integer into @val
485 * but keep the current position.
487 * Returns: %TRUE if successful, %FALSE otherwise.
491 * gst_byte_reader_get_uint64_le:
492 * @reader: a #GstByteReader instance
493 * @val: (out): Pointer to a #guint64 to store the result
495 * Read an unsigned 64 bit little endian integer into @val
496 * and update the current position.
498 * Returns: %TRUE if successful, %FALSE otherwise.
502 * gst_byte_reader_get_int64_le:
503 * @reader: a #GstByteReader instance
504 * @val: (out): Pointer to a #gint64 to store the result
506 * Read a signed 64 bit little endian integer into @val
507 * and update the current position.
509 * Returns: %TRUE if successful, %FALSE otherwise.
513 * gst_byte_reader_peek_uint64_le:
514 * @reader: a #GstByteReader instance
515 * @val: (out): Pointer to a #guint64 to store the result
517 * Read an unsigned 64 bit little endian integer into @val
518 * but keep the current position.
520 * Returns: %TRUE if successful, %FALSE otherwise.
524 * gst_byte_reader_peek_int64_le:
525 * @reader: a #GstByteReader instance
526 * @val: (out): Pointer to a #gint64 to store the result
528 * Read a signed 64 bit little endian integer into @val
529 * but keep the current position.
531 * Returns: %TRUE if successful, %FALSE otherwise.
535 * gst_byte_reader_get_uint64_be:
536 * @reader: a #GstByteReader instance
537 * @val: (out): Pointer to a #guint64 to store the result
539 * Read an unsigned 64 bit big endian integer into @val
540 * and update the current position.
542 * Returns: %TRUE if successful, %FALSE otherwise.
546 * gst_byte_reader_get_int64_be:
547 * @reader: a #GstByteReader instance
548 * @val: (out): Pointer to a #gint64 to store the result
550 * Read a signed 64 bit big endian integer into @val
551 * and update the current position.
553 * Returns: %TRUE if successful, %FALSE otherwise.
557 * gst_byte_reader_peek_uint64_be:
558 * @reader: a #GstByteReader instance
559 * @val: (out): Pointer to a #guint64 to store the result
561 * Read an unsigned 64 bit big endian integer into @val
562 * but keep the current position.
564 * Returns: %TRUE if successful, %FALSE otherwise.
568 * gst_byte_reader_peek_int64_be:
569 * @reader: a #GstByteReader instance
570 * @val: (out): Pointer to a #gint64 to store the result
572 * Read a signed 64 bit big endian integer into @val
573 * but keep the current position.
575 * Returns: %TRUE if successful, %FALSE otherwise.
578 #define GST_BYTE_READER_PEEK_GET(bits,type,name) \
580 gst_byte_reader_get_##name (GstByteReader * reader, type * val) \
582 return _gst_byte_reader_get_##name##_inline (reader, val); \
586 gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \
588 return _gst_byte_reader_peek_##name##_inline (reader, val); \
593 GST_BYTE_READER_PEEK_GET(8,guint8,uint8)
594 GST_BYTE_READER_PEEK_GET(8,gint8,int8)
596 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
597 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
598 GST_BYTE_READER_PEEK_GET(16,gint16,int16_le)
599 GST_BYTE_READER_PEEK_GET(16,gint16,int16_be)
601 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
602 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
603 GST_BYTE_READER_PEEK_GET(24,gint32,int24_le)
604 GST_BYTE_READER_PEEK_GET(24,gint32,int24_be)
606 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
607 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
608 GST_BYTE_READER_PEEK_GET(32,gint32,int32_le)
609 GST_BYTE_READER_PEEK_GET(32,gint32,int32_be)
611 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
612 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
613 GST_BYTE_READER_PEEK_GET(64,gint64,int64_le)
614 GST_BYTE_READER_PEEK_GET(64,gint64,int64_be)
617 * gst_byte_reader_get_float32_le:
618 * @reader: a #GstByteReader instance
619 * @val: (out): Pointer to a #gfloat to store the result
621 * Read a 32 bit little endian floating point value into @val
622 * and update the current position.
624 * Returns: %TRUE if successful, %FALSE otherwise.
628 * gst_byte_reader_peek_float32_le:
629 * @reader: a #GstByteReader instance
630 * @val: (out): Pointer to a #gfloat to store the result
632 * Read a 32 bit little endian floating point value into @val
633 * but keep the current position.
635 * Returns: %TRUE if successful, %FALSE otherwise.
639 * gst_byte_reader_get_float32_be:
640 * @reader: a #GstByteReader instance
641 * @val: (out): Pointer to a #gfloat to store the result
643 * Read a 32 bit big endian floating point value into @val
644 * and update the current position.
646 * Returns: %TRUE if successful, %FALSE otherwise.
650 * gst_byte_reader_peek_float32_be:
651 * @reader: a #GstByteReader instance
652 * @val: (out): Pointer to a #gfloat to store the result
654 * Read a 32 bit big endian floating point value into @val
655 * but keep the current position.
657 * Returns: %TRUE if successful, %FALSE otherwise.
661 * gst_byte_reader_get_float64_le:
662 * @reader: a #GstByteReader instance
663 * @val: (out): Pointer to a #gdouble to store the result
665 * Read a 64 bit little endian floating point value into @val
666 * and update the current position.
668 * Returns: %TRUE if successful, %FALSE otherwise.
672 * gst_byte_reader_peek_float64_le:
673 * @reader: a #GstByteReader instance
674 * @val: (out): Pointer to a #gdouble to store the result
676 * Read a 64 bit little endian floating point value into @val
677 * but keep the current position.
679 * Returns: %TRUE if successful, %FALSE otherwise.
683 * gst_byte_reader_get_float64_be:
684 * @reader: a #GstByteReader instance
685 * @val: (out): Pointer to a #gdouble to store the result
687 * Read a 64 bit big endian floating point value into @val
688 * and update the current position.
690 * Returns: %TRUE if successful, %FALSE otherwise.
694 * gst_byte_reader_peek_float64_be:
695 * @reader: a #GstByteReader instance
696 * @val: (out): Pointer to a #gdouble to store the result
698 * Read a 64 bit big endian floating point value into @val
699 * but keep the current position.
701 * Returns: %TRUE if successful, %FALSE otherwise.
704 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
705 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
706 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
707 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
712 * gst_byte_reader_get_data:
713 * @reader: a #GstByteReader instance
714 * @size: Size in bytes
715 * @val: (out) (transfer none) (array length=size): address of a
716 * #guint8 pointer variable in which to store the result
718 * Returns a constant pointer to the current data
719 * position if at least @size bytes are left and
720 * updates the current position.
723 * Returns: %TRUE if successful, %FALSE otherwise.
726 gst_byte_reader_get_data (GstByteReader * reader, guint size,
729 return _gst_byte_reader_get_data_inline (reader, size, val);
733 * gst_byte_reader_peek_data:
734 * @reader: a #GstByteReader instance
735 * @size: Size in bytes
736 * @val: (out) (transfer none) (array length=size): address of a
737 * #guint8 pointer variable in which to store the result
739 * Returns a constant pointer to the current data
740 * position if at least @size bytes are left and
741 * keeps the current position.
744 * Returns: %TRUE if successful, %FALSE otherwise.
747 gst_byte_reader_peek_data (const GstByteReader * reader, guint size,
750 return _gst_byte_reader_peek_data_inline (reader, size, val);
754 * gst_byte_reader_dup_data:
755 * @reader: a #GstByteReader instance
756 * @size: Size in bytes
757 * @val: (out) (transfer full) (array length=size): address of a
758 * #guint8 pointer variable in which to store the result
760 * Free-function: g_free
762 * Returns a newly-allocated copy of the current data
763 * position if at least @size bytes are left and
764 * updates the current position. Free with g_free() when no longer needed.
766 * Returns: %TRUE if successful, %FALSE otherwise.
769 gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
771 return _gst_byte_reader_dup_data_inline (reader, size, val);
774 /* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
776 _scan_for_start_code (const guint8 * data, guint offset, guint size)
780 while (i <= (size - 4)) {
781 if (data[i + 2] > 1) {
783 } else if (data[i + 1]) {
785 } else if (data[i] || data[i + 2] != 1) {
800 * gst_byte_reader_masked_scan_uint32:
801 * @reader: a #GstByteReader
802 * @mask: mask to apply to data before matching against @pattern
803 * @pattern: pattern to match (after mask is applied)
804 * @offset: offset from which to start scanning, relative to the current
806 * @size: number of bytes to scan from offset
808 * Scan for pattern @pattern with applied mask @mask in the byte reader data,
809 * starting from offset @offset relative to the current position.
811 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
812 * of endianness. All four bytes of the pattern must be present in the
813 * byte reader data for it to match, even if the first or last bytes are masked
816 * It is an error to call this function without making sure that there is
817 * enough data (offset+size bytes) in the byte reader.
819 * Returns: offset of the first match, or -1 if no match was found.
823 * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
825 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
827 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
829 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
831 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
833 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
835 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
837 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
842 gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
843 guint32 pattern, guint offset, guint size)
849 g_return_val_if_fail (size > 0, -1);
850 g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
853 /* we can't find the pattern with less than 4 bytes */
854 if (G_UNLIKELY (size < 4))
857 data = reader->data + reader->byte + offset;
859 /* Handle special case found in MPEG and H264 */
860 if ((pattern == 0x00000100) && (mask == 0xffffff00))
861 return _scan_for_start_code (data, offset, size);
863 /* set the state to something that does not match */
867 for (i = 0; i < size; i++) {
868 /* throw away one byte and move in the next byte */
869 state = ((state << 8) | data[i]);
870 if (G_UNLIKELY ((state & mask) == pattern)) {
871 /* we have a match but we need to have skipped at
872 * least 4 bytes to fill the state. */
873 if (G_LIKELY (i >= 3))
874 return offset + i - 3;
882 #define GST_BYTE_READER_SCAN_STRING(bits) \
884 gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \
886 guint len, off, max_len; \
888 max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
890 /* need at least a single NUL terminator */ \
895 off = reader->byte; \
896 /* endianness does not matter if we are looking for a NUL terminator */ \
897 while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
899 off += sizeof (guint##bits); \
900 /* have we reached the end without finding a NUL terminator? */ \
901 if (len == max_len) \
904 /* return size in bytes including the NUL terminator (hence the +1) */ \
905 return (len + 1) * sizeof (guint##bits); \
908 #define GST_READ_UINT8_LE GST_READ_UINT8
909 GST_BYTE_READER_SCAN_STRING (8);
910 #undef GST_READ_UINT8_LE
911 GST_BYTE_READER_SCAN_STRING (16);
912 GST_BYTE_READER_SCAN_STRING (32);
914 #define GST_BYTE_READER_SKIP_STRING(bits) \
916 gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
918 guint size; /* size in bytes including the terminator */ \
920 g_return_val_if_fail (reader != NULL, FALSE); \
922 size = gst_byte_reader_scan_string_utf##bits (reader); \
923 reader->byte += size; \
928 * gst_byte_reader_skip_string:
929 * @reader: a #GstByteReader instance
931 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
932 * the current position to the byte after the string. This will work for
933 * any NUL-terminated string with a character width of 8 bits, so ASCII,
934 * UTF-8, ISO-8859-N etc.
936 * This function will fail if no NUL-terminator was found in in the data.
938 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
941 * gst_byte_reader_skip_string_utf8:
942 * @reader: a #GstByteReader instance
944 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
945 * the current position to the byte after the string. This will work for
946 * any NUL-terminated string with a character width of 8 bits, so ASCII,
947 * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
949 * This function will fail if no NUL-terminator was found in in the data.
951 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
953 GST_BYTE_READER_SKIP_STRING (8);
956 * gst_byte_reader_skip_string_utf16:
957 * @reader: a #GstByteReader instance
959 * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
960 * advancing the current position to the byte after the string.
962 * No input checking for valid UTF-16 is done.
964 * This function will fail if no NUL-terminator was found in in the data.
966 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
968 GST_BYTE_READER_SKIP_STRING (16);
971 * gst_byte_reader_skip_string_utf32:
972 * @reader: a #GstByteReader instance
974 * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
975 * advancing the current position to the byte after the string.
977 * No input checking for valid UTF-32 is done.
979 * This function will fail if no NUL-terminator was found in in the data.
981 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
983 GST_BYTE_READER_SKIP_STRING (32);
986 * gst_byte_reader_peek_string:
987 * @reader: a #GstByteReader instance
988 * @str: (out) (transfer none) (array zero-terminated=1): address of a
989 * #gchar pointer varieble in which to store the result
991 * Returns a constant pointer to the current data position if there is
992 * a NUL-terminated string in the data (this could be just a NUL terminator).
993 * The current position will be maintained. This will work for any
994 * NUL-terminated string with a character width of 8 bits, so ASCII,
995 * UTF-8, ISO-8859-N etc.
997 * This function will fail if no NUL-terminator was found in in the data.
999 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1002 * gst_byte_reader_peek_string_utf8:
1003 * @reader: a #GstByteReader instance
1004 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1005 * #gchar pointer varieble in which to store the result
1007 * Returns a constant pointer to the current data position if there is
1008 * a NUL-terminated string in the data (this could be just a NUL terminator).
1009 * The current position will be maintained. This will work for any
1010 * NUL-terminated string with a character width of 8 bits, so ASCII,
1011 * UTF-8, ISO-8859-N etc.
1013 * No input checking for valid UTF-8 is done.
1015 * This function will fail if no NUL-terminator was found in in the data.
1017 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1020 gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
1023 g_return_val_if_fail (reader != NULL, FALSE);
1024 g_return_val_if_fail (str != NULL, FALSE);
1026 if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
1027 *str = (const gchar *) (reader->data + reader->byte);
1031 return (*str != NULL);
1035 * gst_byte_reader_get_string_utf8:
1036 * @reader: a #GstByteReader instance
1037 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1038 * #gchar pointer varieble in which to store the result
1040 * Returns a constant pointer to the current data position if there is
1041 * a NUL-terminated string in the data (this could be just a NUL terminator),
1042 * advancing the current position to the byte after the string. This will work
1043 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1044 * UTF-8, ISO-8859-N etc.
1046 * No input checking for valid UTF-8 is done.
1048 * This function will fail if no NUL-terminator was found in in the data.
1050 * Returns: %TRUE if a string could be found, %FALSE otherwise.
1053 gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
1055 guint size; /* size in bytes including the terminator */
1057 g_return_val_if_fail (reader != NULL, FALSE);
1058 g_return_val_if_fail (str != NULL, FALSE);
1060 size = gst_byte_reader_scan_string_utf8 (reader);
1066 *str = (const gchar *) (reader->data + reader->byte);
1067 reader->byte += size;
1071 #define GST_BYTE_READER_DUP_STRING(bits,type) \
1073 gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
1075 guint size; /* size in bytes including the terminator */ \
1077 g_return_val_if_fail (reader != NULL, FALSE); \
1078 g_return_val_if_fail (str != NULL, FALSE); \
1080 size = gst_byte_reader_scan_string_utf##bits (reader); \
1085 *str = g_memdup (reader->data + reader->byte, size); \
1086 reader->byte += size; \
1091 * gst_byte_reader_dup_string_utf8:
1092 * @reader: a #GstByteReader instance
1093 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1094 * #gchar pointer varieble in which to store the result
1096 * Free-function: g_free
1098 * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
1099 * advancing the current position to the byte after the string. This will work
1100 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1101 * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1103 * This function will fail if no NUL-terminator was found in in the data.
1105 * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
1106 * string put into @str must be freed with g_free() when no longer needed.
1108 GST_BYTE_READER_DUP_STRING (8, gchar);
1111 * gst_byte_reader_dup_string_utf16:
1112 * @reader: a #GstByteReader instance
1113 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1114 * #guint16 pointer varieble in which to store the result
1116 * Free-function: g_free
1118 * Returns a newly-allocated copy of the current data position if there is
1119 * a NUL-terminated UTF-16 string in the data (this could be an empty string
1120 * as well), and advances the current position.
1122 * No input checking for valid UTF-16 is done. This function is endianness
1123 * agnostic - you should not assume the UTF-16 characters are in host
1126 * This function will fail if no NUL-terminator was found in in the data.
1128 * Note: there is no peek or get variant of this function to ensure correct
1129 * byte alignment of the UTF-16 string.
1131 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1132 * string put into @str must be freed with g_free() when no longer needed.
1134 GST_BYTE_READER_DUP_STRING (16, guint16);
1137 * gst_byte_reader_dup_string_utf32:
1138 * @reader: a #GstByteReader instance
1139 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1140 * #guint32 pointer varieble in which to store the result
1142 * Free-function: g_free
1144 * Returns a newly-allocated copy of the current data position if there is
1145 * a NUL-terminated UTF-32 string in the data (this could be an empty string
1146 * as well), and advances the current position.
1148 * No input checking for valid UTF-32 is done. This function is endianness
1149 * agnostic - you should not assume the UTF-32 characters are in host
1152 * This function will fail if no NUL-terminator was found in in the data.
1154 * Note: there is no peek or get variant of this function to ensure correct
1155 * byte alignment of the UTF-32 string.
1157 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1158 * string put into @str must be freed with g_free() when no longer needed.
1160 GST_BYTE_READER_DUP_STRING (32, guint32);