Ho un client di rete con un metodo di richiesta che accetta uno std::streambuf*
. Questo metodo è implementato da boost::iostreams::copy
inserendolo in una classe personalizzata di std::streambuf
che sa come scrivere i dati su un'API di rete, che funziona perfettamente. Ciò significa che posso eseguire il flusso di un file nella richiesta senza che sia necessario leggerlo tutto in memoria.Stream da std :: string senza fare una copia?
Ci sono alcuni casi, tuttavia, in cui devono essere inviati grandi blocchi di dati che non sono in un file, quindi ho incluso un sovraccarico che accetta una stringa. Per evitare la duplicazione di tutto il codice di rete nel flusso, è sembrato ovvio che dovrei impostare uno streambuf
che rappresenta la stringa e chiamare l'altro metodo. L'unico modo che ho potuto capire per fare questo lavoro è stato qualcosa di simile:
std::istringstream ss(data);
send(ss.rdbuf());
Purtroppo, istringstream
fa una copia dei dati, che in alcuni casi è di diversi megabyte. Ha perfettamente senso nel caso generale, naturalmente, se si consegna un riferimento const a un oggetto, non si vuole che l'oggetto, supponendolo, possa continuare ad usare quel riferimento.
ho lavorato intorno a questo con il seguente:
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));
Questo sembra funzionare bene, ma mi chiedo se è veramente necessario. Perché lo std::istringstream
non ha un sovraccarico che prende uno std::string const *
? C'è un modo migliore per farlo?
Un'idea interessante. Una delle cose che mi piace dell'installazione esistente è che posso impostare un flusso di input o output personalizzato derivando da 'std :: stringbuf' e devo solo sostituire una o due semplici funzioni, underflow o' overflow' e ' sync', la classe base gestisce tutta la gestione del buffer per me. Sospetto che basare le cose su 'std :: vector' significherebbe che avrei bisogno di molto più codice. Potrei essere in grado di usare lo swap in ogni caso, anche se avrei bisogno che il chiamante "rinunci" alla stringa piuttosto che passare un riferimento costante. –