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