From d617ec87eec19efe7f2a854c437da882348d459e Mon Sep 17 00:00:00 2001 From: darkjames Date: Tue, 17 May 2011 22:20:14 +0000 Subject: [PATCH] Add generic tvb_get_bits_buf() which accepts any no_of_bits. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@37217 f5534014-38df-0310-8fa8-9805f1628bb7 --- epan/libwireshark.def | 2 ++ epan/tvbuff.c | 53 +++++++++++++++++++++++++++++++++++++++++++ epan/tvbuff.h | 3 +++ 3 files changed, 58 insertions(+) diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 1bad5dea64..142bf7bf4a 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -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 diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 83fffe827c..d7a16ebd35 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -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[] = { diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 4763d14683..2d66967560 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -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 -- 2.34.1