mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Heath <mhe...@apache.org>
Subject Adding support for EnumSet to ByteBuffer
Date Sat, 09 Jun 2007 06:03:33 GMT
I've been twiddling a lot of bits with MINA and got tired of it so I
created a utility class that converts instances of EnumSet to bit
vectors and vice-versa.

I thought this feature would be a good addition to MINA's ByteBuffer.
Instead of just committing the change, I wanted to run the idea past the
MINA community since ByteBuffer is such an integral part of the MINA
framework.  I propose adding the following to
org.apache.mina.common.ByteBuffer in TRUNK:

    public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass)
{
        return toEnumSet(enumClass, (long)get() & 0xFFL);
    }

    public <E extends Enum<E>> EnumSet<E> getEnumSetShort(Class<E>
enumClass) {
        return toEnumSet(enumClass, ((long)getShort()) & 0xFFFFL);
    }

    public <E extends Enum<E>> EnumSet<E> getEnumSetInt(Class<E>
enumClass) {
        return toEnumSet(enumClass, (long)getInt() & 0xFFFFFFFFL);
    }

    public <E extends Enum<E>> EnumSet<E> getEnumSetLong(Class<E>
enumClass) {
        return toEnumSet(enumClass, getLong());
    }

    private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> enumClass,
long vector) {
        EnumSet<E> set = EnumSet.noneOf(enumClass);
        long mask = 1;
        for (E e : enumClass.getEnumConstants()) {
            if ((mask & vector) == mask) {
                set.add(e);
            }
            mask <<= 1;
        }
        return set;
    }

    public <E extends Enum<E>> void putEnumSet(EnumSet<E> set) {
        put((byte)toLong(set));
    }
    
    public <E extends Enum<E>> void putEnumSetShort(EnumSet<E> set) {
        putShort((short)toLong(set));
    }
    
    public <E extends Enum<E>> void putEnumSetInt(EnumSet<E> set) {
        putInt((int)toLong(set));
    }
    
    public <E extends Enum<E>> void putEnumSetLong(EnumSet<E> set) {
        putLong(toLong(set));
    }
    
    private <E extends Enum<E>> long toLong(EnumSet<E> s) {
        long vector = 0;
        for (E e : s) {
            vector |= 1L << e.ordinal();
        }
        return vector;
    }


It works like this.  Suppose I have a protocol that uses an integer
sized (32-bit) bit mask to send 32 boolean values.  Instead of masking
off each bit to see if it's set or not, I create an enum that represents
each value in the mask like:

public enum MaskValues {
    VALUE_1, // 0x00000001
    VALUE_2, // 0x00000002
    ...,
    VALUE_31, // 0x40000000
    VALUE_32  // 0x80000000
}

I then do:

EnumSet<MaskValues> values = buf.getEnumSetInt(MaskValues.class);

To see if any bit is set I can do values.contains(MaskValues.VALUE_XX)
or to see if a group of bits are set I can do
values.containsAll(EnumSet.of(MaskValues.VALUE_XX, MaskValues.VALUE_YY))
and so on.  This is much easier to read then:

int bitVector = buf.getInt();
if (bitVector & mask == mask) { do something }

The putXXXX methods provide a mechanism for putting an EnumSet into the
ByteBuffer as a bit vector.

If this functionality is desired, I'll add some Java Docs to the above
methods and commit my code and accompanying unit tests.

-Mike


Mime
View raw message