2011-03-09 9 views
12

std::bitset tiene un método to_string() para serializar como una cadena basada en char de 1 s y 0 s. Obviamente, esto utiliza un solo 8 bits char para cada bit en el conjunto de bits, haciendo que la representación serializada sea 8 veces más larga de lo necesario.
Quiero almacenar el conjunto de bits en una representación binaria para ahorrar espacio. El método to_ulong() es relevante solo cuando hay menos de 32 bits en mi conjunto de bits. Tengo cientos.
No estoy seguro de querer usar memcpy()/std::copy() en el objeto (dirección), ya que eso supone que el objeto es un POD.binario serialización de std :: bitset

La API no parece proporcionar un identificador para la representación de matriz interna de la que podría haber tomado la dirección.

También me gustaría la opción de deserializar el conjunto de bits de la representación binaria.

¿Cómo puedo hacer esto?

+0

Big Endian o Little Endian? Hace una gran diferencia (orden de bits a.k.a)? –

+4

No realmente. Si el conjunto de bits se guarda como una matriz de caracteres, no hay influencia directa para Endianess. –

Respuesta

6

Este es un posible enfoque basado en la creación explícita de un std::vector<unsigned char> leyendo/escribiendo un bit a la vez ...

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

Tenga en cuenta que para llamar a la función de plantilla de-serialización bitset_from_bytes la bitset tamaño N se debe especificar en la llamada de función, por ejemplo

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

Si realmente se preocupan por la velocidad de una solución que ganar algo estaría haciendo un bucle que se desenrolla para que el empaquetado se haga, por ejemplo, un byte a la vez, pero aún mejor es simplemente escribir su propia implementación de conjunto de bits que no oculte la representación binaria interna en lugar de usar std::bitset.

+0

+1 Si la herramienta generalizada no funciona, haga la suya –

0

No puedo ver una manera obvia aparte de convertir a una cadena y hacer tu propia serialización de la cadena que agrupa los trozos de 8 caracteres en un solo byte serializado.

EDITAR: Mejor es simplemente iterar sobre todos los bits con operator[] y serializarlo manualmente.

+0

Quería evitar el intercambio manual de bits, ya que la representación ya está codificada en la matriz continua interna. –

1

editar: Lo siguiente no funciona como se esperaba. Aparentemente, "formato binario" realmente significa "representación ASCII de binario".


Usted debe ser capaz de escribirlos en un std::ostream usando operator<<. Dice here:

[Bitsets] también se pueden insertar y extraer directamente de las secuencias en formato binario.

+0

Sí, vi este comentario. En mi implementación de conjunto de bits, el operador <<() simplemente llama a_cadena(), ¿así que no sé lo que eso significa? ¿Hay alguna otra norma ref. donde esto puede ser mencionado? –

+0

Bien, acabo de probarlo y tampoco funciona. Actualizaré mi respuesta. Lo siento – user634618

+0

Sí, acabo de consultar el estándar y eso es básicamente lo que dice. –

1

Respondiendo a mi propia pregunta para completarla.

Aparentemente, no hay una manera simple de hacer esto con y.

Por simplicidad (aunque no eficiencia), terminé usando to_string, y luego creé bitsets de 32 bits consecutivos de todos los trozos de 32 bits de la cadena (y el resto *), y usando to_ulong en cada uno de estos para recoge los bits en un búfer binario.
Este enfoque deja el twiddling a la propia STL, aunque probablemente no sea la forma más eficiente de hacerlo.

*Tenga en cuenta que ya se std::bitset templated en el bit de recuento total y el resto bitset necesita utilizar alguna plantilla simple meta-programación aritmética.

+0

Su solución es seguramente varias veces más lenta que solo haciendo la serialización leyendo los bits ... – 6502

+0

Quizás. Tendré que probar eso. –

+0

Con g ++ ingenuamente empaquetar los bits en una matriz de char sin signo es un poco más lento que simplemente llamar a 'std :: bitset :: to_string' (y se vuelve más rápido que' to_string' si se hace con 8 bits de desenrollado manual a la vez). Tenga en cuenta que con su solución después de llamar a 'to_string' todavía tiene que hacer la división, reconstruyendo todos los conjuntos de bits, callint' to_ulong' en ellos ... – 6502

2

Según lo sugerido por los chicos en gamedev.net, uno puede intentar usar boost::dynamic_bitset ya que permite el acceso a la representación interna de datos bitpack.

Cuestiones relacionadas