inicializar un std :: C ++ istringstream de una en la memoria intermedia?
Pregunta
Tengo un bloque de memoria (opaco), que quiero almacenar en un Blob en MySQL a través de su adaptador de C ++. El adaptador espera una istream:
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Así que mi pregunta es: ¿Cómo puedo crear un std :: istream de este bloque de memoria (a máquina como char *). No es una cadena, ya que no es terminada en cero (pero sé de su longitud, por supuesto).
No pude encontrar una manera de hacerlo sin necesidad de copiar mi bloque de memoria, por ejemplo, en un std :: string. Creo que esto es un poco desperdicio. Algo como esto no funciona:
std::streambuf istringbuf(blockPtr, blockLength);
std::istringstream tmp_blob(&istringbuf);
debido a std :: duerma streambuf tienen un constructor tales. Vi la siguiente sugerencia.
std:: istringstream tmp_blob;
tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
Es esa la forma correcta?
Solución
Mira std :: istrstream que tiene un constructor
istrstream( char* pch, int nLength );
Esta clase es una especie de depreciación o por lo menos que normalmente se les dice a utilizar otras clases.
El problema con strstream es que es más difícil de gestionar la memoria del búfer char * lo que en general se prefiere stringstream como lo hace la gestión de memoria para usted. Sin embargo, en este caso ya está gestionando la memoria de la char * por lo que el beneficio normal es en este caso un costo. De hecho, en este caso strstream hace exactamente lo que desea con una sobrecarga mínima en el código o la velocidad. Esto es similar a la discusión de ostrsteram por Herb Sutter
Otros consejos
En realidad es bastante trivial para escribir una std::streambuf
de un solo disparo que utiliza el búfer en el lugar como el comportamiento por defecto de todas las funciones virtuales de std::streambuf
hace 'lo correcto'. Puede simplemente setg
el área de lectura en la construcción y underflow
y uflow
con seguridad se puede dejar de volver traits_type::eof()
como el final de la zona inicial get es el final de la secuencia.
por ejemplo:.
#include <streambuf>
#include <iostream>
#include <istream>
#include <ostream>
struct OneShotReadBuf : public std::streambuf
{
OneShotReadBuf(char* s, std::size_t n)
{
setg(s, s, s + n);
}
};
char hw[] = "Hello, World!\n";
int main()
{
// In this case disregard the null terminator
OneShotReadBuf osrb(hw, sizeof hw - 1);
std::istream istr(&osrb);
istr >> std::cout.rdbuf();
}
Boost.IOStreams tiene una corriente que funciona como un stringstream, pero envuelve una matriz nativa, por lo que se evita tener que copiar los datos.
std :: stringstream crea siempre su propio buffer interno
No comprobado pero quizás vale la pena una prueba ...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
A continuación, llamar a esa función con setBlob ss. Su todavía tienen que buffer interno en std :: stringstream como ya se ha mencionado, aunque JALF.