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?

È stato utile?

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ò.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top