2011-03-09 5 views
12

std::bitset a une méthode to_string() pour sérialisation comme char chaîne de 1 s à base et 0 s. Évidemment, cela utilise un seul bit 812 char pour chaque bit dans le bitset, rendant la représentation sérialisée 8 fois plus longtemps que nécessaire.
Je veux stocker le bitset dans une représentation binaire pour économiser de l'espace. La méthode to_ulong() n'est pertinente que s'il y a moins de 32 bits dans mon bitset. J'ai des centaines.
Je ne suis pas sûr que je veux utiliser memcpy()/std::copy() sur l'objet (adresse) lui-même, car cela suppose que l'objet est un POD.binaire sérialisation de std :: bitset

L'API ne semble pas fournir un handle à la représentation de tableau interne à partir de laquelle j'aurais pu prendre l'adresse.

Je voudrais également que l'option désérialise le bitset de la représentation binaire.

Comment est-ce que je peux faire ceci?

+0

Big Endian ou Little Endian? Fait une grande différence (a.k.a.bord de commande)? –

+4

Pas vraiment. Si le bitset est enregistré sous la forme d'un tableau de caractères, il n'y a pas d'influence directe sur Endianess. –

Répondre

6

Il s'agit d'une approche possible basée sur la création explicite d'un std::vector<unsigned char> en lisant/écrivant un bit à la fois ...

template<size_t N> 
std::vector<unsigned char> bitset_to_bytes(const std::bitset<N>& bs) 
{ 
    std::vector<unsigned char> result((N + 7) >> 3); 
    for (int j=0; j<int(N); j++) 
     result[j>>3] |= (bs[j] << (j & 7)); 
    return result; 
} 

template<size_t N> 
std::bitset<N> bitset_from_bytes(const std::vector<unsigned char>& buf) 
{ 
    assert(buf.size() == ((N + 7) >> 3)); 
    std::bitset<N> result; 
    for (int j=0; j<int(N); j++) 
     result[j] = ((buf[j>>3] >> (j & 7)) & 1); 
    return result; 
} 

Notez que pour appeler le modèle de-sérialisation fonction bitset_from_bytes la taille bitset N doit être spécifié dans l'appel de fonction, par exemple

std::bitset<N> bs1; 
... 
std::vector<unsigned char> buffer = bitset_to_bytes(bs1); 
... 
std::bitset<N> bs2 = bitset_from_bytes<N>(buffer); 

Si vous tenez vraiment à la vitesse d'une solution qui gagnerait Quelque chose ferait une boucle déroulant de sorte que l'empaquetage soit fait par exemple un octet à la fois, mais encore mieux est juste pour écrire votre propre implémentation de bitset qui ne cache pas la représentation binaire interne au lieu d'utiliser std::bitset.

+0

+1 Si l'outil généralisé ne fonctionne pas, faites le vôtre –

0

Je ne vois pas d'autre moyen que de convertir en chaîne et de faire votre propre sérialisation de la chaîne qui regroupe des blocs de 8 caractères en un seul octet sérialisé.

EDIT: Il est préférable d'itérer simplement sur tous les bits avec operator[] et de le sérialiser manuellement.

+0

Je voulais éviter le twittling manuel, car la représentation est déjà codée dans le tableau continu interne. –

1

edit: Ce qui suit ne fonctionne pas comme prévu. Apparemment, "format binaire" signifie en réalité "représentation ASCII de binaire".


Vous devriez être en mesure de les écrire à un std::ostream en utilisant operator<<. Il est dit here:

[Bitsets] peuvent également être directement insérés et extraits de flux au format binaire.

+0

Oui, j'ai vu ce commentaire. Dans mon implémentation de bitset, l'opérateur <<() appelle simplement to_string(), donc je ne sais pas ce que cela signifie? Y a-t-il d'autres références standards? où cela pourrait être mentionné? –

+0

Bon, je viens de le tester et ça ne marche pas non plus. Je vais mettre à jour ma réponse. Désolé – user634618

+0

Oui, je viens de vérifier la norme et c'est essentiellement ce qu'il dit. –

1

Répondre à ma propre question pour l'exhaustivité.

Apparemment, il n'y a pas de moyen simple de faire cela. Pour simplifier (mais pas l'efficacité), j'ai fini par utiliser to_string, puis créer des bitsets consécutifs de 32 bits à partir de tous les morceaux de 32 bits de la chaîne (et le reste *), et en utilisant to_ulong sur chacun de ces collecter les bits dans un tampon binaire.
Cette approche laisse le bit-twiddling à la STL elle-même, même si ce n'est probablement pas le moyen le plus efficace de le faire.

*Notez que depuis std::bitset est templated sur le bit nombre total, le reste bitset doit utiliser un modèle arithmétique simple méta-programmation.

+0

Votre solution est sûrement plusieurs fois plus lente que de simplement faire la sérialisation en lisant les bits ... – 6502

+0

Peut-être. Je vais devoir tester ça. –

+0

Avec g ++ nasser naïvement les bits dans un tableau de unsigned char est un peu plus lent que d'appeler 'std :: bitset :: to_string' (et devient plus rapide que' to_string' si on le déroule manuellement 8 bits à la fois). Notez qu'avec votre solution après avoir appelé 'to_string' vous avez encore à faire le fractionnement, en reconstruisant tous les bitsets, callint' to_ulong' sur eux ... – 6502

2

Comme suggéré par les gars à gamedev.net, on peut essayer d'utiliser boost::dynamic_bitset car il permet l'accès à la représentation interne des données bitpacked.

Questions connexes