Tengo un cliente de red con un método de solicitud que toma un std::streambuf*
. Este método está implementado por boost::iostreams::copy
-solo en una clase personalizada std::streambuf
-deriva que sabe cómo escribir los datos en una API de red, que funciona muy bien. Esto significa que puedo transmitir un archivo a la solicitud sin necesidad de leerlo todo en la memoria.Transmitir desde std :: cadena sin hacer una copia?
Hay algunos casos, sin embargo, donde se deben enviar grandes bloques de datos que no están en un archivo, por lo que incluí una sobrecarga que toma una cadena. Para evitar la duplicación de todo el código de red en la transmisión, parecía obvio que debería configurar un streambuf
que representara la cadena y llamar al otro método. La única manera de que pudiera averiguar para hacer este trabajo era algo así como:
std::istringstream ss(data);
send(ss.rdbuf());
Desafortunadamente, istringstream
hace una copia de los datos, que en algunos casos es de varios megabytes. Tiene sentido en el caso general, por supuesto, si le das una referencia constante a algún objeto, no quieres que ese objeto asuma que puede continuar usando esa referencia.
trabajé alrededor de este con lo siguiente:
struct zerocopy_istringbuf
: public std::stringbuf
{
zerocopy_istringbuf(std::string const* s)
: std::stringbuf(std::ios::in)
{
char* p = const_cast<char*>(s->c_str());
setg(p, p, p + s->length());
}
};
...
send(&zerocopy_istringbuf(data));
Esto parece funcionar bien, pero me pregunto si es realmente necesario. ¿Por qué std::istringstream
no tiene una sobrecarga teniendo un std::string const *
? ¿Hay una mejor manera de hacer esto?
Una idea interesante. Una de las cosas que me gusta de la configuración existente es que puedo configurar una secuencia de entrada o salida personalizada derivando de 'std :: stringbuf' y solo tengo que anular una o dos funciones simples, underflow o' overflow' y ' sync', la clase base maneja toda la administración de buffer para mí. Sospecho que basar cosas de 'std :: vector' significaría que necesitaría considerablemente más código. De todos modos, podría usar 'swap', aunque necesitaría hacer que la persona que llama" abandonara "la cadena en vez de hacer una referencia constante. –