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 * @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: (skip)
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_peek_sub_reader: (skip)
104 * @reader: an existing and initialized #GstByteReader instance
105 * @sub_reader: a #GstByteReader instance to initialize as sub-reader
106 * @size: size of @sub_reader in bytes
108 * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
109 * data from the current position of @reader. This is useful to read chunked
110 * formats and make sure that one doesn't read beyond the size of the sub-chunk.
112 * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the
113 * current position of @reader.
115 * Returns: FALSE on error or if @reader does not contain @size more bytes from
116 * the current position, and otherwise TRUE
121 gst_byte_reader_peek_sub_reader (GstByteReader * reader,
122 GstByteReader * sub_reader, guint size)
124 return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
128 * gst_byte_reader_get_sub_reader: (skip)
129 * @reader: an existing and initialized #GstByteReader instance
130 * @sub_reader: a #GstByteReader instance to initialize as sub-reader
131 * @size: size of @sub_reader in bytes
133 * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
134 * data from the current position of @reader. This is useful to read chunked
135 * formats and make sure that one doesn't read beyond the size of the sub-chunk.
137 * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the
138 * position of @reader and moves it forward by @size bytes.
140 * Returns: FALSE on error or if @reader does not contain @size more bytes from
141 * the current position, and otherwise TRUE
146 gst_byte_reader_get_sub_reader (GstByteReader * reader,
147 GstByteReader * sub_reader, guint size)
149 return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
153 * gst_byte_reader_set_pos:
154 * @reader: a #GstByteReader instance
155 * @pos: The new position in bytes
157 * Sets the new position of a #GstByteReader instance to @pos in bytes.
159 * Returns: %TRUE if the position could be set successfully, %FALSE
163 gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
165 g_return_val_if_fail (reader != NULL, FALSE);
167 if (pos > reader->size)
176 * gst_byte_reader_get_pos:
177 * @reader: a #GstByteReader instance
179 * Returns the current position of a #GstByteReader instance in bytes.
181 * Returns: The current position of @reader in bytes.
184 gst_byte_reader_get_pos (const GstByteReader * reader)
186 return _gst_byte_reader_get_pos_inline (reader);
190 * gst_byte_reader_get_remaining:
191 * @reader: a #GstByteReader instance
193 * Returns the remaining number of bytes of a #GstByteReader instance.
195 * Returns: The remaining number of bytes of @reader instance.
198 gst_byte_reader_get_remaining (const GstByteReader * reader)
200 return _gst_byte_reader_get_remaining_inline (reader);
204 * gst_byte_reader_get_size:
205 * @reader: a #GstByteReader instance
207 * Returns the total number of bytes of a #GstByteReader instance.
209 * Returns: The total number of bytes of @reader instance.
212 gst_byte_reader_get_size (const GstByteReader * reader)
214 return _gst_byte_reader_get_size_inline (reader);
217 #define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline
218 #define gst_byte_reader_get_size _gst_byte_reader_get_size_inline
221 * gst_byte_reader_skip:
222 * @reader: a #GstByteReader instance
223 * @nbytes: the number of bytes to skip
225 * Skips @nbytes bytes of the #GstByteReader instance.
227 * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
230 gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
232 return _gst_byte_reader_skip_inline (reader, nbytes);
236 * gst_byte_reader_get_uint8:
237 * @reader: a #GstByteReader instance
238 * @val: (out): Pointer to a #guint8 to store the result
240 * Read an unsigned 8 bit integer into @val and update the current position.
242 * Returns: %TRUE if successful, %FALSE otherwise.
246 * gst_byte_reader_get_int8:
247 * @reader: a #GstByteReader instance
248 * @val: (out): Pointer to a #gint8 to store the result
250 * Read a signed 8 bit integer into @val and update the current position.
252 * Returns: %TRUE if successful, %FALSE otherwise.
256 * gst_byte_reader_peek_uint8:
257 * @reader: a #GstByteReader instance
258 * @val: (out): Pointer to a #guint8 to store the result
260 * Read an unsigned 8 bit integer into @val but keep the current position.
262 * Returns: %TRUE if successful, %FALSE otherwise.
266 * gst_byte_reader_peek_int8:
267 * @reader: a #GstByteReader instance
268 * @val: (out): Pointer to a #gint8 to store the result
270 * Read a signed 8 bit integer into @val but keep the current position.
272 * Returns: %TRUE if successful, %FALSE otherwise.
276 * gst_byte_reader_get_uint16_le:
277 * @reader: a #GstByteReader instance
278 * @val: (out): Pointer to a #guint16 to store the result
280 * Read an unsigned 16 bit little endian integer into @val
281 * and update the current position.
283 * Returns: %TRUE if successful, %FALSE otherwise.
287 * gst_byte_reader_get_int16_le:
288 * @reader: a #GstByteReader instance
289 * @val: (out): Pointer to a #gint16 to store the result
291 * Read a signed 16 bit little endian integer into @val
292 * and update the current position.
294 * Returns: %TRUE if successful, %FALSE otherwise.
298 * gst_byte_reader_peek_uint16_le:
299 * @reader: a #GstByteReader instance
300 * @val: (out): Pointer to a #guint16 to store the result
302 * Read an unsigned 16 bit little endian integer into @val
303 * but keep the current position.
305 * Returns: %TRUE if successful, %FALSE otherwise.
309 * gst_byte_reader_peek_int16_le:
310 * @reader: a #GstByteReader instance
311 * @val: (out): Pointer to a #gint16 to store the result
313 * Read a signed 16 bit little endian integer into @val
314 * but keep the current position.
316 * Returns: %TRUE if successful, %FALSE otherwise.
320 * gst_byte_reader_get_uint16_be:
321 * @reader: a #GstByteReader instance
322 * @val: (out): Pointer to a #guint16 to store the result
324 * Read an unsigned 16 bit big endian integer into @val
325 * and update the current position.
327 * Returns: %TRUE if successful, %FALSE otherwise.
331 * gst_byte_reader_get_int16_be:
332 * @reader: a #GstByteReader instance
333 * @val: (out): Pointer to a #gint16 to store the result
335 * Read a signed 16 bit big endian integer into @val
336 * and update the current position.
338 * Returns: %TRUE if successful, %FALSE otherwise.
342 * gst_byte_reader_peek_uint16_be:
343 * @reader: a #GstByteReader instance
344 * @val: (out): Pointer to a #guint16 to store the result
346 * Read an unsigned 16 bit big endian integer into @val
347 * but keep the current position.
349 * Returns: %TRUE if successful, %FALSE otherwise.
353 * gst_byte_reader_peek_int16_be:
354 * @reader: a #GstByteReader instance
355 * @val: (out): Pointer to a #gint16 to store the result
357 * Read a signed 16 bit big endian integer into @val
358 * but keep the current position.
360 * Returns: %TRUE if successful, %FALSE otherwise.
364 * gst_byte_reader_get_uint24_le:
365 * @reader: a #GstByteReader instance
366 * @val: (out): Pointer to a #guint32 to store the result
368 * Read an unsigned 24 bit little endian integer into @val
369 * and update the current position.
371 * Returns: %TRUE if successful, %FALSE otherwise.
375 * gst_byte_reader_get_int24_le:
376 * @reader: a #GstByteReader instance
377 * @val: (out): Pointer to a #gint32 to store the result
379 * Read a signed 24 bit little endian integer into @val
380 * and update the current position.
382 * Returns: %TRUE if successful, %FALSE otherwise.
386 * gst_byte_reader_peek_uint24_le:
387 * @reader: a #GstByteReader instance
388 * @val: (out): Pointer to a #guint32 to store the result
390 * Read an unsigned 24 bit little endian integer into @val
391 * but keep the current position.
393 * Returns: %TRUE if successful, %FALSE otherwise.
397 * gst_byte_reader_peek_int24_le:
398 * @reader: a #GstByteReader instance
399 * @val: (out): Pointer to a #gint32 to store the result
401 * Read a signed 24 bit little endian integer into @val
402 * but keep the current position.
404 * Returns: %TRUE if successful, %FALSE otherwise.
408 * gst_byte_reader_get_uint24_be:
409 * @reader: a #GstByteReader instance
410 * @val: (out): Pointer to a #guint32 to store the result
412 * Read an unsigned 24 bit big endian integer into @val
413 * and update the current position.
415 * Returns: %TRUE if successful, %FALSE otherwise.
419 * gst_byte_reader_get_int24_be:
420 * @reader: a #GstByteReader instance
421 * @val: (out): Pointer to a #gint32 to store the result
423 * Read a signed 24 bit big endian integer into @val
424 * and update the current position.
426 * Returns: %TRUE if successful, %FALSE otherwise.
430 * gst_byte_reader_peek_uint24_be:
431 * @reader: a #GstByteReader instance
432 * @val: (out): Pointer to a #guint32 to store the result
434 * Read an unsigned 24 bit big endian integer into @val
435 * but keep the current position.
437 * Returns: %TRUE if successful, %FALSE otherwise.
441 * gst_byte_reader_peek_int24_be:
442 * @reader: a #GstByteReader instance
443 * @val: (out): Pointer to a #gint32 to store the result
445 * Read a signed 24 bit big endian integer into @val
446 * but keep the current position.
448 * Returns: %TRUE if successful, %FALSE otherwise.
453 * gst_byte_reader_get_uint32_le:
454 * @reader: a #GstByteReader instance
455 * @val: (out): Pointer to a #guint32 to store the result
457 * Read an unsigned 32 bit little endian integer into @val
458 * and update the current position.
460 * Returns: %TRUE if successful, %FALSE otherwise.
464 * gst_byte_reader_get_int32_le:
465 * @reader: a #GstByteReader instance
466 * @val: (out): Pointer to a #gint32 to store the result
468 * Read a signed 32 bit little endian integer into @val
469 * and update the current position.
471 * Returns: %TRUE if successful, %FALSE otherwise.
475 * gst_byte_reader_peek_uint32_le:
476 * @reader: a #GstByteReader instance
477 * @val: (out): Pointer to a #guint32 to store the result
479 * Read an unsigned 32 bit little endian integer into @val
480 * but keep the current position.
482 * Returns: %TRUE if successful, %FALSE otherwise.
486 * gst_byte_reader_peek_int32_le:
487 * @reader: a #GstByteReader instance
488 * @val: (out): Pointer to a #gint32 to store the result
490 * Read a signed 32 bit little endian integer into @val
491 * but keep the current position.
493 * Returns: %TRUE if successful, %FALSE otherwise.
497 * gst_byte_reader_get_uint32_be:
498 * @reader: a #GstByteReader instance
499 * @val: (out): Pointer to a #guint32 to store the result
501 * Read an unsigned 32 bit big endian integer into @val
502 * and update the current position.
504 * Returns: %TRUE if successful, %FALSE otherwise.
508 * gst_byte_reader_get_int32_be:
509 * @reader: a #GstByteReader instance
510 * @val: (out): Pointer to a #gint32 to store the result
512 * Read a signed 32 bit big endian integer into @val
513 * and update the current position.
515 * Returns: %TRUE if successful, %FALSE otherwise.
519 * gst_byte_reader_peek_uint32_be:
520 * @reader: a #GstByteReader instance
521 * @val: (out): Pointer to a #guint32 to store the result
523 * Read an unsigned 32 bit big endian integer into @val
524 * but keep the current position.
526 * Returns: %TRUE if successful, %FALSE otherwise.
530 * gst_byte_reader_peek_int32_be:
531 * @reader: a #GstByteReader instance
532 * @val: (out): Pointer to a #gint32 to store the result
534 * Read a signed 32 bit big endian integer into @val
535 * but keep the current position.
537 * Returns: %TRUE if successful, %FALSE otherwise.
541 * gst_byte_reader_get_uint64_le:
542 * @reader: a #GstByteReader instance
543 * @val: (out): Pointer to a #guint64 to store the result
545 * Read an unsigned 64 bit little endian integer into @val
546 * and update the current position.
548 * Returns: %TRUE if successful, %FALSE otherwise.
552 * gst_byte_reader_get_int64_le:
553 * @reader: a #GstByteReader instance
554 * @val: (out): Pointer to a #gint64 to store the result
556 * Read a signed 64 bit little endian integer into @val
557 * and update the current position.
559 * Returns: %TRUE if successful, %FALSE otherwise.
563 * gst_byte_reader_peek_uint64_le:
564 * @reader: a #GstByteReader instance
565 * @val: (out): Pointer to a #guint64 to store the result
567 * Read an unsigned 64 bit little endian integer into @val
568 * but keep the current position.
570 * Returns: %TRUE if successful, %FALSE otherwise.
574 * gst_byte_reader_peek_int64_le:
575 * @reader: a #GstByteReader instance
576 * @val: (out): Pointer to a #gint64 to store the result
578 * Read a signed 64 bit little endian integer into @val
579 * but keep the current position.
581 * Returns: %TRUE if successful, %FALSE otherwise.
585 * gst_byte_reader_get_uint64_be:
586 * @reader: a #GstByteReader instance
587 * @val: (out): Pointer to a #guint64 to store the result
589 * Read an unsigned 64 bit big endian integer into @val
590 * and update the current position.
592 * Returns: %TRUE if successful, %FALSE otherwise.
596 * gst_byte_reader_get_int64_be:
597 * @reader: a #GstByteReader instance
598 * @val: (out): Pointer to a #gint64 to store the result
600 * Read a signed 64 bit big endian integer into @val
601 * and update the current position.
603 * Returns: %TRUE if successful, %FALSE otherwise.
607 * gst_byte_reader_peek_uint64_be:
608 * @reader: a #GstByteReader instance
609 * @val: (out): Pointer to a #guint64 to store the result
611 * Read an unsigned 64 bit big endian integer into @val
612 * but keep the current position.
614 * Returns: %TRUE if successful, %FALSE otherwise.
618 * gst_byte_reader_peek_int64_be:
619 * @reader: a #GstByteReader instance
620 * @val: (out): Pointer to a #gint64 to store the result
622 * Read a signed 64 bit big endian integer into @val
623 * but keep the current position.
625 * Returns: %TRUE if successful, %FALSE otherwise.
628 #define GST_BYTE_READER_PEEK_GET(bits,type,name) \
630 gst_byte_reader_get_##name (GstByteReader * reader, type * val) \
632 return _gst_byte_reader_get_##name##_inline (reader, val); \
636 gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \
638 return _gst_byte_reader_peek_##name##_inline (reader, val); \
643 GST_BYTE_READER_PEEK_GET(8,guint8,uint8)
644 GST_BYTE_READER_PEEK_GET(8,gint8,int8)
646 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
647 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
648 GST_BYTE_READER_PEEK_GET(16,gint16,int16_le)
649 GST_BYTE_READER_PEEK_GET(16,gint16,int16_be)
651 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
652 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
653 GST_BYTE_READER_PEEK_GET(24,gint32,int24_le)
654 GST_BYTE_READER_PEEK_GET(24,gint32,int24_be)
656 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
657 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
658 GST_BYTE_READER_PEEK_GET(32,gint32,int32_le)
659 GST_BYTE_READER_PEEK_GET(32,gint32,int32_be)
661 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
662 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
663 GST_BYTE_READER_PEEK_GET(64,gint64,int64_le)
664 GST_BYTE_READER_PEEK_GET(64,gint64,int64_be)
667 * gst_byte_reader_get_float32_le:
668 * @reader: a #GstByteReader instance
669 * @val: (out): Pointer to a #gfloat to store the result
671 * Read a 32 bit little endian floating point value into @val
672 * and update the current position.
674 * Returns: %TRUE if successful, %FALSE otherwise.
678 * gst_byte_reader_peek_float32_le:
679 * @reader: a #GstByteReader instance
680 * @val: (out): Pointer to a #gfloat to store the result
682 * Read a 32 bit little endian floating point value into @val
683 * but keep the current position.
685 * Returns: %TRUE if successful, %FALSE otherwise.
689 * gst_byte_reader_get_float32_be:
690 * @reader: a #GstByteReader instance
691 * @val: (out): Pointer to a #gfloat to store the result
693 * Read a 32 bit big endian floating point value into @val
694 * and update the current position.
696 * Returns: %TRUE if successful, %FALSE otherwise.
700 * gst_byte_reader_peek_float32_be:
701 * @reader: a #GstByteReader instance
702 * @val: (out): Pointer to a #gfloat to store the result
704 * Read a 32 bit big endian floating point value into @val
705 * but keep the current position.
707 * Returns: %TRUE if successful, %FALSE otherwise.
711 * gst_byte_reader_get_float64_le:
712 * @reader: a #GstByteReader instance
713 * @val: (out): Pointer to a #gdouble to store the result
715 * Read a 64 bit little endian floating point value into @val
716 * and update the current position.
718 * Returns: %TRUE if successful, %FALSE otherwise.
722 * gst_byte_reader_peek_float64_le:
723 * @reader: a #GstByteReader instance
724 * @val: (out): Pointer to a #gdouble to store the result
726 * Read a 64 bit little endian floating point value into @val
727 * but keep the current position.
729 * Returns: %TRUE if successful, %FALSE otherwise.
733 * gst_byte_reader_get_float64_be:
734 * @reader: a #GstByteReader instance
735 * @val: (out): Pointer to a #gdouble to store the result
737 * Read a 64 bit big endian floating point value into @val
738 * and update the current position.
740 * Returns: %TRUE if successful, %FALSE otherwise.
744 * gst_byte_reader_peek_float64_be:
745 * @reader: a #GstByteReader instance
746 * @val: (out): Pointer to a #gdouble to store the result
748 * Read a 64 bit big endian floating point value into @val
749 * but keep the current position.
751 * Returns: %TRUE if successful, %FALSE otherwise.
754 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
755 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
756 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
757 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
762 * gst_byte_reader_get_data:
763 * @reader: a #GstByteReader instance
764 * @size: Size in bytes
765 * @val: (out) (transfer none) (array length=size): address of a
766 * #guint8 pointer variable in which to store the result
768 * Returns a constant pointer to the current data
769 * position if at least @size bytes are left and
770 * 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.
794 * Returns: %TRUE if successful, %FALSE otherwise.
797 gst_byte_reader_peek_data (const GstByteReader * reader, guint size,
800 return _gst_byte_reader_peek_data_inline (reader, size, val);
804 * gst_byte_reader_dup_data:
805 * @reader: a #GstByteReader instance
806 * @size: Size in bytes
807 * @val: (out) (transfer full) (array length=size): address of a
808 * #guint8 pointer variable in which to store the result
810 * Free-function: g_free
812 * Returns a newly-allocated copy of the current data
813 * position if at least @size bytes are left and
814 * updates the current position. Free with g_free() when no longer needed.
816 * Returns: %TRUE if successful, %FALSE otherwise.
819 gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
821 return _gst_byte_reader_dup_data_inline (reader, size, val);
824 /* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
826 _scan_for_start_code (const guint8 * data, guint offset, guint size)
828 guint8 *pdata = (guint8 *) data;
829 guint8 *pend = (guint8 *) (data + size - 4);
831 while (pdata <= pend) {
834 } else if (pdata[1]) {
836 } else if (pdata[0] || pdata[2] != 1) {
839 return (pdata - data + offset);
848 _masked_scan_uint32_peek (const GstByteReader * reader,
849 guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
855 g_return_val_if_fail (size > 0, -1);
856 g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
859 /* we can't find the pattern with less than 4 bytes */
860 if (G_UNLIKELY (size < 4))
863 data = reader->data + reader->byte + offset;
865 /* Handle special case found in MPEG and H264 */
866 if ((pattern == 0x00000100) && (mask == 0xffffff00)) {
867 guint ret = _scan_for_start_code (data, offset, size);
868 if (G_UNLIKELY (value))
869 *value = (1 << 8) | data[ret + 3];
873 /* set the state to something that does not match */
877 for (i = 0; i < size; i++) {
878 /* throw away one byte and move in the next byte */
879 state = ((state << 8) | data[i]);
880 if (G_UNLIKELY ((state & mask) == pattern)) {
881 /* we have a match but we need to have skipped at
882 * least 4 bytes to fill the state. */
883 if (G_LIKELY (i >= 3)) {
886 return offset + i - 3;
897 * gst_byte_reader_masked_scan_uint32:
898 * @reader: a #GstByteReader
899 * @mask: mask to apply to data before matching against @pattern
900 * @pattern: pattern to match (after mask is applied)
901 * @offset: offset from which to start scanning, relative to the current
903 * @size: number of bytes to scan from offset
905 * Scan for pattern @pattern with applied mask @mask in the byte reader data,
906 * starting from offset @offset relative to the current position.
908 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
909 * of endianness. All four bytes of the pattern must be present in the
910 * byte reader data for it to match, even if the first or last bytes are masked
913 * It is an error to call this function without making sure that there is
914 * enough data (offset+size bytes) in the byte reader.
916 * Returns: offset of the first match, or -1 if no match was found.
920 * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
922 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
924 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
926 * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
928 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
930 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
932 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
934 * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
939 gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
940 guint32 pattern, guint offset, guint size)
942 return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
946 * gst_byte_reader_masked_scan_uint32_peek:
947 * @reader: a #GstByteReader
948 * @mask: mask to apply to data before matching against @pattern
949 * @pattern: pattern to match (after mask is applied)
950 * @offset: offset from which to start scanning, relative to the current
952 * @size: number of bytes to scan from offset
953 * @value: pointer to uint32 to return matching data
955 * Scan for pattern @pattern with applied mask @mask in the byte reader data,
956 * starting from offset @offset relative to the current position.
958 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
959 * of endianness. All four bytes of the pattern must be present in the
960 * byte reader data for it to match, even if the first or last bytes are masked
963 * It is an error to call this function without making sure that there is
964 * enough data (offset+size bytes) in the byte reader.
966 * Returns: offset of the first match, or -1 if no match was found.
971 gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
972 guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
974 return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value);
977 #define GST_BYTE_READER_SCAN_STRING(bits) \
979 gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \
981 guint len, off, max_len; \
983 max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
985 /* need at least a single NUL terminator */ \
990 off = reader->byte; \
991 /* endianness does not matter if we are looking for a NUL terminator */ \
992 while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
994 off += sizeof (guint##bits); \
995 /* have we reached the end without finding a NUL terminator? */ \
996 if (len == max_len) \
999 /* return size in bytes including the NUL terminator (hence the +1) */ \
1000 return (len + 1) * sizeof (guint##bits); \
1003 #define GST_READ_UINT8_LE GST_READ_UINT8
1004 GST_BYTE_READER_SCAN_STRING (8);
1005 #undef GST_READ_UINT8_LE
1006 GST_BYTE_READER_SCAN_STRING (16);
1007 GST_BYTE_READER_SCAN_STRING (32);
1009 #define GST_BYTE_READER_SKIP_STRING(bits) \
1011 gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
1013 guint size; /* size in bytes including the terminator */ \
1015 g_return_val_if_fail (reader != NULL, FALSE); \
1017 size = gst_byte_reader_scan_string_utf##bits (reader); \
1018 reader->byte += size; \
1019 return (size > 0); \
1023 * gst_byte_reader_skip_string:
1024 * @reader: a #GstByteReader instance
1026 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1027 * the current position to the byte after the string. This will work for
1028 * any NUL-terminated string with a character width of 8 bits, so ASCII,
1029 * UTF-8, ISO-8859-N etc.
1031 * This function will fail if no NUL-terminator was found in in the data.
1033 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1036 * gst_byte_reader_skip_string_utf8:
1037 * @reader: a #GstByteReader instance
1039 * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1040 * the current position to the byte after the string. This will work for
1041 * any NUL-terminated string with a character width of 8 bits, so ASCII,
1042 * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1044 * This function will fail if no NUL-terminator was found in in the data.
1046 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1048 GST_BYTE_READER_SKIP_STRING (8);
1051 * gst_byte_reader_skip_string_utf16:
1052 * @reader: a #GstByteReader instance
1054 * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
1055 * advancing the current position to the byte after the string.
1057 * No input checking for valid UTF-16 is done.
1059 * This function will fail if no NUL-terminator was found in in the data.
1061 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1063 GST_BYTE_READER_SKIP_STRING (16);
1066 * gst_byte_reader_skip_string_utf32:
1067 * @reader: a #GstByteReader instance
1069 * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
1070 * advancing the current position to the byte after the string.
1072 * No input checking for valid UTF-32 is done.
1074 * This function will fail if no NUL-terminator was found in in the data.
1076 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1078 GST_BYTE_READER_SKIP_STRING (32);
1081 * gst_byte_reader_peek_string:
1082 * @reader: a #GstByteReader instance
1083 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1084 * #gchar pointer variable in which to store the result
1086 * Returns a constant pointer to the current data position if there is
1087 * a NUL-terminated string in the data (this could be just a NUL terminator).
1088 * The current position will be maintained. This will work for any
1089 * NUL-terminated string with a character width of 8 bits, so ASCII,
1090 * UTF-8, ISO-8859-N etc.
1092 * This function will fail if no NUL-terminator was found in in the data.
1094 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1097 * gst_byte_reader_peek_string_utf8:
1098 * @reader: a #GstByteReader instance
1099 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1100 * #gchar pointer variable in which to store the result
1102 * Returns a constant pointer to the current data position if there is
1103 * a NUL-terminated string in the data (this could be just a NUL terminator).
1104 * The current position will be maintained. This will work for any
1105 * NUL-terminated string with a character width of 8 bits, so ASCII,
1106 * UTF-8, ISO-8859-N etc.
1108 * No input checking for valid UTF-8 is done.
1110 * This function will fail if no NUL-terminator was found in in the data.
1112 * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1115 gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
1118 g_return_val_if_fail (reader != NULL, FALSE);
1119 g_return_val_if_fail (str != NULL, FALSE);
1121 if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
1122 *str = (const gchar *) (reader->data + reader->byte);
1126 return (*str != NULL);
1130 * gst_byte_reader_get_string_utf8:
1131 * @reader: a #GstByteReader instance
1132 * @str: (out) (transfer none) (array zero-terminated=1): address of a
1133 * #gchar pointer variable in which to store the result
1135 * Returns a constant pointer to the current data position if there is
1136 * a NUL-terminated string in the data (this could be just a NUL terminator),
1137 * advancing the current position to the byte after the string. This will work
1138 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1139 * UTF-8, ISO-8859-N etc.
1141 * No input checking for valid UTF-8 is done.
1143 * This function will fail if no NUL-terminator was found in in the data.
1145 * Returns: %TRUE if a string could be found, %FALSE otherwise.
1148 gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
1150 guint size; /* size in bytes including the terminator */
1152 g_return_val_if_fail (reader != NULL, FALSE);
1153 g_return_val_if_fail (str != NULL, FALSE);
1155 size = gst_byte_reader_scan_string_utf8 (reader);
1161 *str = (const gchar *) (reader->data + reader->byte);
1162 reader->byte += size;
1166 #define GST_BYTE_READER_DUP_STRING(bits,type) \
1168 gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
1170 guint size; /* size in bytes including the terminator */ \
1172 g_return_val_if_fail (reader != NULL, FALSE); \
1173 g_return_val_if_fail (str != NULL, FALSE); \
1175 size = gst_byte_reader_scan_string_utf##bits (reader); \
1180 *str = g_memdup (reader->data + reader->byte, size); \
1181 reader->byte += size; \
1186 * gst_byte_reader_dup_string_utf8:
1187 * @reader: a #GstByteReader instance
1188 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1189 * #gchar pointer variable in which to store the result
1191 * Free-function: g_free
1193 * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
1194 * advancing the current position to the byte after the string. This will work
1195 * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1196 * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1198 * This function will fail if no NUL-terminator was found in in the data.
1200 * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
1201 * string put into @str must be freed with g_free() when no longer needed.
1203 GST_BYTE_READER_DUP_STRING (8, gchar);
1206 * gst_byte_reader_dup_string_utf16:
1207 * @reader: a #GstByteReader instance
1208 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1209 * #guint16 pointer variable in which to store the result
1211 * Free-function: g_free
1213 * Returns a newly-allocated copy of the current data position if there is
1214 * a NUL-terminated UTF-16 string in the data (this could be an empty string
1215 * as well), and advances the current position.
1217 * No input checking for valid UTF-16 is done. This function is endianness
1218 * agnostic - you should not assume the UTF-16 characters are in host
1221 * This function will fail if no NUL-terminator was found in in the data.
1223 * Note: there is no peek or get variant of this function to ensure correct
1224 * byte alignment of the UTF-16 string.
1226 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1227 * string put into @str must be freed with g_free() when no longer needed.
1229 GST_BYTE_READER_DUP_STRING (16, guint16);
1232 * gst_byte_reader_dup_string_utf32:
1233 * @reader: a #GstByteReader instance
1234 * @str: (out) (transfer full) (array zero-terminated=1): address of a
1235 * #guint32 pointer variable in which to store the result
1237 * Free-function: g_free
1239 * Returns a newly-allocated copy of the current data position if there is
1240 * a NUL-terminated UTF-32 string in the data (this could be an empty string
1241 * as well), and advances the current position.
1243 * No input checking for valid UTF-32 is done. This function is endianness
1244 * agnostic - you should not assume the UTF-32 characters are in host
1247 * This function will fail if no NUL-terminator was found in in the data.
1249 * Note: there is no peek or get variant of this function to ensure correct
1250 * byte alignment of the UTF-32 string.
1252 * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1253 * string put into @str must be freed with g_free() when no longer needed.
1255 GST_BYTE_READER_DUP_STRING (32, guint32);