Add a new proto function proto_tree_add_bits() which adds bits to the tree
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Apr 2007 19:24:14 +0000 (19:24 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Apr 2007 19:24:14 +0000 (19:24 +0000)
starting at the bit offset given for the number of bits indicated which wll also return
the value of the bits.
Experimental and for review, documentation to be updated.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@21556 f5534014-38df-0310-8fa8-9805f1628bb7

epan/proto.c
epan/proto.h

index 8d436dcb3abc647a188c6a15ebea410a6ab7cb42..e8534929438bad212803bfb15decdade4c8e18e9 100644 (file)
@@ -5579,4 +5579,241 @@ proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, int offset, int h
 
        return item;
 }
+/* 
+ * This function will dissect a sequence of bits that does not need to be byte aligned the bits
+ * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
+ * Offset should be given in bits. Currently only up to 24 unaligned bits can be handled.
+ */
+
+proto_item *
+proto_tree_add_bits(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint32 *return_value, gboolean little_endian)
+{
+       gint offset;
+       guint length;
+       guint bit_length;
+       char *str;
+       header_field_info *hf_field;
+       guint32 value = 0;
+       int bit;
+       guint32 mask = 0, tmp;
+       gboolean is_bytealigned = FALSE;
+       guint8 mask8    = 0xff;
+       guint16 mask16  = 0xffff;
+       guint32 mask24  = 0xffffff;
+       guint32 mask32  = 0xffffffff;
+       guint8 shift;
+       int i;
+
+       if((bit_offset&0x7)==0)
+               is_bytealigned = TRUE;
+
+       hf_field = proto_registrar_get_nth(hf_index);
+
+       offset = bit_offset>>3;
+       bit_length = ((bit_offset&0x7)+no_of_bits);
+       length = bit_length >>3;
+       if((bit_length&0x7)!=0)
+               length = length +1;
+
+       if (no_of_bits < 2){
+               /* Single bit */
+               mask8 = mask8 >>(bit_offset&0x7);
+               value = tvb_get_guint8(tvb,offset) & mask8;
+               mask = 0x80;
+               shift = 8-((bit_offset + no_of_bits)&0x7);
+               if (shift<8){
+                       value = value >> shift;
+                       mask = mask >> shift;
+               }
+       }else if(no_of_bits < 9){
+               /* One or 2 bytes */
+               if(length == 1){
+                       /* Spans 1 byte */
+                       mask8 = mask8>>(bit_offset&0x7);
+                       value = tvb_get_guint8(tvb,offset)&mask8;
+                       mask = 0x80;
+               }else{
+                       /* Spans 2 bytes */     
+                       mask16 = mask16>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letohs(tvb, offset);
+                       } else {
+                               value=tvb_get_ntohs(tvb, offset);
+                       }
+                       mask = 0x8000;
+               }
+               shift = 8-((bit_offset + no_of_bits)&0x7);
+               if (shift<8){
+                       value = value >> shift;
+                       mask = mask >> shift;
+               }
+               
+       }else if (no_of_bits < 17){
+               /* 2 or 3 bytes */
+               if(length == 2){
+                       /* Spans 2 bytes */
+                       mask16 = mask16>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letohs(tvb, offset);
+                       } else {
+                               value=tvb_get_ntohs(tvb, offset);
+                       }
+                       mask = 0x8000;
+               }else{
+                       /* Spans 3 bytes */     
+                       mask24 = mask24>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letoh24(tvb, offset);
+                       } else {
+                               value=tvb_get_ntoh24(tvb, offset);
+                       }
+                       mask = 0x800000;
+               }
+               shift = 8-((bit_offset + no_of_bits)&0x7);
+               if (shift<8){
+                       value = value >> shift;
+                       mask = mask >> shift;
+               }
+
+       }else if (no_of_bits < 25){
+               /* 3 or 4 bytes */
+               if(length == 3){
+                       /* Spans 3 bytes */
+                       mask24 = mask24>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letoh24(tvb, offset);
+                       } else {
+                               value=tvb_get_ntoh24(tvb, offset);
+                       }
+                       mask = 0x800000;
+               }else{
+                       /* Spans 4 bytes */     
+                       mask32 = mask32>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letohl(tvb, offset);
+                       } else {
+                               value=tvb_get_ntohl(tvb, offset);
+                       }
+                       mask = 0x80000000;
+               }
+               shift = 8-((bit_offset + no_of_bits)&0x7);
+               if (shift<8){
+                       value = value >> shift;
+                       mask = mask >> shift;
+               }
+
+       }else if (no_of_bits < 33){
+               /* 4 or 5 bytes */
+               if(length == 4){
+                       /* Spans 4 bytes */     
+                       mask32 = mask32>>(bit_offset&0x7);
+                       if(little_endian){
+                               value=tvb_get_letohl(tvb, offset);
+                       } else {
+                               value=tvb_get_ntohl(tvb, offset);
+                       }
+                       mask = 0x80000000;
+               }else{
+                       /* Spans 5 bytes
+                        * Does not handle unaligned bits over 24
+                        */
+                       DISSECTOR_ASSERT_NOT_REACHED();
+               }
+               shift = 8-((bit_offset + no_of_bits)&0x7);
+               if (shift<8){
+                       value = value >> shift;
+                       mask = mask >> shift;
+               }
+
+       }else{
+               DISSECTOR_ASSERT_NOT_REACHED();
+       }
+
+       /* prepare the string */
+       str=ep_alloc(256);
+       str[0]='\0';
+       for(bit=0;bit<((int)(bit_offset&0x07));bit++){
+               if(bit&&(!(bit%4))){
+                       strcat(str, " ");
+               }
+               strcat(str,".");
+               mask = mask>>1;
+       }
+       /* read the bits for the int */
+       for(i=0;i<no_of_bits;i++){
+               if(bit&&(!(bit%4))){
+                       strcat(str, " ");
+               }
+               if(bit&&(!(bit%8))){
+                       strcat(str, " ");
+               }
+               bit++;
+               tmp = value & mask;
+               if(tmp != 0){
+                       strcat(str, "1");
+               } else {
+                       strcat(str, "0");
+               }
+               mask = mask>>1;
+       }
+       for(;bit%8;bit++){
+               if(bit&&(!(bit%4))){
+                       strcat(str, " ");
+               }
+               strcat(str,".");
+       }
+
+       if(return_value){
+               *return_value=value;
+       }
+       if(hf_index == -1)
+               return NULL;
+
+       strcat(str," = ");
+       strcat(str,hf_field->name);
+
+       if (hf_field->type == FT_BOOLEAN){
+               /* Boolean field */
+               if (hf_field->strings) {
+                       const true_false_string         *tfstring = &tfs_true_false;
+                       tfstring = (const struct true_false_string*) hf_field->strings;
+
+                       return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, value,
+                               "%s: %s",
+                               str,
+                               value ? tfstring->true_string : tfstring->false_string);
+               }else{
+                       return proto_tree_add_boolean_format(tree, hf_index, tvb, offset, length, value,
+                               "%s: %u",
+                               str,
+                               value);
+               }
+       }
+       /* 1 - 32 bits field */
+
+       if (hf_field->strings) {
+               return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, value,
+                      "%s: %s",
+                                         str,
+                                         val_to_str(value, cVALS(hf_field->strings), "Unknown"));
+       }
+       switch(hf_field->display){
+       case BASE_DEC:
+               return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, value,
+                        "%s: %u",
+                                         str,
+                                         value);
+               break;
+       case BASE_HEX:
+               return proto_tree_add_uint_format(tree, hf_index, tvb, offset, length, value,
+                        "%s: 0x%x",
+                                         str,
+                                         value);
+               break;
+       default:
+               DISSECTOR_ASSERT_NOT_REACHED();
+               return NULL;
+               ;
+       }
 
+}
\ No newline at end of file
index f77bbb95722b176b0430ae496dc7c0b34fc0f408..8ea9bde18ad2df97b6ecccf1962f672dd4cd2c80 100644 (file)
@@ -1572,6 +1572,20 @@ proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb);
 extern proto_item *
 proto_tree_add_bitmask(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_hdr, gint ett, const int **fields, gboolean little_endian);
 
+/** Add bitts to a proto_tree, using the text label registered to that item.
+   The item is extracted from the tvbuff handed to it.
+ @param tree the tree to append this item to
+ @param hfindex field index
+ @param tvb the tv buffer of the current data
+ @param bit_offset start of data in tvb expressed in bits
+ @param no_of_bits length of data in tvb expressed in bits
+ @param return_value if a pointer is passed here the value is returned.
+ @param little_endian big or little endian byte representation
+ @return the newly created item */
+
+extern proto_item *
+proto_tree_add_bits(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint32 *return_value, gboolean little_endian);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */