Commit 66c89519 authored by Benjamin Berg's avatar Benjamin Berg

lib: Add byte data reader/writer helpers

These helpers are directly copied from GStreamer and stripped down quite
a bit to e.g. always assume the machine does not support unaligned
access..
parent 02b44fa1
Pipeline #49088 passed with stages
in 5 minutes and 43 seconds
/* GStreamer byte reader
*
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
* 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
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define FP_BYTE_READER_DISABLE_INLINES
#include "fp-byte-reader.h"
#include <string.h>
/**
* SECTION:fp-byte-reader
* @title: FpByteReader
* @short_description: Reads different integer, string and floating point
* types from a memory buffer
*
* #FpByteReader provides a byte reader that can read different integer and
* floating point types from a memory buffer. It provides functions for reading
* signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits
* and functions for reading little/big endian floating points numbers of
* 32 and 64 bits. It also provides functions to read NUL-terminated strings
* in various character encodings.
*/
/**
* fp_byte_reader_new: (skip)
* @data: (in) (transfer none) (array length=size): data from which the
* #FpByteReader should read
* @size: Size of @data in bytes
*
* Create a new #FpByteReader instance, which will read from @data.
*
* Free-function: fp_byte_reader_free
*
* Returns: (transfer full): a new #FpByteReader instance
*/
FpByteReader *
fp_byte_reader_new (const guint8 * data, guint size)
{
FpByteReader *ret = g_slice_new0 (FpByteReader);
ret->data = data;
ret->size = size;
return ret;
}
/**
* fp_byte_reader_free:
* @reader: (in) (transfer full): a #FpByteReader instance
*
* Frees a #FpByteReader instance, which was previously allocated by
* fp_byte_reader_new().
*/
void
fp_byte_reader_free (FpByteReader * reader)
{
g_return_if_fail (reader != NULL);
g_slice_free (FpByteReader, reader);
}
/**
* fp_byte_reader_init:
* @reader: a #FpByteReader instance
* @data: (in) (transfer none) (array length=size): data from which
* the #FpByteReader should read
* @size: Size of @data in bytes
*
* Initializes a #FpByteReader instance to read from @data. This function
* can be called on already initialized instances.
*/
void
fp_byte_reader_init (FpByteReader * reader, const guint8 * data, guint size)
{
g_return_if_fail (reader != NULL);
reader->data = data;
reader->size = size;
reader->byte = 0;
}
/**
* fp_byte_reader_peek_sub_reader: (skip)
* @reader: an existing and initialized #FpByteReader instance
* @sub_reader: a #FpByteReader instance to initialize as sub-reader
* @size: size of @sub_reader in bytes
*
* Initializes a #FpByteReader 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 fp_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
fp_byte_reader_peek_sub_reader (FpByteReader * reader,
FpByteReader * sub_reader, guint size)
{
return _fp_byte_reader_peek_sub_reader_inline (reader, sub_reader, size);
}
/**
* fp_byte_reader_get_sub_reader: (skip)
* @reader: an existing and initialized #FpByteReader instance
* @sub_reader: a #FpByteReader instance to initialize as sub-reader
* @size: size of @sub_reader in bytes
*
* Initializes a #FpByteReader 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 fp_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
fp_byte_reader_get_sub_reader (FpByteReader * reader,
FpByteReader * sub_reader, guint size)
{
return _fp_byte_reader_get_sub_reader_inline (reader, sub_reader, size);
}
/**
* fp_byte_reader_set_pos:
* @reader: a #FpByteReader instance
* @pos: The new position in bytes
*
* Sets the new position of a #FpByteReader instance to @pos in bytes.
*
* Returns: %TRUE if the position could be set successfully, %FALSE
* otherwise.
*/
gboolean
fp_byte_reader_set_pos (FpByteReader * reader, guint pos)
{
g_return_val_if_fail (reader != NULL, FALSE);
if (pos > reader->size)
return FALSE;
reader->byte = pos;
return TRUE;
}
/**
* fp_byte_reader_get_pos:
* @reader: a #FpByteReader instance
*
* Returns the current position of a #FpByteReader instance in bytes.
*
* Returns: The current position of @reader in bytes.
*/
guint
fp_byte_reader_get_pos (const FpByteReader * reader)
{
return _fp_byte_reader_get_pos_inline (reader);
}
/**
* fp_byte_reader_get_remaining:
* @reader: a #FpByteReader instance
*
* Returns the remaining number of bytes of a #FpByteReader instance.
*
* Returns: The remaining number of bytes of @reader instance.
*/
guint
fp_byte_reader_get_remaining (const FpByteReader * reader)
{
return _fp_byte_reader_get_remaining_inline (reader);
}
/**
* fp_byte_reader_get_size:
* @reader: a #FpByteReader instance
*
* Returns the total number of bytes of a #FpByteReader instance.
*
* Returns: The total number of bytes of @reader instance.
*/
guint
fp_byte_reader_get_size (const FpByteReader * reader)
{
return _fp_byte_reader_get_size_inline (reader);
}
#define fp_byte_reader_get_remaining _fp_byte_reader_get_remaining_inline
#define fp_byte_reader_get_size _fp_byte_reader_get_size_inline
/**
* fp_byte_reader_skip:
* @reader: a #FpByteReader instance
* @nbytes: the number of bytes to skip
*
* Skips @nbytes bytes of the #FpByteReader instance.
*
* Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise.
*/
gboolean
fp_byte_reader_skip (FpByteReader * reader, guint nbytes)
{
return _fp_byte_reader_skip_inline (reader, nbytes);
}
/**
* fp_byte_reader_get_uint8:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint8 to store the result
*
* Read an unsigned 8 bit integer into @val and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int8:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint8 to store the result
*
* Read a signed 8 bit integer into @val and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint8:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint8 to store the result
*
* Read an unsigned 8 bit integer into @val but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int8:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint8 to store the result
*
* Read a signed 8 bit integer into @val but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint16_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint16 to store the result
*
* Read an unsigned 16 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int16_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint16 to store the result
*
* Read a signed 16 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint16_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint16 to store the result
*
* Read an unsigned 16 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int16_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint16 to store the result
*
* Read a signed 16 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint16_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint16 to store the result
*
* Read an unsigned 16 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int16_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint16 to store the result
*
* Read a signed 16 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint16_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint16 to store the result
*
* Read an unsigned 16 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int16_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint16 to store the result
*
* Read a signed 16 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint24_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 24 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int24_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 24 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint24_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 24 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int24_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 24 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint24_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 24 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int24_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 24 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint24_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 24 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int24_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 24 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 32 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 32 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 32 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 32 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 32 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 32 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint32 to store the result
*
* Read an unsigned 32 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint32 to store the result
*
* Read a signed 32 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint64 to store the result
*
* Read an unsigned 64 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint64 to store the result
*
* Read a signed 64 bit little endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint64 to store the result
*
* Read an unsigned 64 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint64 to store the result
*
* Read a signed 64 bit little endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_uint64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint64 to store the result
*
* Read an unsigned 64 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_int64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint64 to store the result
*
* Read a signed 64 bit big endian integer into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_uint64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #guint64 to store the result
*
* Read an unsigned 64 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_int64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gint64 to store the result
*
* Read a signed 64 bit big endian integer into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
#define FP_BYTE_READER_PEEK_GET(bits,type,name) \
gboolean \
fp_byte_reader_get_##name (FpByteReader * reader, type * val) \
{ \
return _fp_byte_reader_get_##name##_inline (reader, val); \
} \
\
gboolean \
fp_byte_reader_peek_##name (const FpByteReader * reader, type * val) \
{ \
return _fp_byte_reader_peek_##name##_inline (reader, val); \
}
/* *INDENT-OFF* */
FP_BYTE_READER_PEEK_GET(8,guint8,uint8)
FP_BYTE_READER_PEEK_GET(8,gint8,int8)
FP_BYTE_READER_PEEK_GET(16,guint16,uint16_le)
FP_BYTE_READER_PEEK_GET(16,guint16,uint16_be)
FP_BYTE_READER_PEEK_GET(16,gint16,int16_le)
FP_BYTE_READER_PEEK_GET(16,gint16,int16_be)
FP_BYTE_READER_PEEK_GET(24,guint32,uint24_le)
FP_BYTE_READER_PEEK_GET(24,guint32,uint24_be)
FP_BYTE_READER_PEEK_GET(24,gint32,int24_le)
FP_BYTE_READER_PEEK_GET(24,gint32,int24_be)
FP_BYTE_READER_PEEK_GET(32,guint32,uint32_le)
FP_BYTE_READER_PEEK_GET(32,guint32,uint32_be)
FP_BYTE_READER_PEEK_GET(32,gint32,int32_le)
FP_BYTE_READER_PEEK_GET(32,gint32,int32_be)
FP_BYTE_READER_PEEK_GET(64,guint64,uint64_le)
FP_BYTE_READER_PEEK_GET(64,guint64,uint64_be)
FP_BYTE_READER_PEEK_GET(64,gint64,int64_le)
FP_BYTE_READER_PEEK_GET(64,gint64,int64_be)
/**
* fp_byte_reader_get_float32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gfloat to store the result
*
* Read a 32 bit little endian floating point value into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_float32_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gfloat to store the result
*
* Read a 32 bit little endian floating point value into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_float32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gfloat to store the result
*
* Read a 32 bit big endian floating point value into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_float32_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gfloat to store the result
*
* Read a 32 bit big endian floating point value into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_float64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gdouble to store the result
*
* Read a 64 bit little endian floating point value into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_float64_le:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gdouble to store the result
*
* Read a 64 bit little endian floating point value into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_get_float64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gdouble to store the result
*
* Read a 64 bit big endian floating point value into @val
* and update the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
/**
* fp_byte_reader_peek_float64_be:
* @reader: a #FpByteReader instance
* @val: (out): Pointer to a #gdouble to store the result
*
* Read a 64 bit big endian floating point value into @val
* but keep the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
FP_BYTE_READER_PEEK_GET(32,gfloat,float32_le)
FP_BYTE_READER_PEEK_GET(32,gfloat,float32_be)
FP_BYTE_READER_PEEK_GET(64,gdouble,float64_le)
FP_BYTE_READER_PEEK_GET(64,gdouble,float64_be)
/* *INDENT-ON* */
/**
* fp_byte_reader_get_data:
* @reader: a #FpByteReader instance
* @size: Size in bytes
* @val: (out) (transfer none) (array length=size): address of a
* #guint8 pointer variable in which to store the result
*
* Returns a constant pointer to the current data
* position if at least @size bytes are left and