inizializzare uno std C ++ :: istringstream da un nel buffer di memoria?
Domanda
Ho un blocco di memoria (opaco), che voglio conservare in un blob in MySQL attraverso il loro adattatore di C ++. L'adattatore si aspetta un istream:
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Quindi la mia domanda è: come posso creare uno std :: istream da questo blocco di memoria (digitato come char *). Non è una stringa come non è terminata da null (ma so che la sua lunghezza, naturalmente).
non riuscivo a trovare un modo per farlo senza copiare il blocco di memoria per esempio in uno std :: string. Penso che questo sia un po 'uno spreco. Qualcosa di simile a questo non funziona:
std::streambuf istringbuf(blockPtr, blockLength);
std::istringstream tmp_blob(&istringbuf);
perché std :: doesnt streambuf hanno un tale costruttore. Ho visto il seguente suggerimento.
std:: istringstream tmp_blob;
tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
E 'questo il modo corretto?
Soluzione
Guarda std :: istrstream ha un costruttore
istrstream( char* pch, int nLength );
Questa classe è una sorta di deprezzato o almeno si sono normalmente ha detto di usare altre classi.
Il problema con strstream è che è più complesso da gestire la memoria del buffer char * così, in generale, si preferisce stringstream come fa la gestione della memoria per voi. Tuttavia, in questo caso si sta già gestendo la memoria del char * in modo che il beneficio normale è in questo caso un costo. Infatti in questo caso strstream fa esattamente quello che vuoi con un overhead minimo nel codice o la velocità. Questo è simile alla discussione di ostrsteram da Herb Sutter
Altri suggerimenti
In realtà è piuttosto banale per scrivere un one-shot std::streambuf
che utilizza il buffer in luogo come il comportamento predefinito di tutte le funzioni virtuali di std::streambuf
fa 'la cosa giusta'. Si può solo setg
l'area di lettura nella costruzione e underflow
e uflow
può tranquillamente essere lasciato per tornare traits_type::eof()
come la fine del l'area iniziale get è la fine del flusso.
per esempio:.
#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 ha un flusso che funziona come uno stringstream, ma avvolge una matrice nativa, in modo da evitare di dover copiare i dati.
std :: stringstream crea sempre un proprio buffer interno
Non testato, ma forse vale la pena di un test ...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
Quindi chiamare quella funzione setBlob con ss. Il tuo ancora che buffer interno in std :: stringstream come JALF già detto però.