Add generic tvb_get_bits_buf() which accepts any no_of_bits.

svn path=/trunk/; revision=37217
This commit is contained in:
Jakub Zawadzki 2011-05-17 22:20:14 +00:00
parent 1372515b02
commit e21e71e46e
3 changed files with 58 additions and 0 deletions

View File

@ -387,6 +387,7 @@ ep_strdup_printf
ep_strdup_vprintf
ep_strndup
ep_strsplit
ep_tvb_get_bits
ep_tvb_memdup
epan_base64_decode
epan_cleanup
@ -1069,6 +1070,7 @@ tvb_find_line_end_unquoted
tvb_format_text
tvb_format_text_wsp
tvb_free
tvb_get_bits_buf
tvb_get_bits8
tvb_get_bits16
tvb_get_bits32

View File

@ -1656,6 +1656,59 @@ tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits)
return (guint8)value;
}
void
tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf)
{
/* Byte align offset */
gint offset = bit_offset >> 3;
bit_offset = bit_offset & 0x7;
if (G_LIKELY(bit_offset != 0)) {
/* XXX, this can be optimized */
while (no_of_bits >= 8) {
guint16 value = (tvb_get_ntohs(tvb, offset) & bit_mask16[bit_offset]) >> (8 - bit_offset);
*buf++ = (guint8) value;
offset++;
no_of_bits -= 8;
}
/* something left? */
if (no_of_bits > 0)
*buf = tvb_get_bits8(tvb, offset * 8 + bit_offset, no_of_bits);
} else {
/* fast code path for bit_offset == 0 */
while (no_of_bits >= 8) {
*buf++ = tvb_get_guint8(tvb, offset);
offset++;
no_of_bits -= 8;
}
/* something left? */
if (no_of_bits > 0)
*buf = tvb_get_guint8(tvb, offset) >> (8-no_of_bits);
}
}
guint8 *
ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits)
{
gint no_of_bytes;
guint8 *buf;
/* XXX, no_of_bits == -1 -> to end of tvb? */
if (no_of_bits < 0 || bit_offset < 0) {
DISSECTOR_ASSERT_NOT_REACHED();
}
no_of_bytes = (no_of_bits >> 3) + ((no_of_bits & 0x7) != 0); /* ceil(no_of_bits / 8.0) */
buf = ep_alloc(no_of_bytes);
tvb_get_bits_buf(tvb, bit_offset, no_of_bits, buf);
return buf;
}
/* Get 9 - 16 bits */
/* Bit offset mask for number of bits = 16 - 32 */
static const guint32 bit_mask32[] = {

View File

@ -363,6 +363,9 @@ extern guint64 tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, const gint no_of_b
*/
extern guint32 tvb_get_bits(tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const gboolean little_endian);
void tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf);
guint8 *ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits);
/** Returns target for convenience. Does not suffer from possible
* expense of tvb_get_ptr(), since this routine is smart enough
* to copy data in chunks if the request range actually exists in