2012-10-24 16 views
16

Ho alcuni dati in un buffer puntato da un puntatore const char*. I dati sono solo una stringa ASCII. Conosco le sue dimensioni. Mi piacerebbe essere in grado di leggerlo nello stesso modo in cui i dati vengono letti dai flussi. Sto cercando una soluzione che mi permettesse di scrivere codice come questo:Creazione di un flusso di input dalla memoria costante

// for example, data points to a string "42 3.14 blah" 
MemoryStreamWrapper in(data, data_size); 
int x; 
float y; 
std::string w; 
in >> x >> y >> w; 

condizione importante: i dati non possono essere copiati o alterati in alcun modo (altrimenti mi basta usare un flusso di stringa Per quanto ne so, non è possibile creare uno stream di stringa da un puntatore const char senza copiare i dati.)

+0

pinging @ Dietmar-Kuhl ... –

+0

qual è il tipo di 'data'? È 'const char *' giusto? –

+0

Sì, è 'const char *' –

risposta

23

Il modo per fare ciò è creare un buffer di flusso adatto. Questo può, per esempio, essere fatto in questo modo:

#include <streambuf> 
#include <istream> 

struct membuf: std::streambuf { 
    membuf(char const* base, size_t size) { 
     char* p(const_cast<char*>(base)); 
     this->setg(p, p, p + size); 
    } 
}; 
struct imemstream: virtual membuf, std::istream { 
    imemstream(char const* base, size_t size) 
     : membuf(base, size) 
     , std::istream(static_cast<std::streambuf*>(this)) { 
    } 
}; 

L'unica cosa alquanto scomoda è la const_cast<char*>() nel buffer flusso: il buffer corrente non cambierà i dati ma l'interfaccia richiede ancora char* da utilizzare, principalmente per semplificare la modifica del buffer nei buffer di flusso "normali". Con questo, è possibile utilizzare imemstream come un flusso di input normale:

imemstream in(data, size); 
in >> value; 
+0

Che cosa significa questo che 'pubsetbuf' di' istringstream' no? – ildjarn

+0

Non puoi semplicemente creare un normale 'std :: istringstream' e tramite' .rdbuf() -> pubsetbuf (data, size) 'fare lo stesso? – Xeo

+0

E 'stato più facile di quanto pensassi! Credo che sia stato complicato perché ho fatto lo stesso per i socket socket, nel qual caso richiede centinaia di righe ... – user1610015

1

L'unico modo sarebbe quello di sottoclasse std :: istream (che richiede anche sottoclasse std :: streambuf) per creare la propria classe di stream che legge dalla memoria costante.

Non è così facile come sembra, perché le classi di flusso della libreria standard C++ sono piuttosto disordinate e mal progettate. Non penso che ne valga la pena a meno che non ne abbia bisogno per scalare molto.

Problemi correlati