Add generic tvb_get_bits_buf() which accepts any no_of_bits.
authordarkjames <darkjames@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 17 May 2011 22:20:14 +0000 (22:20 +0000)
committerdarkjames <darkjames@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 17 May 2011 22:20:14 +0000 (22:20 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@37217 f5534014-38df-0310-8fa8-9805f1628bb7

epan/libwireshark.def
epan/tvbuff.c
epan/tvbuff.h

index 1bad5dea64c009c2128207c7bc243be9eabdbf47..142bf7bf4a8399bad523b8bf9d8a9613acdd393d 100644 (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
index 83fffe827ca3ca9ca751f3708e99079a5666f15f..d7a16ebd35afa4a69898e650ad25185b942d6eee 100644 (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[] = {
index 4763d146836399193a602f6ba32c731e3c9f5680..2d669675600903c5d0cfadffeb4645cfb9a67016 100644 (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