inicializar um C ++ std :: istringstream de um no buffer de memória?
Pergunta
Eu tenho um bloco de memória (opaco), que eu quero para armazenar em um Blob no MySQL através do seu adaptador de C ++. O adaptador espera um istream:
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Então, minha pergunta é: como posso criar um std :: istream deste bloco de memória (digitado como char *). Não é uma cadeia, pois não é terminada em nulo (mas eu sei que seu comprimento é claro).
Eu não poderia encontrar uma maneira de fazê-lo sem copiar o meu bloco de memória, por exemplo, em um std :: string. Eu acho que isso é um pouco desperdício. Algo como isso não funciona:
std::streambuf istringbuf(blockPtr, blockLength);
std::istringstream tmp_blob(&istringbuf);
porque std :: streambuf esquentar têm como um construtor. Eu vi a seguinte sugestão.
std:: istringstream tmp_blob;
tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
É essa a maneira correta?
Solução
Olhe para std :: istrstream tem um construtor
istrstream( char* pch, int nLength );
Esta classe é uma espécie de depreciado ou pelo menos você normalmente são instruídos a usar outras classes.
O problema com strstream é que ele é mais complexo para gerenciar a memória do char * buffer de modo em geral você preferir stringstream como faz o gerenciamento de memória para você. No entanto, neste caso, você já está gerenciando a memória do char * assim o benefício normal é neste caso um custo. Na verdade, neste caso strstream faz exatamente o que você quer com sobrecarga mínima no código ou velocidade. Isto é semelhante à discussão de ostrsteram por Herb Sutter
Outras dicas
É realmente muito trivial para escrever um std::streambuf
one-shot que usa o tampão no lugar como o comportamento padrão de todas as funções virtuais de std::streambuf
faz 'a coisa certa'. Você pode apenas setg
a área de leitura na construção e underflow
e uflow
pode seguramente ser deixado para traits_type::eof()
retorno como o fim da área get inicial é o fim do fluxo.
por exemplo:.
#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 tem um fluxo que funciona como um stringstream, mas envolve uma matriz nativa, de modo a evitar ter que copiar os dados.
std :: stringstream sempre cria seu próprio buffer interno
teste de um Untested mas talvez valha a pena ...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
Em seguida, chamar essa função setBlob com ss. Sua ainda tem que buffer interno em std :: stringstream como jalf já mencionado embora.