• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer byte reader
2  *
3  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4  * Copyright (C) 2009,2014 Tim-Philipp Müller <tim centricular net>
5  *
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.
10  *
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.
15  *
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.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #define GST_BYTE_READER_DISABLE_INLINES
27 #include "gstbytereader.h"
28 
29 #include "gst/glib-compat-private.h"
30 #include <string.h>
31 
32 /**
33  * SECTION:gstbytereader
34  * @title: GstByteReader
35  * @short_description: Reads different integer, string and floating point
36  *     types from a memory buffer
37  * @symbols:
38  * - gst_byte_reader_skip_unchecked
39  * - gst_byte_reader_get_uint8_unchecked
40  * - gst_byte_reader_peek_uint8_unchecked
41  * - gst_byte_reader_get_int8_unchecked
42  * - gst_byte_reader_peek_int8_unchecked
43  * - gst_byte_reader_get_uint16_le_unchecked
44  * - gst_byte_reader_get_uint16_be_unchecked
45  * - gst_byte_reader_peek_uint16_le_unchecked
46  * - gst_byte_reader_peek_uint16_be_unchecked
47  * - gst_byte_reader_get_int16_le_unchecked
48  * - gst_byte_reader_get_int16_be_unchecked
49  * - gst_byte_reader_peek_int16_le_unchecked
50  * - gst_byte_reader_peek_int16_be_unchecked
51  * - gst_byte_reader_get_uint24_le_unchecked
52  * - gst_byte_reader_get_uint24_be_unchecked
53  * - gst_byte_reader_peek_uint24_le_unchecked
54  * - gst_byte_reader_peek_uint24_be_unchecked
55  * - gst_byte_reader_get_int24_le_unchecked
56  * - gst_byte_reader_get_int24_be_unchecked
57  * - gst_byte_reader_peek_int24_le_unchecked
58  * - gst_byte_reader_peek_int24_be_unchecked
59  * - gst_byte_reader_get_uint32_le_unchecked
60  * - gst_byte_reader_get_uint32_be_unchecked
61  * - gst_byte_reader_peek_uint32_le_unchecked
62  * - gst_byte_reader_peek_uint32_be_unchecked
63  * - gst_byte_reader_get_int32_le_unchecked
64  * - gst_byte_reader_get_int32_be_unchecked
65  * - gst_byte_reader_peek_int32_le_unchecked
66  * - gst_byte_reader_peek_int32_be_unchecked
67  * - gst_byte_reader_get_float32_le_unchecked
68  * - gst_byte_reader_get_float32_be_unchecked
69  * - gst_byte_reader_get_float64_le_unchecked
70  * - gst_byte_reader_get_float64_be_unchecked
71  * - gst_byte_reader_peek_float32_le_unchecked
72  * - gst_byte_reader_peek_float32_be_unchecked
73  * - gst_byte_reader_peek_float64_le_unchecked
74  * - gst_byte_reader_peek_float64_be_unchecked
75  * - gst_byte_reader_peek_data_unchecked
76  * - gst_byte_reader_get_data_unchecked
77  * - gst_byte_reader_dup_data_unchecked
78  *
79  * #GstByteReader provides a byte reader that can read different integer and
80  * floating point types from a memory buffer. It provides functions for reading
81  * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
82  * and functions for reading little/big endian floating points numbers of
83  * 32 and 64 bits. It also provides functions to read NUL-terminated strings
84  * in various character encodings.
85  */
86 
87 /**
88  * gst_byte_reader_new: (skip)
89  * @data: (in) (transfer none) (array length=size): data from which the
90  *     #GstByteReader should read
91  * @size: Size of @data in bytes
92  *
93  * Create a new #GstByteReader instance, which will read from @data.
94  *
95  * Free-function: gst_byte_reader_free
96  *
97  * Returns: (transfer full): a new #GstByteReader instance
98  */
99 GstByteReader *
gst_byte_reader_new(const guint8 * data,guint size)100 gst_byte_reader_new (const guint8 * data, guint size)
101 {
102   GstByteReader *ret = g_slice_new0 (GstByteReader);
103 
104   ret->data = data;
105   ret->size = size;
106 
107   return ret;
108 }
109 
110 /**
111  * gst_byte_reader_free:
112  * @reader: (in) (transfer full): a #GstByteReader instance
113  *
114  * Frees a #GstByteReader instance, which was previously allocated by
115  * gst_byte_reader_new().
116  */
117 void
gst_byte_reader_free(GstByteReader * reader)118 gst_byte_reader_free (GstByteReader * reader)
119 {
120   g_return_if_fail (reader != NULL);
121 
122   g_slice_free (GstByteReader, reader);
123 }
124 
125 /**
126  * gst_byte_reader_init:
127  * @reader: a #GstByteReader instance
128  * @data: (in) (transfer none) (array length=size): data from which
129  *     the #GstByteReader should read
130  * @size: Size of @data in bytes
131  *
132  * Initializes a #GstByteReader instance to read from @data. This function
133  * can be called on already initialized instances.
134  */
135 void
gst_byte_reader_init(GstByteReader * reader,const guint8 * data,guint size)136 gst_byte_reader_init (GstByteReader * reader, const guint8 * data, guint size)
137 {
138   g_return_if_fail (reader != NULL);
139 
140   reader->data = data;
141   reader->size = size;
142   reader->byte = 0;
143 }
144 
145 /**
146  * gst_byte_reader_peek_sub_reader: (skip)
147  * @reader: an existing and initialized #GstByteReader instance
148  * @sub_reader: a #GstByteReader instance to initialize as sub-reader
149  * @size: size of @sub_reader in bytes
150  *
151  * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
152  * data from the current position of @reader. This is useful to read chunked
153  * formats and make sure that one doesn't read beyond the size of the sub-chunk.
154  *
155  * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the
156  * current position of @reader.
157  *
158  * Returns: FALSE on error or if @reader does not contain @size more bytes from
159  *     the current position, and otherwise TRUE
160  *
161  * Since: 1.6
162  */
163 gboolean
gst_byte_reader_peek_sub_reader(GstByteReader * reader,GstByteReader * sub_reader,guint size)164 gst_byte_reader_peek_sub_reader (GstByteReader * reader,
165     GstByteReader * sub_reader, guint size)
166 {
167   return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
168 }
169 
170 /**
171  * gst_byte_reader_get_sub_reader: (skip)
172  * @reader: an existing and initialized #GstByteReader instance
173  * @sub_reader: a #GstByteReader instance to initialize as sub-reader
174  * @size: size of @sub_reader in bytes
175  *
176  * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
177  * data from the current position of @reader. This is useful to read chunked
178  * formats and make sure that one doesn't read beyond the size of the sub-chunk.
179  *
180  * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the
181  * position of @reader and moves it forward by @size bytes.
182  *
183  * Returns: FALSE on error or if @reader does not contain @size more bytes from
184  *     the current position, and otherwise TRUE
185  *
186  * Since: 1.6
187  */
188 gboolean
gst_byte_reader_get_sub_reader(GstByteReader * reader,GstByteReader * sub_reader,guint size)189 gst_byte_reader_get_sub_reader (GstByteReader * reader,
190     GstByteReader * sub_reader, guint size)
191 {
192   return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
193 }
194 
195 /**
196  * gst_byte_reader_set_pos:
197  * @reader: a #GstByteReader instance
198  * @pos: The new position in bytes
199  *
200  * Sets the new position of a #GstByteReader instance to @pos in bytes.
201  *
202  * Returns: %TRUE if the position could be set successfully, %FALSE
203  * otherwise.
204  */
205 gboolean
gst_byte_reader_set_pos(GstByteReader * reader,guint pos)206 gst_byte_reader_set_pos (GstByteReader * reader, guint pos)
207 {
208   g_return_val_if_fail (reader != NULL, FALSE);
209 
210   if (pos > reader->size)
211     return FALSE;
212 
213   reader->byte = pos;
214 
215   return TRUE;
216 }
217 
218 /**
219  * gst_byte_reader_get_pos:
220  * @reader: a #GstByteReader instance
221  *
222  * Returns the current position of a #GstByteReader instance in bytes.
223  *
224  * Returns: The current position of @reader in bytes.
225  */
226 guint
gst_byte_reader_get_pos(const GstByteReader * reader)227 gst_byte_reader_get_pos (const GstByteReader * reader)
228 {
229   return _gst_byte_reader_get_pos_inline (reader);
230 }
231 
232 /**
233  * gst_byte_reader_get_remaining:
234  * @reader: a #GstByteReader instance
235  *
236  * Returns the remaining number of bytes of a #GstByteReader instance.
237  *
238  * Returns: The remaining number of bytes of @reader instance.
239  */
240 guint
gst_byte_reader_get_remaining(const GstByteReader * reader)241 gst_byte_reader_get_remaining (const GstByteReader * reader)
242 {
243   return _gst_byte_reader_get_remaining_inline (reader);
244 }
245 
246 /**
247  * gst_byte_reader_get_size:
248  * @reader: a #GstByteReader instance
249  *
250  * Returns the total number of bytes of a #GstByteReader instance.
251  *
252  * Returns: The total number of bytes of @reader instance.
253  */
254 guint
gst_byte_reader_get_size(const GstByteReader * reader)255 gst_byte_reader_get_size (const GstByteReader * reader)
256 {
257   return _gst_byte_reader_get_size_inline (reader);
258 }
259 
260 #define gst_byte_reader_get_remaining _gst_byte_reader_get_remaining_inline
261 #define gst_byte_reader_get_size _gst_byte_reader_get_size_inline
262 
263 /**
264  * gst_byte_reader_skip:
265  * @reader: a #GstByteReader instance
266  * @nbytes: the number of bytes to skip
267  *
268  * Skips @nbytes bytes of the #GstByteReader instance.
269  *
270  * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
271  */
272 gboolean
gst_byte_reader_skip(GstByteReader * reader,guint nbytes)273 gst_byte_reader_skip (GstByteReader * reader, guint nbytes)
274 {
275   return _gst_byte_reader_skip_inline (reader, nbytes);
276 }
277 
278 /**
279  * gst_byte_reader_get_uint8:
280  * @reader: a #GstByteReader instance
281  * @val: (out): Pointer to a #guint8 to store the result
282  *
283  * Read an unsigned 8 bit integer into @val and update the current position.
284  *
285  * Returns: %TRUE if successful, %FALSE otherwise.
286  */
287 
288 /**
289  * gst_byte_reader_get_int8:
290  * @reader: a #GstByteReader instance
291  * @val: (out): Pointer to a #gint8 to store the result
292  *
293  * Read a signed 8 bit integer into @val and update the current position.
294  *
295  * Returns: %TRUE if successful, %FALSE otherwise.
296  */
297 
298 /**
299  * gst_byte_reader_peek_uint8:
300  * @reader: a #GstByteReader instance
301  * @val: (out): Pointer to a #guint8 to store the result
302  *
303  * Read an unsigned 8 bit integer into @val but keep the current position.
304  *
305  * Returns: %TRUE if successful, %FALSE otherwise.
306  */
307 
308 /**
309  * gst_byte_reader_peek_int8:
310  * @reader: a #GstByteReader instance
311  * @val: (out): Pointer to a #gint8 to store the result
312  *
313  * Read a signed 8 bit integer into @val but keep the current position.
314  *
315  * Returns: %TRUE if successful, %FALSE otherwise.
316  */
317 
318 /**
319  * gst_byte_reader_get_uint16_le:
320  * @reader: a #GstByteReader instance
321  * @val: (out): Pointer to a #guint16 to store the result
322  *
323  * Read an unsigned 16 bit little endian integer into @val
324  * and update the current position.
325  *
326  * Returns: %TRUE if successful, %FALSE otherwise.
327  */
328 
329 /**
330  * gst_byte_reader_get_int16_le:
331  * @reader: a #GstByteReader instance
332  * @val: (out): Pointer to a #gint16 to store the result
333  *
334  * Read a signed 16 bit little endian integer into @val
335  * and update the current position.
336  *
337  * Returns: %TRUE if successful, %FALSE otherwise.
338  */
339 
340 /**
341  * gst_byte_reader_peek_uint16_le:
342  * @reader: a #GstByteReader instance
343  * @val: (out): Pointer to a #guint16 to store the result
344  *
345  * Read an unsigned 16 bit little endian integer into @val
346  * but keep the current position.
347  *
348  * Returns: %TRUE if successful, %FALSE otherwise.
349  */
350 
351 /**
352  * gst_byte_reader_peek_int16_le:
353  * @reader: a #GstByteReader instance
354  * @val: (out): Pointer to a #gint16 to store the result
355  *
356  * Read a signed 16 bit little endian integer into @val
357  * but keep the current position.
358  *
359  * Returns: %TRUE if successful, %FALSE otherwise.
360  */
361 
362 /**
363  * gst_byte_reader_get_uint16_be:
364  * @reader: a #GstByteReader instance
365  * @val: (out): Pointer to a #guint16 to store the result
366  *
367  * Read an unsigned 16 bit big endian integer into @val
368  * and update the current position.
369  *
370  * Returns: %TRUE if successful, %FALSE otherwise.
371  */
372 
373 /**
374  * gst_byte_reader_get_int16_be:
375  * @reader: a #GstByteReader instance
376  * @val: (out): Pointer to a #gint16 to store the result
377  *
378  * Read a signed 16 bit big endian integer into @val
379  * and update the current position.
380  *
381  * Returns: %TRUE if successful, %FALSE otherwise.
382  */
383 
384 /**
385  * gst_byte_reader_peek_uint16_be:
386  * @reader: a #GstByteReader instance
387  * @val: (out): Pointer to a #guint16 to store the result
388  *
389  * Read an unsigned 16 bit big endian integer into @val
390  * but keep the current position.
391  *
392  * Returns: %TRUE if successful, %FALSE otherwise.
393  */
394 
395 /**
396  * gst_byte_reader_peek_int16_be:
397  * @reader: a #GstByteReader instance
398  * @val: (out): Pointer to a #gint16 to store the result
399  *
400  * Read a signed 16 bit big endian integer into @val
401  * but keep the current position.
402  *
403  * Returns: %TRUE if successful, %FALSE otherwise.
404  */
405 
406 /**
407  * gst_byte_reader_get_uint24_le:
408  * @reader: a #GstByteReader instance
409  * @val: (out): Pointer to a #guint32 to store the result
410  *
411  * Read an unsigned 24 bit little endian integer into @val
412  * and update the current position.
413  *
414  * Returns: %TRUE if successful, %FALSE otherwise.
415  */
416 
417 /**
418  * gst_byte_reader_get_int24_le:
419  * @reader: a #GstByteReader instance
420  * @val: (out): Pointer to a #gint32 to store the result
421  *
422  * Read a signed 24 bit little endian integer into @val
423  * and update the current position.
424  *
425  * Returns: %TRUE if successful, %FALSE otherwise.
426  */
427 
428 /**
429  * gst_byte_reader_peek_uint24_le:
430  * @reader: a #GstByteReader instance
431  * @val: (out): Pointer to a #guint32 to store the result
432  *
433  * Read an unsigned 24 bit little endian integer into @val
434  * but keep the current position.
435  *
436  * Returns: %TRUE if successful, %FALSE otherwise.
437  */
438 
439 /**
440  * gst_byte_reader_peek_int24_le:
441  * @reader: a #GstByteReader instance
442  * @val: (out): Pointer to a #gint32 to store the result
443  *
444  * Read a signed 24 bit little endian integer into @val
445  * but keep the current position.
446  *
447  * Returns: %TRUE if successful, %FALSE otherwise.
448  */
449 
450 /**
451  * gst_byte_reader_get_uint24_be:
452  * @reader: a #GstByteReader instance
453  * @val: (out): Pointer to a #guint32 to store the result
454  *
455  * Read an unsigned 24 bit big endian integer into @val
456  * and update the current position.
457  *
458  * Returns: %TRUE if successful, %FALSE otherwise.
459  */
460 
461 /**
462  * gst_byte_reader_get_int24_be:
463  * @reader: a #GstByteReader instance
464  * @val: (out): Pointer to a #gint32 to store the result
465  *
466  * Read a signed 24 bit big endian integer into @val
467  * and update the current position.
468  *
469  * Returns: %TRUE if successful, %FALSE otherwise.
470  */
471 
472 /**
473  * gst_byte_reader_peek_uint24_be:
474  * @reader: a #GstByteReader instance
475  * @val: (out): Pointer to a #guint32 to store the result
476  *
477  * Read an unsigned 24 bit big endian integer into @val
478  * but keep the current position.
479  *
480  * Returns: %TRUE if successful, %FALSE otherwise.
481  */
482 
483 /**
484  * gst_byte_reader_peek_int24_be:
485  * @reader: a #GstByteReader instance
486  * @val: (out): Pointer to a #gint32 to store the result
487  *
488  * Read a signed 24 bit big endian integer into @val
489  * but keep the current position.
490  *
491  * Returns: %TRUE if successful, %FALSE otherwise.
492  */
493 
494 
495 /**
496  * gst_byte_reader_get_uint32_le:
497  * @reader: a #GstByteReader instance
498  * @val: (out): Pointer to a #guint32 to store the result
499  *
500  * Read an unsigned 32 bit little endian integer into @val
501  * and update the current position.
502  *
503  * Returns: %TRUE if successful, %FALSE otherwise.
504  */
505 
506 /**
507  * gst_byte_reader_get_int32_le:
508  * @reader: a #GstByteReader instance
509  * @val: (out): Pointer to a #gint32 to store the result
510  *
511  * Read a signed 32 bit little endian integer into @val
512  * and update the current position.
513  *
514  * Returns: %TRUE if successful, %FALSE otherwise.
515  */
516 
517 /**
518  * gst_byte_reader_peek_uint32_le:
519  * @reader: a #GstByteReader instance
520  * @val: (out): Pointer to a #guint32 to store the result
521  *
522  * Read an unsigned 32 bit little endian integer into @val
523  * but keep the current position.
524  *
525  * Returns: %TRUE if successful, %FALSE otherwise.
526  */
527 
528 /**
529  * gst_byte_reader_peek_int32_le:
530  * @reader: a #GstByteReader instance
531  * @val: (out): Pointer to a #gint32 to store the result
532  *
533  * Read a signed 32 bit little endian integer into @val
534  * but keep the current position.
535  *
536  * Returns: %TRUE if successful, %FALSE otherwise.
537  */
538 
539 /**
540  * gst_byte_reader_get_uint32_be:
541  * @reader: a #GstByteReader instance
542  * @val: (out): Pointer to a #guint32 to store the result
543  *
544  * Read an unsigned 32 bit big endian integer into @val
545  * and update the current position.
546  *
547  * Returns: %TRUE if successful, %FALSE otherwise.
548  */
549 
550 /**
551  * gst_byte_reader_get_int32_be:
552  * @reader: a #GstByteReader instance
553  * @val: (out): Pointer to a #gint32 to store the result
554  *
555  * Read a signed 32 bit big endian integer into @val
556  * and update the current position.
557  *
558  * Returns: %TRUE if successful, %FALSE otherwise.
559  */
560 
561 /**
562  * gst_byte_reader_peek_uint32_be:
563  * @reader: a #GstByteReader instance
564  * @val: (out): Pointer to a #guint32 to store the result
565  *
566  * Read an unsigned 32 bit big endian integer into @val
567  * but keep the current position.
568  *
569  * Returns: %TRUE if successful, %FALSE otherwise.
570  */
571 
572 /**
573  * gst_byte_reader_peek_int32_be:
574  * @reader: a #GstByteReader instance
575  * @val: (out): Pointer to a #gint32 to store the result
576  *
577  * Read a signed 32 bit big endian integer into @val
578  * but keep the current position.
579  *
580  * Returns: %TRUE if successful, %FALSE otherwise.
581  */
582 
583 /**
584  * gst_byte_reader_get_uint64_le:
585  * @reader: a #GstByteReader instance
586  * @val: (out): Pointer to a #guint64 to store the result
587  *
588  * Read an unsigned 64 bit little endian integer into @val
589  * and update the current position.
590  *
591  * Returns: %TRUE if successful, %FALSE otherwise.
592  */
593 
594 /**
595  * gst_byte_reader_get_int64_le:
596  * @reader: a #GstByteReader instance
597  * @val: (out): Pointer to a #gint64 to store the result
598  *
599  * Read a signed 64 bit little endian integer into @val
600  * and update the current position.
601  *
602  * Returns: %TRUE if successful, %FALSE otherwise.
603  */
604 
605 /**
606  * gst_byte_reader_peek_uint64_le:
607  * @reader: a #GstByteReader instance
608  * @val: (out): Pointer to a #guint64 to store the result
609  *
610  * Read an unsigned 64 bit little endian integer into @val
611  * but keep the current position.
612  *
613  * Returns: %TRUE if successful, %FALSE otherwise.
614  */
615 
616 /**
617  * gst_byte_reader_peek_int64_le:
618  * @reader: a #GstByteReader instance
619  * @val: (out): Pointer to a #gint64 to store the result
620  *
621  * Read a signed 64 bit little endian integer into @val
622  * but keep the current position.
623  *
624  * Returns: %TRUE if successful, %FALSE otherwise.
625  */
626 
627 /**
628  * gst_byte_reader_get_uint64_be:
629  * @reader: a #GstByteReader instance
630  * @val: (out): Pointer to a #guint64 to store the result
631  *
632  * Read an unsigned 64 bit big endian integer into @val
633  * and update the current position.
634  *
635  * Returns: %TRUE if successful, %FALSE otherwise.
636  */
637 
638 /**
639  * gst_byte_reader_get_int64_be:
640  * @reader: a #GstByteReader instance
641  * @val: (out): Pointer to a #gint64 to store the result
642  *
643  * Read a signed 64 bit big endian integer into @val
644  * and update the current position.
645  *
646  * Returns: %TRUE if successful, %FALSE otherwise.
647  */
648 
649 /**
650  * gst_byte_reader_peek_uint64_be:
651  * @reader: a #GstByteReader instance
652  * @val: (out): Pointer to a #guint64 to store the result
653  *
654  * Read an unsigned 64 bit big endian integer into @val
655  * but keep the current position.
656  *
657  * Returns: %TRUE if successful, %FALSE otherwise.
658  */
659 
660 /**
661  * gst_byte_reader_peek_int64_be:
662  * @reader: a #GstByteReader instance
663  * @val: (out): Pointer to a #gint64 to store the result
664  *
665  * Read a signed 64 bit big endian integer into @val
666  * but keep the current position.
667  *
668  * Returns: %TRUE if successful, %FALSE otherwise.
669  */
670 
671 #define GST_BYTE_READER_PEEK_GET(bits,type,name) \
672 gboolean \
673 gst_byte_reader_get_##name (GstByteReader * reader, type * val) \
674 { \
675   return _gst_byte_reader_get_##name##_inline (reader, val); \
676 } \
677 \
678 gboolean \
679 gst_byte_reader_peek_##name (const GstByteReader * reader, type * val) \
680 { \
681   return _gst_byte_reader_peek_##name##_inline (reader, val); \
682 }
683 
684 /* *INDENT-OFF* */
685 
686 GST_BYTE_READER_PEEK_GET(8,guint8,uint8)
687 GST_BYTE_READER_PEEK_GET(8,gint8,int8)
688 
689 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
690 GST_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
691 GST_BYTE_READER_PEEK_GET(16,gint16,int16_le)
692 GST_BYTE_READER_PEEK_GET(16,gint16,int16_be)
693 
694 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
695 GST_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
696 GST_BYTE_READER_PEEK_GET(24,gint32,int24_le)
697 GST_BYTE_READER_PEEK_GET(24,gint32,int24_be)
698 
699 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
700 GST_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
701 GST_BYTE_READER_PEEK_GET(32,gint32,int32_le)
702 GST_BYTE_READER_PEEK_GET(32,gint32,int32_be)
703 
704 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
705 GST_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
706 GST_BYTE_READER_PEEK_GET(64,gint64,int64_le)
707 GST_BYTE_READER_PEEK_GET(64,gint64,int64_be)
708 
709 /**
710  * gst_byte_reader_get_float32_le:
711  * @reader: a #GstByteReader instance
712  * @val: (out): Pointer to a #gfloat to store the result
713  *
714  * Read a 32 bit little endian floating point value into @val
715  * and update the current position.
716  *
717  * Returns: %TRUE if successful, %FALSE otherwise.
718  */
719 
720 /**
721  * gst_byte_reader_peek_float32_le:
722  * @reader: a #GstByteReader instance
723  * @val: (out): Pointer to a #gfloat to store the result
724  *
725  * Read a 32 bit little endian floating point value into @val
726  * but keep the current position.
727  *
728  * Returns: %TRUE if successful, %FALSE otherwise.
729  */
730 
731 /**
732  * gst_byte_reader_get_float32_be:
733  * @reader: a #GstByteReader instance
734  * @val: (out): Pointer to a #gfloat to store the result
735  *
736  * Read a 32 bit big endian floating point value into @val
737  * and update the current position.
738  *
739  * Returns: %TRUE if successful, %FALSE otherwise.
740  */
741 
742 /**
743  * gst_byte_reader_peek_float32_be:
744  * @reader: a #GstByteReader instance
745  * @val: (out): Pointer to a #gfloat to store the result
746  *
747  * Read a 32 bit big endian floating point value into @val
748  * but keep the current position.
749  *
750  * Returns: %TRUE if successful, %FALSE otherwise.
751  */
752 
753 /**
754  * gst_byte_reader_get_float64_le:
755  * @reader: a #GstByteReader instance
756  * @val: (out): Pointer to a #gdouble to store the result
757  *
758  * Read a 64 bit little endian floating point value into @val
759  * and update the current position.
760  *
761  * Returns: %TRUE if successful, %FALSE otherwise.
762  */
763 
764 /**
765  * gst_byte_reader_peek_float64_le:
766  * @reader: a #GstByteReader instance
767  * @val: (out): Pointer to a #gdouble to store the result
768  *
769  * Read a 64 bit little endian floating point value into @val
770  * but keep the current position.
771  *
772  * Returns: %TRUE if successful, %FALSE otherwise.
773  */
774 
775 /**
776  * gst_byte_reader_get_float64_be:
777  * @reader: a #GstByteReader instance
778  * @val: (out): Pointer to a #gdouble to store the result
779  *
780  * Read a 64 bit big endian floating point value into @val
781  * and update the current position.
782  *
783  * Returns: %TRUE if successful, %FALSE otherwise.
784  */
785 
786 /**
787  * gst_byte_reader_peek_float64_be:
788  * @reader: a #GstByteReader instance
789  * @val: (out): Pointer to a #gdouble to store the result
790  *
791  * Read a 64 bit big endian floating point value into @val
792  * but keep the current position.
793  *
794  * Returns: %TRUE if successful, %FALSE otherwise.
795  */
796 
797 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
798 GST_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
799 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
800 GST_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
801 
802 /* *INDENT-ON* */
803 
804 /**
805  * gst_byte_reader_get_data:
806  * @reader: a #GstByteReader instance
807  * @size: Size in bytes
808  * @val: (out) (transfer none) (array length=size): address of a
809  *     #guint8 pointer variable in which to store the result
810  *
811  * Returns a constant pointer to the current data
812  * position if at least @size bytes are left and
813  * updates the current position.
814  *
815  * Returns: %TRUE if successful, %FALSE otherwise.
816  */
817 gboolean
gst_byte_reader_get_data(GstByteReader * reader,guint size,const guint8 ** val)818 gst_byte_reader_get_data (GstByteReader * reader, guint size,
819     const guint8 ** val)
820 {
821   return _gst_byte_reader_get_data_inline (reader, size, val);
822 }
823 
824 /**
825  * gst_byte_reader_peek_data:
826  * @reader: a #GstByteReader instance
827  * @size: Size in bytes
828  * @val: (out) (transfer none) (array length=size): address of a
829  *     #guint8 pointer variable in which to store the result
830  *
831  * Returns a constant pointer to the current data
832  * position if at least @size bytes are left and
833  * keeps the current position.
834  *
835  * Returns: %TRUE if successful, %FALSE otherwise.
836  */
837 gboolean
gst_byte_reader_peek_data(const GstByteReader * reader,guint size,const guint8 ** val)838 gst_byte_reader_peek_data (const GstByteReader * reader, guint size,
839     const guint8 ** val)
840 {
841   return _gst_byte_reader_peek_data_inline (reader, size, val);
842 }
843 
844 /**
845  * gst_byte_reader_dup_data:
846  * @reader: a #GstByteReader instance
847  * @size: Size in bytes
848  * @val: (out) (transfer full) (array length=size): address of a
849  *     #guint8 pointer variable in which to store the result
850  *
851  * Free-function: g_free
852  *
853  * Returns a newly-allocated copy of the current data
854  * position if at least @size bytes are left and
855  * updates the current position. Free with g_free() when no longer needed.
856  *
857  * Returns: %TRUE if successful, %FALSE otherwise.
858  */
859 gboolean
gst_byte_reader_dup_data(GstByteReader * reader,guint size,guint8 ** val)860 gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
861 {
862   return _gst_byte_reader_dup_data_inline (reader, size, val);
863 }
864 
865 /* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */
866 static inline gint
_scan_for_start_code(const guint8 * data,guint size)867 _scan_for_start_code (const guint8 * data, guint size)
868 {
869   guint8 *pdata = (guint8 *) data;
870   guint8 *pend = (guint8 *) (data + size - 4);
871 
872   while (pdata <= pend) {
873     if (pdata[2] > 1) {
874       pdata += 3;
875     } else if (pdata[1]) {
876       pdata += 2;
877     } else if (pdata[0] || pdata[2] != 1) {
878       pdata++;
879     } else {
880       return (pdata - data);
881     }
882   }
883 
884   /* nothing found */
885   return -1;
886 }
887 
888 static inline guint
_masked_scan_uint32_peek(const GstByteReader * reader,guint32 mask,guint32 pattern,guint offset,guint size,guint32 * value)889 _masked_scan_uint32_peek (const GstByteReader * reader,
890     guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
891 {
892   const guint8 *data;
893   guint32 state;
894   guint i;
895 
896   g_return_val_if_fail (size > 0, -1);
897   g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
898       -1);
899 
900   /* we can't find the pattern with less than 4 bytes */
901   if (G_UNLIKELY (size < 4))
902     return -1;
903 
904   data = reader->data + reader->byte + offset;
905 
906   /* Handle special case found in MPEG and H264 */
907   if ((pattern == 0x00000100) && (mask == 0xffffff00)) {
908     gint ret = _scan_for_start_code (data, size);
909 
910     if (ret == -1)
911       return ret;
912 
913     if (value != NULL)
914       *value = (1 << 8) | data[ret + 3];
915 
916     return ret + offset;
917   }
918 
919   /* set the state to something that does not match */
920   state = ~pattern;
921 
922   /* now find data */
923   for (i = 0; i < size; i++) {
924     /* throw away one byte and move in the next byte */
925     state = ((state << 8) | data[i]);
926     if (G_UNLIKELY ((state & mask) == pattern)) {
927       /* we have a match but we need to have skipped at
928        * least 4 bytes to fill the state. */
929       if (G_LIKELY (i >= 3)) {
930         if (value)
931           *value = state;
932         return offset + i - 3;
933       }
934     }
935   }
936 
937   /* nothing found */
938   return -1;
939 }
940 
941 
942 /**
943  * gst_byte_reader_masked_scan_uint32:
944  * @reader: a #GstByteReader
945  * @mask: mask to apply to data before matching against @pattern
946  * @pattern: pattern to match (after mask is applied)
947  * @offset: offset from which to start scanning, relative to the current
948  *     position
949  * @size: number of bytes to scan from offset
950  *
951  * Scan for pattern @pattern with applied mask @mask in the byte reader data,
952  * starting from offset @offset relative to the current position.
953  *
954  * The bytes in @pattern and @mask are interpreted left-to-right, regardless
955  * of endianness.  All four bytes of the pattern must be present in the
956  * byte reader data for it to match, even if the first or last bytes are masked
957  * out.
958  *
959  * It is an error to call this function without making sure that there is
960  * enough data (offset+size bytes) in the byte reader.
961  *
962  * Returns: offset of the first match, or -1 if no match was found.
963  *
964  * Example:
965  * |[
966  * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff
967  *
968  * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256);
969  * // -> returns 0
970  * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255);
971  * // -> returns -1
972  * gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255);
973  * // -> returns 1
974  * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256);
975  * // -> returns -1
976  * gst_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256);
977  * // -> returns 0
978  * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256);
979  * // -> returns 2
980  * gst_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4);
981  * // -> returns -1
982  * ]|
983  */
984 guint
gst_byte_reader_masked_scan_uint32(const GstByteReader * reader,guint32 mask,guint32 pattern,guint offset,guint size)985 gst_byte_reader_masked_scan_uint32 (const GstByteReader * reader, guint32 mask,
986     guint32 pattern, guint offset, guint size)
987 {
988   return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL);
989 }
990 
991 /**
992  * gst_byte_reader_masked_scan_uint32_peek:
993  * @reader: a #GstByteReader
994  * @mask: mask to apply to data before matching against @pattern
995  * @pattern: pattern to match (after mask is applied)
996  * @offset: offset from which to start scanning, relative to the current
997  *     position
998  * @size: number of bytes to scan from offset
999  * @value: (out): pointer to uint32 to return matching data
1000  *
1001  * Scan for pattern @pattern with applied mask @mask in the byte reader data,
1002  * starting from offset @offset relative to the current position.
1003  *
1004  * The bytes in @pattern and @mask are interpreted left-to-right, regardless
1005  * of endianness.  All four bytes of the pattern must be present in the
1006  * byte reader data for it to match, even if the first or last bytes are masked
1007  * out.
1008  *
1009  * It is an error to call this function without making sure that there is
1010  * enough data (offset+size bytes) in the byte reader.
1011  *
1012  * Returns: offset of the first match, or -1 if no match was found.
1013  *
1014  * Since: 1.6
1015  */
1016 guint
gst_byte_reader_masked_scan_uint32_peek(const GstByteReader * reader,guint32 mask,guint32 pattern,guint offset,guint size,guint32 * value)1017 gst_byte_reader_masked_scan_uint32_peek (const GstByteReader * reader,
1018     guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value)
1019 {
1020   return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value);
1021 }
1022 
1023 #define GST_BYTE_READER_SCAN_STRING(bits) \
1024 static guint \
1025 gst_byte_reader_scan_string_utf##bits (const GstByteReader * reader) \
1026 { \
1027   guint len, off, max_len; \
1028   \
1029   max_len = (reader->size - reader->byte) / sizeof (guint##bits); \
1030   \
1031   /* need at least a single NUL terminator */ \
1032   if (max_len < 1) \
1033     return 0; \
1034   \
1035   len = 0; \
1036   off = reader->byte; \
1037   /* endianness does not matter if we are looking for a NUL terminator */ \
1038   while (GST_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \
1039     ++len; \
1040     off += sizeof (guint##bits); \
1041     /* have we reached the end without finding a NUL terminator? */ \
1042     if (len == max_len) \
1043       return 0; \
1044   } \
1045   /* return size in bytes including the NUL terminator (hence the +1) */ \
1046   return (len + 1) * sizeof (guint##bits); \
1047 }
1048 
1049 #define GST_READ_UINT8_LE GST_READ_UINT8
1050 GST_BYTE_READER_SCAN_STRING (8);
1051 #undef GST_READ_UINT8_LE
1052 GST_BYTE_READER_SCAN_STRING (16);
1053 GST_BYTE_READER_SCAN_STRING (32);
1054 
1055 #define GST_BYTE_READER_SKIP_STRING(bits) \
1056 gboolean \
1057 gst_byte_reader_skip_string_utf##bits (GstByteReader * reader) \
1058 { \
1059   guint size; /* size in bytes including the terminator */ \
1060   \
1061   g_return_val_if_fail (reader != NULL, FALSE); \
1062   \
1063   size = gst_byte_reader_scan_string_utf##bits (reader); \
1064   reader->byte += size; \
1065   return (size > 0); \
1066 }
1067 
1068 /**
1069  * gst_byte_reader_skip_string:
1070  * @reader: a #GstByteReader instance
1071  *
1072  * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1073  * the current position to the byte after the string. This will work for
1074  * any NUL-terminated string with a character width of 8 bits, so ASCII,
1075  * UTF-8, ISO-8859-N etc.
1076  *
1077  * This function will fail if no NUL-terminator was found in in the data.
1078  *
1079  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1080  */
1081 /**
1082  * gst_byte_reader_skip_string_utf8:
1083  * @reader: a #GstByteReader instance
1084  *
1085  * Skips a NUL-terminated string in the #GstByteReader instance, advancing
1086  * the current position to the byte after the string. This will work for
1087  * any NUL-terminated string with a character width of 8 bits, so ASCII,
1088  * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1089  *
1090  * This function will fail if no NUL-terminator was found in in the data.
1091  *
1092  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1093  */
1094 GST_BYTE_READER_SKIP_STRING (8);
1095 
1096 /**
1097  * gst_byte_reader_skip_string_utf16:
1098  * @reader: a #GstByteReader instance
1099  *
1100  * Skips a NUL-terminated UTF-16 string in the #GstByteReader instance,
1101  * advancing the current position to the byte after the string.
1102  *
1103  * No input checking for valid UTF-16 is done.
1104  *
1105  * This function will fail if no NUL-terminator was found in in the data.
1106  *
1107  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1108  */
1109 GST_BYTE_READER_SKIP_STRING (16);
1110 
1111 /**
1112  * gst_byte_reader_skip_string_utf32:
1113  * @reader: a #GstByteReader instance
1114  *
1115  * Skips a NUL-terminated UTF-32 string in the #GstByteReader instance,
1116  * advancing the current position to the byte after the string.
1117  *
1118  * No input checking for valid UTF-32 is done.
1119  *
1120  * This function will fail if no NUL-terminator was found in in the data.
1121  *
1122  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1123  */
1124 GST_BYTE_READER_SKIP_STRING (32);
1125 
1126 /**
1127  * gst_byte_reader_peek_string:
1128  * @reader: a #GstByteReader instance
1129  * @str: (out) (transfer none) (array zero-terminated=1): address of a
1130  *     #gchar pointer variable in which to store the result
1131  *
1132  * Returns a constant pointer to the current data position if there is
1133  * a NUL-terminated string in the data (this could be just a NUL terminator).
1134  * The current position will be maintained. This will work for any
1135  * NUL-terminated string with a character width of 8 bits, so ASCII,
1136  * UTF-8, ISO-8859-N etc.
1137  *
1138  * This function will fail if no NUL-terminator was found in in the data.
1139  *
1140  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1141  */
1142 /**
1143  * gst_byte_reader_peek_string_utf8:
1144  * @reader: a #GstByteReader instance
1145  * @str: (out) (transfer none) (array zero-terminated=1): address of a
1146  *     #gchar pointer variable in which to store the result
1147  *
1148  * Returns a constant pointer to the current data position if there is
1149  * a NUL-terminated string in the data (this could be just a NUL terminator).
1150  * The current position will be maintained. This will work for any
1151  * NUL-terminated string with a character width of 8 bits, so ASCII,
1152  * UTF-8, ISO-8859-N etc.
1153  *
1154  * No input checking for valid UTF-8 is done.
1155  *
1156  * This function will fail if no NUL-terminator was found in in the data.
1157  *
1158  * Returns: %TRUE if a string could be skipped, %FALSE otherwise.
1159  */
1160 gboolean
gst_byte_reader_peek_string_utf8(const GstByteReader * reader,const gchar ** str)1161 gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
1162     const gchar ** str)
1163 {
1164   g_return_val_if_fail (reader != NULL, FALSE);
1165   g_return_val_if_fail (str != NULL, FALSE);
1166 
1167   if (gst_byte_reader_scan_string_utf8 (reader) > 0) {
1168     *str = (const gchar *) (reader->data + reader->byte);
1169   } else {
1170     *str = NULL;
1171   }
1172   return (*str != NULL);
1173 }
1174 
1175 /**
1176  * gst_byte_reader_get_string_utf8:
1177  * @reader: a #GstByteReader instance
1178  * @str: (out) (transfer none) (array zero-terminated=1): address of a
1179  *     #gchar pointer variable in which to store the result
1180  *
1181  * Returns a constant pointer to the current data position if there is
1182  * a NUL-terminated string in the data (this could be just a NUL terminator),
1183  * advancing the current position to the byte after the string. This will work
1184  * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1185  * UTF-8, ISO-8859-N etc.
1186  *
1187  * No input checking for valid UTF-8 is done.
1188  *
1189  * This function will fail if no NUL-terminator was found in in the data.
1190  *
1191  * Returns: %TRUE if a string could be found, %FALSE otherwise.
1192  */
1193 gboolean
gst_byte_reader_get_string_utf8(GstByteReader * reader,const gchar ** str)1194 gst_byte_reader_get_string_utf8 (GstByteReader * reader, const gchar ** str)
1195 {
1196   guint size;                   /* size in bytes including the terminator */
1197 
1198   g_return_val_if_fail (reader != NULL, FALSE);
1199   g_return_val_if_fail (str != NULL, FALSE);
1200 
1201   size = gst_byte_reader_scan_string_utf8 (reader);
1202   if (size == 0) {
1203     *str = NULL;
1204     return FALSE;
1205   }
1206 
1207   *str = (const gchar *) (reader->data + reader->byte);
1208   reader->byte += size;
1209   return TRUE;
1210 }
1211 
1212 #define GST_BYTE_READER_DUP_STRING(bits,type) \
1213 gboolean \
1214 gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
1215 { \
1216   guint size; /* size in bytes including the terminator */ \
1217   \
1218   g_return_val_if_fail (reader != NULL, FALSE); \
1219   g_return_val_if_fail (str != NULL, FALSE); \
1220   \
1221   size = gst_byte_reader_scan_string_utf##bits (reader); \
1222   if (size == 0) { \
1223     *str = NULL; \
1224     return FALSE; \
1225   } \
1226   *str = g_memdup2 (reader->data + reader->byte, size); \
1227   reader->byte += size; \
1228   return TRUE; \
1229 }
1230 
1231 /**
1232  * gst_byte_reader_dup_string_utf8:
1233  * @reader: a #GstByteReader instance
1234  * @str: (out) (transfer full) (array zero-terminated=1): address of a
1235  *     #gchar pointer variable in which to store the result
1236  *
1237  * Free-function: g_free
1238  *
1239  * FIXME:Reads (copies) a NUL-terminated string in the #GstByteReader instance,
1240  * advancing the current position to the byte after the string. This will work
1241  * for any NUL-terminated string with a character width of 8 bits, so ASCII,
1242  * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done.
1243  *
1244  * This function will fail if no NUL-terminator was found in in the data.
1245  *
1246  * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The
1247  *     string put into @str must be freed with g_free() when no longer needed.
1248  */
1249 GST_BYTE_READER_DUP_STRING (8, gchar);
1250 
1251 /**
1252  * gst_byte_reader_dup_string_utf16:
1253  * @reader: a #GstByteReader instance
1254  * @str: (out) (transfer full) (array zero-terminated=1): address of a
1255  *     #guint16 pointer variable in which to store the result
1256  *
1257  * Free-function: g_free
1258  *
1259  * Returns a newly-allocated copy of the current data position if there is
1260  * a NUL-terminated UTF-16 string in the data (this could be an empty string
1261  * as well), and advances the current position.
1262  *
1263  * No input checking for valid UTF-16 is done. This function is endianness
1264  * agnostic - you should not assume the UTF-16 characters are in host
1265  * endianness.
1266  *
1267  * This function will fail if no NUL-terminator was found in in the data.
1268  *
1269  * Note: there is no peek or get variant of this function to ensure correct
1270  * byte alignment of the UTF-16 string.
1271  *
1272  * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1273  *     string put into @str must be freed with g_free() when no longer needed.
1274  */
1275 GST_BYTE_READER_DUP_STRING (16, guint16);
1276 
1277 /**
1278  * gst_byte_reader_dup_string_utf32:
1279  * @reader: a #GstByteReader instance
1280  * @str: (out) (transfer full) (array zero-terminated=1): address of a
1281  *     #guint32 pointer variable in which to store the result
1282  *
1283  * Free-function: g_free
1284  *
1285  * Returns a newly-allocated copy of the current data position if there is
1286  * a NUL-terminated UTF-32 string in the data (this could be an empty string
1287  * as well), and advances the current position.
1288  *
1289  * No input checking for valid UTF-32 is done. This function is endianness
1290  * agnostic - you should not assume the UTF-32 characters are in host
1291  * endianness.
1292  *
1293  * This function will fail if no NUL-terminator was found in in the data.
1294  *
1295  * Note: there is no peek or get variant of this function to ensure correct
1296  * byte alignment of the UTF-32 string.
1297  *
1298  * Returns: %TRUE if a string could be read, %FALSE otherwise. The
1299  *     string put into @str must be freed with g_free() when no longer needed.
1300  */
1301 GST_BYTE_READER_DUP_STRING (32, guint32);
1302