GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 5.6% 9 / 0 / 162
Functions: 3.9% 3 / 0 / 76
Branches: 2.0% 2 / 0 / 102

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