9
votes

Mise en œuvre d'un bitfield de style C en Java

J'ai un problème que je suis un peu coincé et j'ai été informé par un collègue que ce serait un bon endroit pour demander de l'aide.

J'essaie de mettre en place un bitfield de style C à Java. Voici un exemple rugueux (je n'ai pas le code actuel devant moi en ce moment). P>

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;


3 commentaires

Notez que votre exemple original est en réalité un comportement indéfini.


Comme vous avez une version ancienne et limitée de Java, pouvez-vous nous dire ce que c'est?


C'est Java SE 6. Techniquement, les fitfields sont compilés avec un compilateur C ++. Je crois que la prise en charge ajoutée C ++ pour utiliser des types autres que des entiers. Si cela est indéfini, je peux accepter cela ... Je n'ai pas la possibilité de le corriger, et quel que soit le comportement qu'il fait actuellement est ce que je dois imiter.


4 Réponses :


1
votes

Certaines recherches superficielles n'ont révélé aucune bibliothèque pour le rendre facile, mais vous pouvez toujours emballer et déballer les choses à la main avec les opérations bitwises:

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);
    }

    // ...
}


1 commentaires

Merci Willglynn. J'étais conscient que cela est possible, cependant, compte tenu du nombre de fitfields que je dois gérer, j'avais peur que cette approche ne soit difficile de gérer et pourrait être difficile à déboguer. J'avais trouvé cela lien qui semble semblable à votre approche, mais peut-être un peu plus générique.



7
votes

Etant donné que UDP accepte uniquement les tableaux d'octets, vous pouvez déclarer une classe Java de n'importe quelle manière appropriée et la seule étape critique consiste à définir ses méthodes de sérialisation et de désérialisation: xxx


2 commentaires

Oui bon point et merci pour les commentaires. J'espère toujours une solution plus générale parce que j'ai tellement de fictifs à traiter. Faire chaque manuellement semble être une expérience très douloureuse.


Soyez prudent que vous ne définissez aucune des valeurs de membre à l'extérieur de leur portée valide ou d'ajouter des masques sur la sérialisation; En ce moment, sérialiser A = 2 aboutirait à a = 0 , b = 1 .



3
votes

J'ai fini par utiliser une approche similaire présentée ici: Quelle est la manière la plus efficace en Java pour emballer des bits

Et puis j'ai fait une classe wrapper qui utilise LinkedHashMap pour stocker les entrées individuelles du terrain.

Chaque champ a été implémenté comme une classe qui stocke le nombre de bits et la valeur du champ. Le nom du champ est la clé du linkedHashMap.

J'ai ajouté des méthodes pour démarrer et mettre fin à une structure, une méthode pour ajouter un champ de bits à la structure et les procédés de définition de valeurs en fonction des clés.

My Pack Methy iTère à travers le LinkedHashMap et met les bits tout en gardant une trace du décalage du bit (je viens d'utiliser un entier à cet effet).

La méthode de déballage énorme également le LinkedHashMap et obtient les bits, en gardant une trace du décalage du bit et stocke les valeurs dans LinkedHashMap.

Pour plus de commodité, j'ai écrit des méthodes pour emballer les champs de bits aux entiers, shorts, longs et d'octets. Pour convertir entre la matrice d'octet et les valeurs, j'ai utilisé un bytebuffer et appelé méthode wrap.

J'ai également écrit des méthodes pour déballier un entier emballé, court, long ou octet en allouant d'abord le bytebuffer pour le nombre d'octets que le type de données a (4 pour entier, 2 pour court, ECT), puis appelant les différents mettre des méthodes de l'octebuffer. Une fois que j'avais un tableau d'octets, j'ai pu passer cela à la méthode de déballage.

Je suis allé avec cette approche parce que j'avais besoin de quelque chose de soi-à-don de tâches, et c'était assez facile pour les autres personnes à suivre ... Je sais qu'il y a probablement plus de moyens plus élégants impliquant des annotations ou d'autres choses (je trouvé javâduct mais il n'a pas incorporé des champs de bits.)

Emballage et déballage à partir de divers types de données primitifs me permettent de lire et d'écrire les résultats d'un fichier DataGuTretstream / DataOutPutStream.

Je suis désolé de ne pas pouvoir poster le code pour que tout le monde bénéficie, de sorte que l'explication ci-dessus devra suffire. Espérons que cela aidera quelqu'un dans une situation similaire :).


0 commentaires

5
votes

La structure de classe de la bibliothèque Javolution fait ce dont vous avez besoin ( http: //www.javolution.org/apidocs/index.html?javolution/io/truct.html ) Voir Exemple "Horloge":

 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();
 }


0 commentaires