He estado escribiendo una versión binaria de iostreams. Básicamente le permite escribir archivos binarios, pero le da mucho control sobre el formato del archivo. Ejemplo de uso: (., donde el prefijo es u16le)Versión binaria de iostream
my_file << binary::u32le << my_int << binary::u16le << my_string;
escribiría my_int como un entero sin signo de 32 bits, y mi_cadena como una cadena de longitud prefijada Para leer el archivo de nuevo, sería voltear las flechas. Funciona genial. Sin embargo, me tocó un bache en el diseño, y todavía estoy en la valla al respecto. Entonces, es hora de preguntar SO. (Hacemos un par de suposiciones, tales como bytes de 8 bits, complementos de complemento 2 y flotantes IEEE en este momento).
iostreams, debajo del capó, use streambufs. Realmente es un diseño fantástico: iostreams codifica la serialización de un 'int
' en texto, y deja que el streambuf subyacente se encargue del resto. Por lo tanto, obtienes cout, fstreams, stringstreams, etc. Todos estos, los iostreams y los streambufs, están modelados, generalmente en char, pero a veces también como un wchar. Sin embargo, mis datos son un flujo de bytes, que mejor se representa por 'unsigned char
'.
Mis primeros intentos fueron crear plantillas de las clases basadas en unsigned char
. std::basic_string
plantillas lo suficientemente bien, pero streambuf
no. Me encontré con varios problemas con una clase llamada codecvt
, que nunca pude seguir el tema unsigned char
. Esto plantea dos preguntas:
1) ¿Por qué es un streambuf responsable de tales cosas? Parece que las conversiones de código se encuentran fuera de la responsabilidad de un streambuf: streambufs debería tomar una secuencia y almacenar datos en búfer desde/hacia ella. Nada mas. Algo de alto nivel como conversiones de código parece que debería pertenecer a iostreams.
Como no pude hacer que los streambufs con plantillas trabajaran con char sin signo, volví a char, y simplemente fundí datos entre char/unsigned char. Traté de minimizar el número de lanzamientos, por razones obvias. La mayoría de los datos básicamente terminan en una función de lectura() o de escritura(), que luego invoca el streambuf subyacente. (Y use un molde en el proceso.) La función de lectura es básicamente:
size_t read(unsigned char *buffer, size_t size)
{
size_t ret;
ret = stream()->sgetn(reinterpret_cast<char *>(buffer), size);
// deal with ret for return size, eof, errors, etc.
...
}
¿Buena solución, mala solución?
Las dos primeras preguntas indican que se necesita más información. En primer lugar, se analizaron proyectos como boost :: serialization, pero existen en un nivel superior, ya que definen su propio formato binario. Esto es más para leer/escribir en un nivel inferior, donde se desea definir el formato, o el formato ya está definido, o los metadatos no son necesarios o deseados.
En segundo lugar, algunos han preguntado sobre el modificador binary::u32le
. Es una ejemplificación de una clase que posee el anhelo y el ancho deseados, por el momento, tal vez firmado en el futuro. La secuencia contiene una copia de la última instancia pasada de esa clase, y la usó en la serialización. Este fue un poco de una solución, que originalmente intentó sobrecarga para el operador < < así:
bostream &operator << (uint8_t n);
bostream &operator << (uint16_t n);
bostream &operator << (uint32_t n);
bostream &operator << (uint64_t n);
Sin embargo en el momento, esto no parece funcionar. Tuve varios problemas con la llamada de función ambigua. Esto fue especialmente cierto en el caso de las constantes, aunque podría, como sugirió un afiche, emitir o simplemente declararlo como const <type>
. Me parece recordar que había otro problema más grande sin embargo.
Su problema de llamada de función ambigua puede deberse al hecho de que [u] int32_t se suele definir como "[unsigned] long". Por lo tanto, si intenta escribir un "[unsigned] int", que suelen ser los literales numéricos, se necesita una promoción, pero el tipo para promocionar es ambiguo (por ejemplo, largo versus doble). –
¿Puede por favor publicar la salida del compilador en esos conflictos que tuvo con unsigned char streambuf? – Basilevs