/* GStreamer byte reader
*
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
- * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2009,2014 Tim-Philipp Müller <tim centricular net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
}
/**
+ * gst_byte_reader_peek_sub_reader: (skip)
+ * @reader: an existing and initialized #GstByteReader instance
+ * @sub_reader: a #GstByteReader instance to initialize as sub-reader
+ * @size: size of @sub_reader in bytes
+ *
+ * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
+ * data from the current position of @reader. This is useful to read chunked
+ * formats and make sure that one doesn't read beyond the size of the sub-chunk.
+ *
+ * Unlike gst_byte_reader_get_sub_reader(), this function does not modify the
+ * current position of @reader.
+ *
+ * Returns: FALSE on error or if @reader does not contain @size more bytes from
+ * the current position, and otherwise TRUE
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_byte_reader_peek_sub_reader (GstByteReader * reader,
+ GstByteReader * sub_reader, guint size)
+{
+ return _gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
+}
+
+/**
+ * gst_byte_reader_get_sub_reader: (skip)
+ * @reader: an existing and initialized #GstByteReader instance
+ * @sub_reader: a #GstByteReader instance to initialize as sub-reader
+ * @size: size of @sub_reader in bytes
+ *
+ * Initializes a #GstByteReader sub-reader instance to contain @size bytes of
+ * data from the current position of @reader. This is useful to read chunked
+ * formats and make sure that one doesn't read beyond the size of the sub-chunk.
+ *
+ * Unlike gst_byte_reader_peek_sub_reader(), this function also modifies the
+ * position of @reader and moves it forward by @size bytes.
+ *
+ * Returns: FALSE on error or if @reader does not contain @size more bytes from
+ * the current position, and otherwise TRUE
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_byte_reader_get_sub_reader (GstByteReader * reader,
+ GstByteReader * sub_reader, guint size)
+{
+ return _gst_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
+}
+
+/**
* gst_byte_reader_set_pos:
* @reader: a #GstByteReader instance
* @pos: The new position in bytes
void gst_byte_reader_init (GstByteReader *reader, const guint8 *data, guint size);
+gboolean gst_byte_reader_peek_sub_reader (GstByteReader * reader,
+ GstByteReader * sub_reader,
+ guint size);
+
+gboolean gst_byte_reader_get_sub_reader (GstByteReader * reader,
+ GstByteReader * sub_reader,
+ guint size);
+
gboolean gst_byte_reader_set_pos (GstByteReader *reader, guint pos);
guint gst_byte_reader_get_pos (const GstByteReader *reader);
}
static inline gboolean
+_gst_byte_reader_peek_sub_reader_inline (GstByteReader * reader,
+ GstByteReader * sub_reader, guint size)
+{
+ g_return_val_if_fail (reader != NULL, FALSE);
+ g_return_val_if_fail (sub_reader != NULL, FALSE);
+
+ if (_gst_byte_reader_get_remaining_unchecked (reader) < size)
+ return FALSE;
+
+ sub_reader->data = reader->data + reader->byte;
+ sub_reader->byte = 0;
+ sub_reader->size = size;
+ return TRUE;
+}
+
+static inline gboolean
+_gst_byte_reader_get_sub_reader_inline (GstByteReader * reader,
+ GstByteReader * sub_reader, guint size)
+{
+ if (!_gst_byte_reader_peek_sub_reader_inline (reader, sub_reader, size))
+ return FALSE;
+ gst_byte_reader_skip_unchecked (reader, size);
+ return TRUE;
+}
+
+static inline gboolean
_gst_byte_reader_dup_data_inline (GstByteReader * reader, guint size, guint8 ** val)
{
g_return_val_if_fail (reader != NULL, FALSE);
GST_END_TEST;
+GST_START_TEST (test_sub_reader)
+{
+ const guint8 memdata[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+ GstByteReader reader = GST_BYTE_READER_INIT (memdata, sizeof (memdata));
+ GstByteReader sub;
+ const guint8 *data = NULL, *sub_data = NULL;
+ guint16 v = 0;
+
+ /* init sub reader */
+ fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 17));
+ fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 16));
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 16);
+ fail_unless (gst_byte_reader_peek_data (&reader, 16, &data));
+ fail_unless (gst_byte_reader_peek_data (&sub, 16, &sub_data));
+ fail_unless (memcmp (data, sub_data, 16) == 0);
+
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 16);
+ fail_unless (gst_byte_reader_skip (&reader, 3));
+ fail_if (gst_byte_reader_peek_sub_reader (&reader, &sub, 14));
+ fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 13));
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 13);
+ fail_unless (gst_byte_reader_peek_data (&reader, 13, &data));
+ fail_unless (gst_byte_reader_peek_data (&sub, 13, &sub_data));
+ fail_unless (memcmp (data, sub_data, 16) == 0);
+
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 13);
+ fail_unless (gst_byte_reader_peek_sub_reader (&reader, &sub, 3));
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 3);
+ fail_if (gst_byte_reader_peek_data (&sub, 10, &sub_data));
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0304);
+ fail_if (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&sub), 1);
+
+ fail_unless (gst_byte_reader_get_uint16_be (&reader, &v));
+ fail_unless_equals_int (v, 0x0304);
+ fail_unless (gst_byte_reader_get_uint16_be (&reader, &v));
+ fail_unless_equals_int (v, 0x0506);
+ fail_unless_equals_int (gst_byte_reader_get_remaining (&reader), 9);
+
+ /* get sub reader */
+ gst_byte_reader_init (&reader, memdata, sizeof (memdata));
+ fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 17));
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 16));
+ fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 1));
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 0));
+
+ gst_byte_reader_init (&reader, memdata, sizeof (memdata));
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2));
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0001);
+ fail_if (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 3));
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0203);
+ fail_if (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x04);
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 9));
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0506);
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0708);
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x090a);
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0b0c);
+ fail_if (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (gst_byte_reader_get_uint8_unchecked (&sub), 0x0d);
+ fail_if (gst_byte_reader_get_sub_reader (&reader, &sub, 3));
+ fail_unless (gst_byte_reader_get_sub_reader (&reader, &sub, 2));
+ fail_unless (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_unless_equals_int (v, 0x0e0f);
+ fail_if (gst_byte_reader_get_uint16_be (&sub, &v));
+ fail_if (gst_byte_reader_get_uint16_be (&reader, &v));
+}
+
+GST_END_TEST;
+
static Suite *
gst_byte_reader_suite (void)
{
tcase_add_test (tc_chain, test_scan);
tcase_add_test (tc_chain, test_string_funcs);
tcase_add_test (tc_chain, test_dup_string);
+ tcase_add_test (tc_chain, test_sub_reader);
return s;
}