#ifndef lib_bitstream_h #define lib_bitstream_h /* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file lib/bitstream.h * \brief Bit stream access using word access. * \ingroup lib * * This library provides sequential bit stream access functions using word * access, providing bus optimised endian and boundary safe access. */ /** Forward declaration. */ typedef struct bitstream_t bitstream_t; /** * Called when the buffer is exhausted. * \param ctx bit stream context * \param user_data user data provided on initialisation */ typedef void (*bitstream_buffer_cb_t) (bitstream_t *ctx, void *user_data); /** Bit stream direction. */ enum bitstream_direction_t { BITSTREAM_READ, BITSTREAM_WRITE }; typedef enum bitstream_direction_t bitstream_direction_t; /** Bit stream sequential access context. */ struct bitstream_t { /** Bit stream direction. */ bitstream_direction_t direction; /** Working buffer. */ u64 buffer; /** Number of valid bits in the working buffer. */ uint buffer_bits; /** Data pointer, accessed as words. */ u32 *data; /** Number of available bits in data buffer. */ uint data_bits; /** Number of written bits in data buffer. */ uint data_written_bits; /** Exhausted data buffer callback. */ bitstream_buffer_cb_t buffer_cb; /** User data associated with exhausted buffer callback. */ void *buffer_cb_user_data; }; BEGIN_DECLS /** * Initialise a bit stream. * \param ctx bit stream context * \param data stream data pointer * \param nb_bytes number of valid bytes in the stream * \param direction direction of access */ void bitstream_init (bitstream_t *ctx, void *data, uint nb_bytes, bitstream_direction_t direction); /** * Shortcut to initialise a bit stream for reading. * \param ctx bit stream context * \param data stream data pointer * \param nb_bytes number of valid bytes in the stream */ #define bitstream_read_init(ctx, data, nb_bytes) \ bitstream_init ((ctx), (void *) (data), (nb_bytes), BITSTREAM_READ) /** * Shortcut to initialise a bit stream for writing. * \param ctx bit stream context * \param data stream data pointer * \param nb_bytes number of valid bytes in the stream */ #define bitstream_write_init(ctx, data, nb_bytes) \ bitstream_init ((ctx), (data), (nb_bytes), BITSTREAM_WRITE) /** * Initialise the exhausted buffer callback. * \param ctx bit stream context * \param cb callback * \param user_data user data * * Callback stay initialised until bit stream end. This function can be * called with a NULL parameter if callback is no longer required. */ void bitstream_init_buffer_cb (bitstream_t *ctx, bitstream_buffer_cb_t cb, void *user_data); /** * Initialise again a bit stream with a new buffer. * \param ctx bit stream context * \param data stream data pointer * \param nb_bytes number of valid bytes in the stream * * Can be called from buffer exhausted callback. */ void bitstream_set_buffer (bitstream_t *ctx, void *data, uint nb_bytes); /** * Read up to 32 bits from the bit stream. * \param ctx bit stream context * \param nb_bits number of bits to read (1-32) * \return unsigned read value */ uint bitstream_read_ (bitstream_t *ctx, uint nb_bits __FL); #define bitstream_read(ctx, nb_bits) \ bitstream_read_(ctx, nb_bits __fL) /** * Write up to 32 bits to the bit stream. * \param ctx bit stream context * \param value value to write * \param nb_bits number of bits to write (1-32) */ void bitstream_write_ (bitstream_t *ctx, uint value, uint nb_bits __FL); #define bitstream_write(ctx, value, nb_bits) \ bitstream_write_(ctx, value, nb_bits __fL) /** * Write remaining bits. * \param ctx bit stream context * \return number of written bits */ uint bitstream_write_finalise (bitstream_t *ctx); /** * Read from 33 up to 64 bits from the bit stream. * \param ctx bit stream context * \param nb_bits number of bits to read (33-64) * \return unsigned read value */ u64 bitstream_read_large (bitstream_t *ctx, uint nb_bits); /** * Write from 33 up to 64 bits to the bit stream. * \param ctx bit stream context * \param value value to write * \param nb_bits number of bits to write (33-64) */ void bitstream_write_large (bitstream_t *ctx, u64 value, uint nb_bits); /** * Skip any number of bits from an input bit stream. * \param ctx bit stream context * \param nb_bits number of bits to skip (0-any) */ void bitstream_skip (bitstream_t *ctx, uint nb_bits); /** * Read a byte buffer from the bit stream. * \param ctx bit stream context * \param buf buffer address to store data read * \param size buffer size */ void bitstream_read_buf (bitstream_t *ctx, u8 *buf, uint size); /** * Write a byte buffer to the bit stream. * \param ctx bit stream context * \param buf buffer address * \param size buffer size */ void bitstream_write_buf (bitstream_t *ctx, const u8 *buf, uint size); /** * Copy a byte buffer between two bit streams. * \param dst destination bit stream context * \param src source bit stream context * \param size buffer size */ void bitstream_copy_buf (bitstream_t *dst, bitstream_t *src, uint size); /** * Read a string from the bit stream. * \param ctx bit stream context * \param str string address to store data read * \param size string max size (null character included) * \return number of read characters (null character excluded) * * Stop reading at first null byte or at max size, whichever come first, * always store a null character. If the returned value equals the given * size, no null character has been read before the reading stopped. */ uint bitstream_read_str (bitstream_t *ctx, char *str, uint size); /** * Write a string to the bit stream. * \param ctx bit stream context * \param str string address * \param size string max size (null character included) * \return number of written characters (null character excluded) * * Stop writing at first null byte or at max size, whichever come first, * always store a null character (size - 1 character will be stored at most). * If the returned value equals the given size, no null character has been * written before the writing stopped. */ uint bitstream_write_str (bitstream_t *ctx, const char *str, uint size); /** * Return the number of available bits. * \param ctx bit stream context * \return number of bits which can be read or written */ uint bitstream_available_bits (bitstream_t *ctx); /** * Return the number of written bits. * \param ctx bit stream context * \return number of written bits or zero it this is a read bit stream */ uint bitstream_written_bits (bitstream_t *ctx); /** * Read or write bits from the bit stream. * \param ctx bit stream context * \param value address to store the read value or of the value to write * \param nb_bits number of bits to access (1-64) * * Access type (read or write) depends on context direction. */ #define bitstream_access(ctx, value, nb_bits) \ (sizeof(*(value)) == 1 ? bitstream_access_8 ((ctx), (void *) (value), (nb_bits)) \ : (sizeof(*(value)) == 2 ? bitstream_access_16 ((ctx), (void *) (value), (nb_bits)) \ : (sizeof(*(value)) == 4 ? bitstream_access_32 ((ctx), (void *) (value), (nb_bits)) \ : (sizeof(*(value)) == 8 ? bitstream_access_64 ((ctx), (void *) (value), (nb_bits)) \ : bitstream_access_unknown_size ())))) /* Dummy function used to raise errors on unknown sizes. */ uint bitstream_access_unknown_size (void); /** * Read or write the next "nb_bits" from/to the bit stream. * \param ctx bit stream context * \param value pointer to the value * \param nb_bits number of bits to access (1-64) * * Internal function, use bitstream_access(). */ void bitstream_access_8 (bitstream_t *ctx, u8 *value, uint nb_bits); /** * Read or write the next "nb_bits" from/to the bit stream. * \param ctx bit stream context * \param value pointer to the value * \param nb_bits number of bits to access (1-64) * * Internal function, use bitstream_access(). */ void bitstream_access_16 (bitstream_t *ctx, u16 *value, uint nb_bits); /** * Read or write the next "nb_bits" from/to the bit stream. * \param ctx bit stream context * \param value pointer to the value * \param nb_bits number of bits to access (1-64) * * Internal function, use bitstream_access(). */ void bitstream_access_32 (bitstream_t *ctx, u32 *value, uint nb_bits); /** * Read or write the next "nb_bits" from/to the bit stream. * \param ctx bit stream context * \param value pointer to the value * \param nb_bits number of bits to access (1-64) * * Internal function, use bitstream_access(). */ void bitstream_access_64 (bitstream_t *ctx, u64 *value, uint nb_bits); /** * Write remaining bits or do nothing for read bit stream. * \param ctx bit stream context * \return number of written bits or 0 for read bit stream */ uint bitstream_access_finalise (bitstream_t *ctx); /** * Read or write a byte buffer. * \param ctx bit stream context * \param buf buffer address * \param size buffer size * * See bitstream_read_buf() and bitstream_write_buf() for details. */ void bitstream_access_buf (bitstream_t *ctx, u8 *buf, uint size); /** * Read or write a string. * \param ctx bit stream context * \param str string address * \param size string max size (null character included) * \return number of accessed characters (null character excluded) * * See bitstream_read_str() and bitstream_write_str() for details. */ uint bitstream_access_str (bitstream_t *ctx, char *str, uint size); /** * Read up to 32 bits from a bit stream. * \param data stream data pointer * \param bit_offset bit offset inside stream * \param nb_bits number of bits to read (1-32) * \return unsigned read value */ uint bitstream_direct_read (const void *data, uint bit_offset, uint nb_bits); /** * Read from 33 up to 64 bits from a bit stream. * \param data stream data pointer * \param bit_offset bit offset inside stream * \param nb_bits number of bits to read (33-64) * \return unsigned read value */ u64 bitstream_direct_read_large (const void *data, uint bit_offset, uint nb_bits); /** * Read a MAC address from a bit stream. * \param data stream data pointer * \return read MAC */ mac_t bitstream_direct_read_mac (const void *data); /** * Read two MAC addresses from a bit stream. * \param data stream data pointer * \param dst first MAC read, usually the destination * \param src second MAC read, usually the source */ void bitstream_direct_read_macs (const void *data, mac_t *dst, mac_t *src); /** * Write up to 32 bits to a bit stream. * \param data stream data pointer * \param bit_offset bit offset inside stream * \param value value to write * \param nb_bits number of bits to write (1-32) */ void bitstream_direct_write (void *data, uint bit_offset, uint value, uint nb_bits); /** * Write from 33 up to 64 bits to a bit stream. * \param data stream data pointer * \param bit_offset bit offset inside stream * \param value value to write * \param nb_bits number of bits to write (33-64) */ void bitstream_direct_write_large (void *data, uint bit_offset, u64 value, uint nb_bits); /** * Provide a API similar to libc memcpy to copy data between two bit streams. * \param dest destination address * \param src source address * \param size number of bytes */ void bitstream_memcpy (void *dest, const void *src, uint size); /** * Provide a API similar to libc memcmp to compare data between two bit * streams. * \param s1 first address * \param s2 second address * \param size number of bytes * \return true if equal, false otherwise * * \warning return value semantics does not match memcmp one! */ bool bitstream_memcmp (const void *s1, const void *s2, uint size); /* Compat macros. */ #define bitstream_finalise bitstream_access_finalise #define bitstream_buffer_full_init_cb bitstream_init_buffer_cb #define bitstream_bytes_processed(ctx) (bitstream_written_bits(ctx) / 8) END_DECLS #endif /* lib_bitstream_h */