9

I have a problem that I am a bit stuck on and I was informed by a colleague that this would be a good place to seek help.

I am trying to implement a C style bitfield in Java. Here is a rough example (I do not have the actual code in front of me at this moment).

typedef union
{
  typedef struct
  {
     unsigned short a :1;
     unsigned short b :1;
     unsigned short c :2;
     unsigned short d :10;
  } bitfield;

  unsigned short bitmap;
}example_bitfield;

I have a good bit of similar style bitfields from legacy code. The reason that I need to come up with an equivalent method for Java is that I am working on code that will use Java to communicate with other legacy applications using UDP.

I do not have the option of rewriting the code. I am aware that this approach is not portable, has endianness issues (and padding/alignment, ect), and could be done a better way if I were able to rewrite the code. Unfortunately I need an answer to this very specific problem. The system is closed and so I do not need to worry about every single possible combination of compilers/operating systems/ect.

The approach of using a Java EnumSet will not work because I believe that will only allow for each value to be one bit. I need to be able to pack values with for instance the value of d occupying 10 bits.

I know about the Java Bitset but it has limitations. I am using an older version of Java, and so I do not have some of the newer Java Bitset methods (Namely the valueOf methods which would probably surely help).

Does anyone have any ideas of how to make this as manageable as possible? I have over 10 bitfields that I need to implement for my communications.

Thank you for any help you can provide!

shadowisadog
  • 123
  • 1
  • 1
  • 5
  • 1
    Note that your original example is actually undefined behavior. – obataku Sep 22 '12 at 17:32
  • As you have an old and limited version of Java, can you tell us what it is? – Peter Lawrey Sep 22 '12 at 17:36
  • It is Java SE 6. Technically the bitfields are being compiled with a c++ compiler. I believe c++ added support for using types other than integers. If it is undefined, I can accept that... I don't have the option to correct it, and whatever behavior it is currently doing is what I have to emulate. – shadowisadog Sep 22 '12 at 17:46

4 Answers4

7

Since UDP accepts only byte arrays, you can declare a Java class in any suitable way and the only critical step is to define its serialization and deserialization methods:

class example_bitfield {
  byte a;
  byte b;
  byte c;
  short d;

  public void fromArray(byte[] m) {
    byte b0=m[0];
    byte b1=m[1];
    a=b0>>>7;
    b=(b0>>6)&1;
    c=(b0>>4)&3;
    d=(b0&0xF<<6)|(b1>>>2);
  }
  public void toArray(byte[] m) {
    m[0]=(a<<7)|(b<<6)|(c<<4)|(d>>>6);
    m[1]=(d&0x3F)<<2;
  }
}
MWB
  • 11,740
  • 6
  • 46
  • 91
Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
  • Yes good point and thank you for the feedback. I am still hoping for a more general solution because I have so many bitfields to deal with. Doing each manually seems like it would be a very painful experience. – shadowisadog Sep 22 '12 at 19:06
  • 1
    Be careful that you don't set any of the member values to outside their valid range, or add some masks on serialization; right now, serializing `a = 2` would result in `a = 0`, `b = 1`. – willglynn Sep 22 '12 at 19:43
  • The code above maybe wrong. The 'a' field should be the lowest bit of lowest byte. So the correct code to read 'a' is: `a=b0 & 0x01`, the remaining fields all needs rewrite. – Bob Yang Oct 16 '22 at 04:57
5

Class Struct from Javolution library makes what you need (http://www.javolution.org/apidocs/index.html?javolution/io/Struct.html) See "Clock" example:

 import java.nio.ByteBuffer;
 class Clock extends Struct { // Hardware clock mapped to memory.
     Unsigned16 seconds  = new Unsigned16(5); // unsigned short seconds:5
     Unsigned16 minutes  = new Unsigned16(5); // unsigned short minutes:5
     Unsigned16 hours    = new Unsigned16(4); // unsigned short hours:4
     Clock() {
         setByteBuffer(Clock.nativeBuffer(), 0);
     }
     private static native ByteBuffer nativeBuffer();
 }
ant
  • 151
  • 2
  • 2
3

I ended up using a similar approach presented here: What is the most efficent way in Java to pack bits

And then I made a wrapper class that uses LinkedHashMap to store the individual bit field entries.

Each field was implemented as a class that stores the number of bits and the value of the field. The name of the field is the key to the LinkedHashMap.

I added methods for starting and ending a structure, a method to add a bit field to the structure, and methods for getting and setting values based on keys.

My pack method iterates through the LinkedHashMap and puts the bits while keeping track of the bit offset (I just used an integer for this purpose).

The unpack method also iterates the LinkedHashMap and gets the bits, keeping track of the bit offset, and storing the values in the LinkedHashMap.

For convenience I wrote methods for packing the bit fields to integers, shorts, longs, and a byte. To convert between the byte array and the values I used a ByteBuffer and called the wrap method.

I also wrote methods for unpacking a packed integer, short, long, or byte by first allocating the ByteBuffer for the number of bytes that the data type has (4 for integer, 2 for short, ect) and then calling the various put methods of the ByteBuffer. Once I had a byte array I was able to pass that to the unpack method.

I went with this approach because I needed something self contained, that was easy to work with, and that was fairly easy for other people to follow... I know there are probably more elegant ways involving annotations or other things (I found JavaStruct but it didn't incorporate bit fields.)

Packing and unpacking from various primitive data types enable me to read and write the results from a DataInputStream/DataOutputStream easier.

I am sorry that I am unable to post the code for everyone to benefit from, so the above explanation will have to suffice. Hopefully it will help someone in a similar situation :).

Community
  • 1
  • 1
shadowisadog
  • 123
  • 1
  • 1
  • 5
1

Some cursory searching didn't reveal any libraries to make this easy, but you could always pack and unpack things by hand with bitwise operations:

class ExampleBitfield {
    int bitfield;      // actually 16 bits

    public int getBitfield() {
        return bitfield;
    }
    public void setBitfield(int bitfield) {
        this.bitfield = bitfield & 0xffff;
    }

    // lowest bit
    public int getA() {
        return (bitfield >> 0) & 0x01;
    }
    public int setA(int a) {
        return (bitfield & ~0x01) | ((a & 0x01) << 0);
    }

    // second lowest bit
    public int getB() {
        return (bitfield >> 1) & 0x01;
    }
    public int setB(int b) {
        return (bitfield & ~0x02) | ((b & 0x01) << 1);
    }

    // ...
}
willglynn
  • 11,210
  • 48
  • 40
  • Thank you willglynn. I was aware that this is possible, however given the number of bitfields that I have to handle, I was afraid this approach would be hard to manage and could be difficult to debug. I had found this [link](http://stackoverflow.com/questions/7604653/what-is-the-most-efficient-way-in-java-to-pack-bits-into-byte-and-read-it-back) Which seems similar to your approach but perhaps somewhat more generic. – shadowisadog Sep 22 '12 at 18:29