1 /* GStreamer byte reader
3 * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4 * Copyright (C) 2009,2014 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 * @title: GstByteReader
34 * @short_description: Reads different integer, string and floating point
35 * types from a memory buffer
37 * #GstByteReader provides a byte reader that can read different integer and
38 * floating point types from a memory buffer. It provides functions for reading
39 * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
40 * and functions for reading little/big endian floating points numbers of
41 * 32 and 64 bits. It also provides functions to read NUL-terminated strings
42 * in various character encodings.
46 * gst_byte_reader_new: (skip)
47 * @data: (in) (transfer none) (array length=size): data from which the
48 * #GstByteReader should read
49 * @size: Size of @data in bytes
51 * Create a new #GstByteReader instance, which will read from @data.
53 * Free-function: gst_byte_reader_free
55 * Returns: (transfer full): a new #GstByteReader instance
58 gst_byte_reader_new (const guint8 * data, guint size)
60 GstByteReader *ret = g_slice_new0 (GstByteReader);
69 * gst_byte_reader_free:
70 * @reader: (in) (transfer full): a #GstByteReader instance
72 * Frees a #GstByteReader instance, which was previously allocated by
73 * gst_byte_reader_new().
76 gst_byte_reader_free (GstByteReader * reader)
78 g_return_if_fail (reader != NULL);
80 g_slice_free (GstByteReader, reader);
84 * gst_byte_reader_init:
85 * @reader: a #GstByteReader instance
86 * @data: (in) (transfer none) (array length=size): data from which
87 * the #GstByteReader should read
88 * @size: Size of @data in bytes
90 * Initializes a #GstByteReader instance to read from @data. This function
91 * can be called on already initialized instances.
94 gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
96 g_return_if_fail (reader != NULL);
104 * gst_byte_reader_peek_sub_reader: (skip)
105 * @reader: an existing and initialized #GstByteReader instance
106 * @sub_reader: a #GstByteReader instance to initialize as sub-reader
107 * @size: size of @sub_reader in bytes
109 * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
110 * data from the current position of @reader. This is useful to read chunked
111 * formats and make sure that one doesn't read beyond the size of the sub-chunk.
113 * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the
114 * current position of @reader.
116 * Returns: FALSE on error or if @reader does not contain @size more bytes from
117 * the current position, and otherwise TRUE
122 gst_byte_reader_peek_sub_reader (GstByteReader * reader,
123 GstByteReader * sub_reader, guint size)
125 return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
129 * gst_byte_reader_get_sub_reader: (skip)
130 * @reader: an existing and initialized #GstByteReader instance
131 * @sub_reader: a #GstByteReader instance to initialize as sub-reader
132 * @size: size of @sub_reader in bytes
134 * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
135 * data from the current position of @reader. This is useful to read chunked
136 * formats and make sure that one doesn't read beyond the size of the sub-chunk.
138 * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the
139 * position of @reader and moves it forward by @size bytes.
141 * Returns: FALSE on error or if @reader does not contain @size more bytes from
142 * the current position, and otherwise TRUE
147 gst_byte_reader_get_sub_reader (GstByteReader * reader,
148 GstByteReader * sub_reader, guint size)
150 return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
154 * gst_byte_reader_set_pos:
155 * @reader: a #GstByteReader instance
156 * @pos: The new position in bytes
158 * Sets the new position of a #GstByteReader instance to @pos in bytes.
160 * Returns: %TRUE if the position could be set successfully, %FALSE
164 gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
166 g_return_val_if_fail (reader != NULL, FALSE);
168 if (pos > reader->size)
177 * gst_byte_reader_get_pos:
178 * @reader: a #GstByteReader instance
180 * Returns the current position of a #GstByteReader instance in bytes.
182 * Returns: The current position of @reader in bytes.
185 gst_byte_reader_get_pos (const GstByteReader * reader)
187 return _gst_byte_reader_get_pos_inline (reader);
191 * gst_byte_reader_get_remaining:
192 * @reader: a #GstByteReader instance
194 * Returns the remaining number of bytes of a #GstByteReader instance.
196 * Returns: The remaining number of bytes of @reader instance.
199 gst_byte_reader_get_remaining (const GstByteReader * reader)
201 return _gst_byte_reader_get_remaining_inline (reader);
205 * gst_byte_reader_get_size:
206 * @reader: a #GstByteReader instance
208 * Returns the total number of bytes of a #GstByteReader instance.
210 * Returns: The total number of bytes of @reader instance.
213 gst_byte_reader_get_size (const GstByteReader * reader)
215 return _gst_byte_reader_get_size_inline (reader);
218 #define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline
219 #define gst_byte_reader_get_size _gst_byte_reader_get_size_inline
222 * gst_byte_reader_skip:
223 * @reader: a #GstByteReader instance
224 * @nbytes: the number of bytes to skip
226 * Skips @nbytes bytes of the #GstByteReader instance.
228 * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
231 gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
233 return _gst_byte_reader_skip_inline (reader, nbytes);
237 * gst_byte_reader_get_uint8:
238 * @reader: a #GstByteReader instance
239 * @val: (out): Pointer to a #guint8 to store the result
241 * Read an unsigned 8 bit integer into @val and update the current position.
243 * Returns: %TRUE if successful, %FALSE otherwise.
247 * gst_byte_reader_get_int8:
248 * @reader: a #GstByteReader instance
249 * @val: (out): Pointer to a #gint8 to store the result
251 * Read a signed 8 bit integer into @val and update the current position.
253 * Returns: %TRUE if successful, %FALSE otherwise.
257 * gst_byte_reader_peek_uint8:
258 * @reader: a #GstByteReader instance
259 * @val: (out): Pointer to a #guint8 to store the result
261 * Read an unsigned 8 bit integer into @val but keep the current position.
263 * Returns: %TRUE if successful, %FALSE otherwise.
267 * gst_byte_reader_peek_int8:
268 * @reader: a #GstByteReader instance
269 * @val: (out): Pointer to a #gint8 to store the result
271 * Read a signed 8 bit integer into @val but keep the current position.
273 * Returns: %TRUE if successful, %FALSE otherwise.
277 * gst_byte_reader_get_uint16_le:
278 * @reader: a #GstByteReader instance
279 * @val: (out): Pointer to a #guint16 to store the result
281 * Read an unsigned 16 bit little endian integer into @val
282 * and update the current position.
284 * Returns: %TRUE if successful, %FALSE otherwise.
288 * gst_byte_reader_get_int16_le:
289 * @reader: a #GstByteReader instance
290 * @val: (out): Pointer to a #gint16 to store the result
292 * Read a signed 16 bit little endian integer into @val
293 * and update the current position.
295 * Returns: %TRUE if successful, %FALSE otherwise.
299 * gst_byte_reader_peek_uint16_le:
300 * @reader: a #GstByteReader instance
301 * @val: (out): Pointer to a #guint16 to store the result
303 * Read an unsigned 16 bit little endian integer into @val
304 * but keep the current position.
306 * Returns: %TRUE if successful, %FALSE otherwise.
310 * gst_byte_reader_peek_int16_le:
311 * @reader: a #GstByteReader instance
312 * @val: (out): Pointer to a #gint16 to store the result
314 * Read a signed 16 bit little endian integer into @val
315 * but keep the current position.
317 * Returns: %TRUE if successful, %FALSE otherwise.
321 * gst_byte_reader_get_uint16_be:
322 * @reader: a #GstByteReader instance
323 * @val: (out): Pointer to a #guint16 to store the result
325 * Read an unsigned 16 bit big endian integer into @val
326 * and update the current position.
328 * Returns: %TRUE if successful, %FALSE otherwise.
332 * gst_byte_reader_get_int16_be:
333 * @reader: a #GstByteReader instance
334 * @val: (out): Pointer to a #gint16 to store the result
336 * Read a signed 16 bit big endian integer into @val
337 * and update the current position.
339 * Returns: %TRUE if successful, %FALSE otherwise.
343 * gst_byte_reader_peek_uint16_be:
344 * @reader: a #GstByteReader instance
345 * @val: (out): Pointer to a #guint16 to store the result
347 * Read an unsigned 16 bit big endian integer into @val
348 * but keep the current position.
350 * Returns: %TRUE if successful, %FALSE otherwise.
354 * gst_byte_reader_peek_int16_be:
355 * @reader: a #GstByteReader instance
356 * @val: (out): Pointer to a #gint16 to store the result
358 * Read a signed 16 bit big endian integer into @val
359 * but keep the current position.
361 * Returns: %TRUE if successful, %FALSE otherwise.
365 * gst_byte_reader_get_uint24_le:
366 * @reader: a #GstByteReader instance
367 * @val: (out): Pointer to a #guint32 to store the result
369 * Read an unsigned 24 bit little endian integer into @val
370 * and update the current position.
372 * Returns: %TRUE if successful, %FALSE otherwise.
376 * gst_byte_reader_get_int24_le:
377 * @reader: a #GstByteReader instance
378 * @val: (out): Pointer to a #gint32 to store the result
380 * Read a signed 24 bit little endian integer into @val
381 * and update the current position.
383 * Returns: %TRUE if successful, %FALSE otherwise.
387 * gst_byte_reader_peek_uint24_le:
388 * @reader: a #GstByteReader instance
389 * @val: (out): Pointer to a #guint32 to store the result
391 * Read an unsigned 24 bit little endian integer into @val
392 * but keep the current position.
394 * Returns: %TRUE if successful, %FALSE otherwise.
398 * gst_byte_reader_peek_int24_le:
399 * @reader: a #GstByteReader instance
400 * @val: (out): Pointer to a #gint32 to store the result
402 * Read a signed 24 bit little endian integer into @val
403 * but keep the current position.
405 * Returns: %TRUE if successful, %FALSE otherwise.
409 * gst_byte_reader_get_uint24_be:
410 * @reader: a #GstByteReader instance
411 * @val: (out): Pointer to a #guint32 to store the result
413 * Read an unsigned 24 bit big endian integer into @val
414 * and update the current position.
416 * Returns: %TRUE if successful, %FALSE otherwise.
420 * gst_byte_reader_get_int24_be:
421 * @reader: a #GstByteReader instance
422 * @val: (out): Pointer to a #gint32 to store the result
424 * Read a signed 24 bit big endian integer into @val
425 * and update the current position.
427 * Returns: %TRUE if successful, %FALSE otherwise.
431 * gst_byte_reader_peek_uint24_be:
432 * @reader: a #GstByteReader instance
433 * @val: (out): Pointer to a #guint32 to store the result
435 * Read an unsigned 24 bit big endian integer into @val
436 * but keep the current position.
438 * Returns: %TRUE if successful, %FALSE otherwise.
442 * gst_byte_reader_peek_int24_be:
443 * @reader: a #GstByteReader instance
444 * @val: (out): Pointer to a #gint32 to store the result
446 * Read a signed 24 bit big endian integer into @val
447 * but keep the current position.
449 * Returns: %TRUE if successful, %FALSE otherwise.
454 * gst_byte_reader_get_uint32_le:
455 * @reader: a #GstByteReader instance
456 * @val: (out): Pointer to a #guint32 to store the result
458 * Read an unsigned 32 bit little endian integer into @val
459 * and update the current position.
461 * Returns: %TRUE if successful, %FALSE otherwise.
465 * gst_byte_reader_get_int32_le:
466 * @reader: a #GstByteReader instance
467 * @val: (out): Pointer to a #gint32 to store the result
469 * Read a signed 32 bit little endian integer into @val
470 * and update the current position.
472 * Returns: %TRUE if successful, %FALSE otherwise.
476 * gst_byte_reader_peek_uint32_le:
477 * @reader: a #GstByteReader instance
478 * @val: (out): Pointer to a #guint32 to store the result
480 * Read an unsigned 32 bit little endian integer into @val
481 * but keep the current position.
483 * Returns: %TRUE if successful, %FALSE otherwise.
487 * gst_byte_reader_peek_int32_le:
488 * @reader: a #GstByteReader instance
489 * @val: (out): Pointer to a #gint32 to store the result
491 * Read a signed 32 bit little endian integer into @val
492 * but keep the current position.
494 * Returns: %TRUE if successful, %FALSE otherwise.
498 * gst_byte_reader_get_uint32_be:
499 * @reader: a #GstByteReader instance
500 * @val: (out): Pointer to a #guint32 to store the result
502 * Read an unsigned 32 bit big endian integer into @val
503 * and update the current position.
505 * Returns: %TRUE if successful, %FALSE otherwise.
509 * gst_byte_reader_get_int32_be:
510 * @reader: a #GstByteReader instance
511 * @val: (out): Pointer to a #gint32 to store the result
513 * Read a signed 32 bit big endian integer into @val
514 * and update the current position.
516 * Returns: %TRUE if successful, %FALSE otherwise.
520 * gst_byte_reader_peek_uint32_be:
521 * @reader: a #GstByteReader instance
522 * @val: (out): Pointer to a #guint32 to store the result
524 * Read an unsigned 32 bit big endian integer into @val
525 * but keep the current position.
527 * Returns: %TRUE if successful, %FALSE otherwise.
531 * gst_byte_reader_peek_int32_be:
532 * @reader: a #GstByteReader instance
533 * @val: (out): Pointer to a #gint32 to store the result
535 * Read a signed 32 bit big endian integer into @val
536 * but keep the current position.
538 * Returns: %TRUE if successful, %FALSE otherwise.
542 * gst_byte_reader_get_uint64_le:
543 * @reader: a #GstByteReader instance
544 * @val: (out): Pointer to a #guint64 to store the result
546 * Read an unsigned 64 bit little endian integer into @val
547 * and update the current position.
549 * Returns: %TRUE if successful, %FALSE otherwise.
553 * gst_byte_reader_get_int64_le:
554 * @reader: a #GstByteReader instance
555 * @val: (out): Pointer to a #gint64 to store the result
557 * Read a signed 64 bit little endian integer into @val
558 * and update the current position.
560 * Returns: %TRUE if successful, %FALSE otherwise.
564 * gst_byte_reader_peek_uint64_le:
565 * @reader: a #GstByteReader instance
566 * @val: (out): Pointer to a #guint64 to store the result
568 * Read an unsigned 64 bit little endian integer into @val
569 * but keep the current position.
571 * Returns: %TRUE if successful, %FALSE otherwise.
575 * gst_byte_reader_peek_int64_le:
576 * @reader: a #GstByteReader instance
577 * @val: (out): Pointer to a #gint64 to store the result
579 * Read a signed 64 bit little endian integer into @val
580 * but keep the current position.
582 * Returns: %TRUE if successful, %FALSE otherwise.
586 * gst_byte_reader_get_uint64_be:
587 * @reader: a #GstByteReader instance
588 * @val: (out): Pointer to a #guint64 to store the result
590 * Read an unsigned 64 bit big endian integer into @val
591 * and update the current position.
593 * Returns: %TRUE if successful, %FALSE otherwise.
597 * gst_byte_reader_get_int64_be:
598 * @reader: a #GstByteReader instance
599 * @val: (out): Pointer to a #gint64 to store the result
601 * Read a signed 64 bit big endian integer into @val
602 * and update the current position.
604 * Returns: %TRUE if successful, %FALSE otherwise.
608 * gst_byte_reader_peek_uint64_be:
609 * @reader: a #GstByteReader instance
610 * @val: (out): Pointer to a #guint64 to store the result
612 * Read an unsigned 64 bit big endian integer into @val
613 * but keep the current position.
615 * Returns: %TRUE if successful, %FALSE otherwise.
619 * gst_byte_reader_peek_int64_be:
620 * @reader: a #GstByteReader instance
621 * @val: (out): Pointer to a #gint64 to store the result
623 * Read a signed 64 bit big endian integer into @val
624 * but keep the current position.
626 * Returns: %TRUE if successful, %FALSE otherwise.
629 #define GST_BYTE_READER_PEEK_GET(bits,type,name) \
631 gst_byte_reader_get_##name (GstByteReader * reader, type * val) \
633 return _gst_byte_reader_get_##name##_inline (reader, val); \
637 gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \
639 return _gst_byte_reader_peek_##name##_inline (reader, val); \
644 GST_BYTE_READER_PEEK_GET(8,guint8,uint8)
645 GST_BYTE_READER_PEEK_GET(8,gint8,int8)
647 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
648 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
649 GST_BYTE_READER_PEEK_GET(16,gint16,int16_le)
650 GST_BYTE_READER_PEEK_GET(16,gint16,int16_be)
652 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
653 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
654 GST_BYTE_READER_PEEK_GET(24,gint32,int24_le)
655 GST_BYTE_READER_PEEK_GET(24,gint32,int24_be)
657 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
658 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
659 GST_BYTE_READER_PEEK_GET(32,gint32,int32_le)
660 GST_BYTE_READER_PEEK_GET(32,gint32,int32_be)
662 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
663 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
664 GST_BYTE_READER_PEEK_GET(64,gint64,int64_le)
665 GST_BYTE_READER_PEEK_GET(64,gint64,int64_be)
668 * gst_byte_reader_get_float32_le:
669 * @reader: a #GstByteReader instance
670 * @val: (out): Pointer to a #gfloat to store the result
672 * Read a 32 bit little endian floating point value into @val
673 * and update the current position.
675 * Returns: %TRUE if successful, %FALSE otherwise.
679 * gst_byte_reader_peek_float32_le:
680 * @reader: a #GstByteReader instance
681 * @val: (out): Pointer to a #gfloat to store the result
683 * Read a 32 bit little endian floating point value into @val
684 * but keep the current position.
686 * Returns: %TRUE if successful, %FALSE otherwise.
690 * gst_byte_reader_get_float32_be:
691 * @reader: a #GstByteReader instance
692 * @val: (out): Pointer to a #gfloat to store the result
694 * Read a 32 bit big endian floating point value into @val
695 * and update the current position.
697 * Returns: %TRUE if successful, %FALSE otherwise.
701 * gst_byte_reader_peek_float32_be:
702 * @reader: a #GstByteReader instance
703 * @val: (out): Pointer to a #gfloat to store the result
705 * Read a 32 bit big endian floating point value into @val
706 * but keep the current position.
708 * Returns: %TRUE if successful, %FALSE otherwise.
712 * gst_byte_reader_get_float64_le:
713 * @reader: a #GstByteReader instance
714 * @val: (out): Pointer to a #gdouble to store the result
716 * Read a 64 bit little endian floating point value into @val
717 * and update the current position.
719 * Returns: %TRUE if successful, %FALSE otherwise.
723 * gst_byte_reader_peek_float64_le:
724 * @reader: a #GstByteReader instance
725 * @val: (out): Pointer to a #gdouble to store the result
727 * Read a 64 bit little endian floating point value into @val
728 * but keep the current position.
730 * Returns: %TRUE if successful, %FALSE otherwise.
734 * gst_byte_reader_get_float64_be:
735 * @reader: a #GstByteReader instance
736 * @val: (out): Pointer to a #gdouble to store the result
738 * Read a 64 bit big endian floating point value into @val
739 * and update the current position.
741 * Returns: %TRUE if successful, %FALSE otherwise.
745 * gst_byte_reader_peek_float64_be:
746 * @reader: a #GstByteReader instance
747 * @val: (out): Pointer to a #gdouble to store the result
749 * Read a 64 bit big endian floating point value into @val
750 * but keep the current position.
752 * Returns: %TRUE if successful, %FALSE otherwise.
755 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
756 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
757 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
758 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
763 * gst_byte_reader_get_data:
764 * @reader: a #GstByteReader instance
765 * @size: Size in bytes
766 * @val: (out) (transfer none) (array length=size): address of a
767 * #guint8 pointer variable in which to store the result
769 * Returns a constant pointer to the current data
770 * position if at least @size bytes are left and
771 * updates the current position.
773 * Returns: %TRUE if successful, %FALSE otherwise.
776 gst_byte_reader_get_data (GstByteReader * reader, guint size,
779 return _gst_byte_reader_get_data_inline (reader, size, val);
783 * gst_byte_reader_peek_data:
784 * @reader: a #GstByteReader instance
785 * @size: Size in bytes
786 * @val: (out) (transfer none) (array length=size): address of a
787 * #guint8 pointer variable in which to store the result
789 * Returns a constant pointer to the current data
790 * position if at least @size bytes are left and
791 * keeps the current position.
793 * Returns: %TRUE if successful, %FALSE otherwise.
796 gst_byte_reader_peek_data (const GstByteReader * reader, guint size,
799 return _gst_byte_reader_peek_data_inline (reader, size, val);
803 * gst_byte_reader_dup_data:
804 * @reader: a #GstByteReader instance
805 * @size: Size in bytes
806 * @val: (out) (transfer full) (array length=size): address of a
807 * #guint8 pointer variable in which to store the result
809 * Free-function: g_free
811 * Returns a newly-allocated copy of the current data
812 * position if at least @size bytes are left and
813 * updates the current position. Free with g_free() when no longer needed.
815 * Returns: %TRUE if successful, %FALSE otherwise.
818 gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
820 return _gst_byte_reader_dup_data_inline (reader, size, val);
823 /* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
825 _scan_for_start_code (const guint8 * data, guint size)
827 guint8 *pdata = (guint8 *) data;
828 guint8 *pend = (guint8 *) (data + size - 4);
830 while (pdata <= pend) {
833 } else if (pdata[1]) {
835 } else if (pdata[0] || pdata[2] != 1) {
838 return (pdata - data);
847 _masked_scan_uint32_peek (const GstByteReader * reader,
848 guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
854 g_return_val_if_fail (size > 0, -1);
855 g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
858 /* we can't find the pattern with less than 4 bytes */
859 if (G_UNLIKELY (size < 4))
862 data = reader->data + reader->byte + offset;
864 /* Handle special case found in MPEG and H264 */
865 if ((pattern == 0x00000100) && (mask == 0xffffff00)) {
866 gint ret = _scan_for_start_code (data, size);
872 *value = (1 << 8) | data[ret + 3];
877 /* set the state to something that does not match */
881 for (i = 0; i < size; i++) {
882 /* throw away one byte and move in the next byte */
883 state = ((state << 8) | data[i]);
884 if (G_UNLIKELY ((state & mask) == pattern)) {
885 /* we have a match but we need to have skipped at
886 * least 4 bytes to fill the state. */
887 if (G_LIKELY (i >= 3)) {
890 return offset + i - 3;
901 * gst_byte_reader_masked_scan_uint32:
902 * @reader: a #GstByteReader
903 * @mask: mask to apply to data before matching against @pattern
904 * @pattern: pattern to match (after mask is applied)
905 * @offset: offset from which to start scanning, relative to the current
907 * @size: number of bytes to scan from offset
909 * Scan for pattern @pattern with applied mask @mask in the byte reader data,
910 * starting from offset @offset relative to the current position.
912 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
913 * of endianness. All four bytes of the pattern must be present in the
914 * byte reader data for it to match, even if the first or last bytes are masked
917 * It is an error to call this function without making sure that there is
918 * enough data (offset+size bytes) in the byte reader.
920 * Returns: offset of the first match, or -1 if no match was found.
924 * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
926 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
928 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
930 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
932 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
934 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
936 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
938 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
943 gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
944 guint32 pattern, guint offset, guint size)
946 return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
950 * gst_byte_reader_masked_scan_uint32_peek:
951 * @reader: a #GstByteReader
952 * @mask: mask to apply to data before matching against @pattern
953 * @pattern: pattern to match (after mask is applied)
954 * @offset: offset from which to start scanning, relative to the current
956 * @size: number of bytes to scan from offset
957 * @value: (out): pointer to uint32 to return matching data
959 * Scan for pattern @pattern with applied mask @mask in the byte reader data,
960 * starting from offset @offset relative to the current position.
962 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
963 * of endianness. All four bytes of the pattern must be present in the
964 * byte reader data for it to match, even if the first or last bytes are masked
967 * It is an error to call this function without making sure that there is
968 * enough data (offset+size bytes) in the byte reader.
970 * Returns: offset of the first match, or -1 if no match was found.
975 gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
976 guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
978 return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value);
981 #define GST_BYTE_READER_SCAN_STRING(bits) \
983 gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \
985 guint len, off, max_len; \
987 max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
989 /* need at least a single NUL terminator */ \
994 off = reader->byte; \
995 /* endianness does not matter if we are looking for a NUL terminator */ \
996 while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
998 off += sizeof (guint##bits); \
999 /* have we reached the end without finding a NUL terminator? */ \
1000 if (len == max_len) \
1003 /* return size in bytes including the NUL terminator (hence the +1) */ \
1004 return (len + 1) * sizeof (guint##bits); \
1007 #define GST_READ_UINT8_LE GST_READ_UINT8
1008 GST_BYTE_READER_SCAN_STRING (8);
1009 #undef GST_READ_UINT8_LE
1010 GST_BYTE_READER_SCAN_STRING (16);
1011 GST_BYTE_READER_SCAN_STRING (32);
1013 #define GST_BYTE_READER_SKIP_STRING(bits) \
1015 gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
1017 guint size; /* size in bytes including the terminator */ \
1019 g_return_val_if_fail (reader != NULL, FALSE); \
1021 size = gst_byte_reader_scan_string_utf##bits (reader); \
1022 reader->byte += size; \
1023 return (size > 0); \
1027 * gst_byte_reader_skip_string:
1028 * @reader: a #GstByteReader instance
1030 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1031 * the current position to the byte after the string. This will work for
1032 * any NUL-terminated string with a character width of 8 bits, so ASCII,
1033 * UTF-8, ISO-8859-N etc.
1035 * This function will fail if no NUL-terminator was found in in the data.
1037 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1040 * gst_byte_reader_skip_string_utf8:
1041 * @reader: a #GstByteReader instance
1043 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1044 * the current position to the byte after the string. This will work for
1045 * any NUL-terminated string with a character width of 8 bits, so ASCII,
1046 * UTF-8, ISO-8859-N etc. 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 skipped, %FALSE otherwise.
1052 GST_BYTE_READER_SKIP_STRING (8);
1055 * gst_byte_reader_skip_string_utf16:
1056 * @reader: a #GstByteReader instance
1058 * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
1059 * advancing the current position to the byte after the string.
1061 * No input checking for valid UTF-16 is done.
1063 * This function will fail if no NUL-terminator was found in in the data.
1065 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1067 GST_BYTE_READER_SKIP_STRING (16);
1070 * gst_byte_reader_skip_string_utf32:
1071 * @reader: a #GstByteReader instance
1073 * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
1074 * advancing the current position to the byte after the string.
1076 * No input checking for valid UTF-32 is done.
1078 * This function will fail if no NUL-terminator was found in in the data.
1080 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1082 GST_BYTE_READER_SKIP_STRING (32);
1085 * gst_byte_reader_peek_string:
1086 * @reader: a #GstByteReader instance
1087 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1088 * #gchar pointer variable in which to store the result
1090 * Returns a constant pointer to the current data position if there is
1091 * a NUL-terminated string in the data (this could be just a NUL terminator).
1092 * The current position will be maintained. This will work for any
1093 * NUL-terminated string with a character width of 8 bits, so ASCII,
1094 * UTF-8, ISO-8859-N etc.
1096 * This function will fail if no NUL-terminator was found in in the data.
1098 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1101 * gst_byte_reader_peek_string_utf8:
1102 * @reader: a #GstByteReader instance
1103 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1104 * #gchar pointer variable in which to store the result
1106 * Returns a constant pointer to the current data position if there is
1107 * a NUL-terminated string in the data (this could be just a NUL terminator).
1108 * The current position will be maintained. This will work for any
1109 * NUL-terminated string with a character width of 8 bits, so ASCII,
1110 * UTF-8, ISO-8859-N etc.
1112 * No input checking for valid UTF-8 is done.
1114 * This function will fail if no NUL-terminator was found in in the data.
1116 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1119 gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
1122 g_return_val_if_fail (reader != NULL, FALSE);
1123 g_return_val_if_fail (str != NULL, FALSE);
1125 if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
1126 *str = (const gchar *) (reader->data + reader->byte);
1130 return (*str != NULL);
1134 * gst_byte_reader_get_string_utf8:
1135 * @reader: a #GstByteReader instance
1136 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1137 * #gchar pointer variable in which to store the result
1139 * Returns a constant pointer to the current data position if there is
1140 * a NUL-terminated string in the data (this could be just a NUL terminator),
1141 * advancing the current position to the byte after the string. This will work
1142 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1143 * UTF-8, ISO-8859-N etc.
1145 * No input checking for valid UTF-8 is done.
1147 * This function will fail if no NUL-terminator was found in in the data.
1149 * Returns: %TRUE if a string could be found, %FALSE otherwise.
1152 gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
1154 guint size; /* size in bytes including the terminator */
1156 g_return_val_if_fail (reader != NULL, FALSE);
1157 g_return_val_if_fail (str != NULL, FALSE);
1159 size = gst_byte_reader_scan_string_utf8 (reader);
1165 *str = (const gchar *) (reader->data + reader->byte);
1166 reader->byte += size;
1170 #define GST_BYTE_READER_DUP_STRING(bits,type) \
1172 gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
1174 guint size; /* size in bytes including the terminator */ \
1176 g_return_val_if_fail (reader != NULL, FALSE); \
1177 g_return_val_if_fail (str != NULL, FALSE); \
1179 size = gst_byte_reader_scan_string_utf##bits (reader); \
1184 *str = g_memdup (reader->data + reader->byte, size); \
1185 reader->byte += size; \
1190 * gst_byte_reader_dup_string_utf8:
1191 * @reader: a #GstByteReader instance
1192 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1193 * #gchar pointer variable in which to store the result
1195 * Free-function: g_free
1197 * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
1198 * advancing the current position to the byte after the string. This will work
1199 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1200 * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1202 * This function will fail if no NUL-terminator was found in in the data.
1204 * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
1205 * string put into @str must be freed with g_free() when no longer needed.
1207 GST_BYTE_READER_DUP_STRING (8, gchar);
1210 * gst_byte_reader_dup_string_utf16:
1211 * @reader: a #GstByteReader instance
1212 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1213 * #guint16 pointer variable in which to store the result
1215 * Free-function: g_free
1217 * Returns a newly-allocated copy of the current data position if there is
1218 * a NUL-terminated UTF-16 string in the data (this could be an empty string
1219 * as well), and advances the current position.
1221 * No input checking for valid UTF-16 is done. This function is endianness
1222 * agnostic - you should not assume the UTF-16 characters are in host
1225 * This function will fail if no NUL-terminator was found in in the data.
1227 * Note: there is no peek or get variant of this function to ensure correct
1228 * byte alignment of the UTF-16 string.
1230 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1231 * string put into @str must be freed with g_free() when no longer needed.
1233 GST_BYTE_READER_DUP_STRING (16, guint16);
1236 * gst_byte_reader_dup_string_utf32:
1237 * @reader: a #GstByteReader instance
1238 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1239 * #guint32 pointer variable in which to store the result
1241 * Free-function: g_free
1243 * Returns a newly-allocated copy of the current data position if there is
1244 * a NUL-terminated UTF-32 string in the data (this could be an empty string
1245 * as well), and advances the current position.
1247 * No input checking for valid UTF-32 is done. This function is endianness
1248 * agnostic - you should not assume the UTF-32 characters are in host
1251 * This function will fail if no NUL-terminator was found in in the data.
1253 * Note: there is no peek or get variant of this function to ensure correct
1254 * byte alignment of the UTF-32 string.
1256 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1257 * string put into @str must be freed with g_free() when no longer needed.
1259 GST_BYTE_READER_DUP_STRING (32, guint32);