GCC Code Coverage Report


Directory: ./
File: libfprint/fpi-byte-reader.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 5 122 4.1%
Functions: 1 72 1.4%
Branches: 2 92 2.2%

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