Pregunta

Dada una cadena binaria codificada en 1 byte, ¿es posible mapear varios de los bits de ese byte en un valor de enumación?
EG: Supongamos que quiero cortar mi campo en esto:

  • bit1 y bit2 = campo1
  • bit3 = campo2
  • bit4 = campo3
  • bit5 = campo4
  • Otros bits no están utilizados

¿Cómo podría mapear eso para decir:

public enum MyEnum {
    FIELD1, FIELD2, FIELD3, FIELD4;

    private static final EnumSet<MyEnum> ALLFIELDS = EnumSet.allOf(MyEnum.class);

}

Lo que estoy tratando de hacer es filtrar estos valores de Enum usando una maspata de bits. Para eso, hice el siguiente método:

public static <E extends Enum<E>> EnumSet<E> filterWithBitMask(EnumSet<E> set, int bitmask) {
    List<E> kept = new ArrayList<E>();
    for (E property : set) {
        if ((bitmask & (1 << ((Enum<E>) property).ordinal())) != 0) {
            kept.add(property);
        }
    }
    EnumSet<E> selectedProperties = set.clone();
    selectedProperties.retainAll(kept);
    return selectedProperties;
}

Esto funciona bien siempre que mis campos enum representan un solo bit, pero no puedo entender cómo combinarlos en un solo campo. Lo siento si eso parece obvio, pero esta es la primera vez que estoy manipulando los datos en el nivel de bits ...

Editar comentarios: edité la estructura de campo para representar lo que realmente tengo. Entonces, el único campo que abarca más de 1 bit es el campo1. Según la presencia de BIT1 y BIT2, asigno una variable de peso al campo1.

public enum MyByte {    
    BIT_1, BIT_2, BIT_3, BIT_4, BIT_5;

    private static final EnumSet<MyByte> ALLPROPERTIES = EnumSet.allOf(MyByte.class);

    public static EnumSet<Fields> getValues(int bitmask) {
        EnumSet<MyByte> selectedBits = filterWithBitMask(ALLPROPERTIES, bitmask);
        int weight = 0;
        EnumSet<Fields> fields = null;
        if (selectedBits.contains(BIT_1)) 
            weight += 1;
        if (selectedBits.contains(BIT_2))
            weight += 2;
        if (selectedBits.contains(BIT_1) || selectedBits.contains(BIT_2)) 
            fields = EnumSet.of(Fields.FIELD1.setValue(weight));
        if (selectedBits.contains(BIT_3)) {
            if (fields != null)
                fields.add(Fields.FIELD2);
            else fields = EnumSet.of(Fields.FIELD2);
        }
        if (selectedBits.contains(BIT_4)) {
            if (fields != null)
                fields.add(Fields.FIELD3);
            else fields = EnumSet.of(Fields.FIELD3);
        }

        if (selectedBits.contains(BIT_5)) {
            if (fields != null)
                fields.add(Fields.FIELD4);
            else fields = EnumSet.of(Fields.FIELD4);
        }

        return fields;
    }

    public enum Fields {

        // BIT_1 and BIT_2
        FIELD1,
        // BIT_3
        FIELD2,
        // BIT_4
        FIELD3,
        // BIT_5
        FIELD4;

        private int value;

        public Fields setValue(int i) {
            this.value = i;
            return this;
        }

    }


}

Aquí está la solución sucia que se me ocurrió por ahora, pero realmente no me gusta con todas esas declaraciones si. Si alguien tiene una mejor solución, me alegraría cambiar esto ;-)

Gracias !

¿Fue útil?

Solución

No estoy seguro de lo que quieres. Esto puede ser de interés:

import java.util.*;
enum Field {
    field1((byte) 0xc0) {
        int filter_(byte mask) { // you may want this one to be different
            return mask & this.mask;
        }
    },
    field2((byte) 0x20), field3((byte) 0x10), field4((byte) 0x08);
    Field(byte mask) {
        this.mask = mask;
    }
    int filter_(byte mask) {
        return mask & this.mask;
    }
    static EnumSet<Field> filter(byte mask) {
        final EnumSet<Field> fields = EnumSet.noneOf(Field.class);
        for (Field field : values())
            if (field.filter_(mask) != 0) fields.add(field);
        return fields;
    }
    final byte mask;
}
public class Main {
    public static void main(String[] args) {
        for(Field field:Field.values()) {
            System.out.println(Field.filter(field.mask));
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top