summaryrefslogtreecommitdiff
path: root/epan/tvbuff.c
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2011-05-18 18:49:33 +0000
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2011-05-18 18:49:33 +0000
commit3bb5e937d48628d4722bf0d28bb7400f1ca93da5 (patch)
treeb6f70559b543fa10f1e37e386de4bda94a1ac066 /epan/tvbuff.c
parent487f03612f0f3c26bc476bb6935afee97c87aa45 (diff)
downloadwireshark-3bb5e937d48628d4722bf0d28bb7400f1ca93da5.tar.gz
- Optimize tvb_get_bits_buf
- Add lsb0 (read: least significant bit is 0) parameter to tvb_get_bits_buf() (not tested, might be buggy...) svn path=/trunk/; revision=37254
Diffstat (limited to 'epan/tvbuff.c')
-rw-r--r--epan/tvbuff.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/epan/tvbuff.c b/epan/tvbuff.c
index d7a16ebd35..197ba7e754 100644
--- a/epan/tvbuff.c
+++ b/epan/tvbuff.c
@@ -1657,25 +1657,51 @@ tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits)
}
void
-tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf)
+tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf, gboolean lsb0)
{
+ guint8 bit_mask, bit_shift;
/* Byte align offset */
gint offset = bit_offset >> 3;
bit_offset = bit_offset & 0x7;
+ bit_mask = (lsb0) ? 0xff : bit_mask8[bit_offset];
+ bit_shift = (lsb0) ? bit_offset : (8 - bit_offset);
+
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);
+ guint16 value = (guint16) tvb_get_guint8(tvb, offset);
- *buf++ = (guint8) value;
+ while (no_of_bits >= 8) {
offset++;
+ value = ((value & bit_mask) << 8) | tvb_get_guint8(tvb, offset);
+
+ *buf++ = (guint8) (value >> bit_shift);
no_of_bits -= 8;
}
/* something left? */
- if (no_of_bits > 0)
- *buf = tvb_get_bits8(tvb, offset * 8 + bit_offset, no_of_bits);
+ if (no_of_bits > 0) {
+ guint8 tot_no_bits = bit_offset+no_of_bits;
+
+ /* Overlaps with next byte? Get next byte */
+ if (tot_no_bits > 8) {
+ offset++;
+ value = ((value & bit_mask) << 8) | tvb_get_guint8(tvb, offset);
+ }
+
+ if (lsb0) {
+ value = (value >> bit_offset) & (bit_mask8[8-no_of_bits]);
+
+ /* value = (value & ((1 << tot_no_bits)-1)) >> bit_offset; */
+
+
+ } else {
+ if (tot_no_bits > 8)
+ value = value >> (16 - tot_no_bits);
+ else
+ value = (value & bit_mask) >> (8-tot_no_bits);
+ }
+ *buf = (guint8) value;
+ }
} else {
/* fast code path for bit_offset == 0 */
@@ -1686,13 +1712,17 @@ tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf)
}
/* something left? */
- if (no_of_bits > 0)
- *buf = tvb_get_guint8(tvb, offset) >> (8-no_of_bits);
+ if (no_of_bits > 0) {
+ if (lsb0)
+ *buf = tvb_get_guint8(tvb, offset) & bit_mask8[8-no_of_bits]; /* read: ((1 << no_of_bits)-1) */
+ else
+ *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)
+ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean lsb0)
{
gint no_of_bytes;
guint8 *buf;
@@ -1705,7 +1735,7 @@ ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits)
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);
+ tvb_get_bits_buf(tvb, bit_offset, no_of_bits, buf, lsb0);
return buf;
}