l'initialisation d'un C ++ std :: istringstream à partir d'un tampon dans la mémoire?
Question
J'ai un bloc de mémoire (opaque), que je veux stocker dans un Blob dans mySQL par leur adaptateur C ++. L'adaptateur attend un istream:
virtual void setBlob(unsigned int parameterIndex, std::istream * blob) = 0;
Alors ma question est: comment puis-je créer un std :: istream de ce bloc de mémoire (typée comme char *). Ce n'est pas une chaîne comme il est non nul terminé (mais je sais que sa longueur bien sûr).
Je ne pouvais pas trouver un moyen de le faire sans copier mon bloc de mémoire par exemple dans un std :: string. Je pense que c'est un peu inutile. Quelque chose comme cela ne fonctionne pas:
std::streambuf istringbuf(blockPtr, blockLength);
std::istringstream tmp_blob(&istringbuf);
parce que std :: ne marche pas streambuf ont un tel constructeur. J'ai vu la suggestion suivante.
std:: istringstream tmp_blob;
tmp_blob.rdbuf()->pubsetbuf(blockPtr, blockLength);
Est-ce la bonne façon?
La solution
Regardez std :: istrstream il a un constructeur
istrstream( char* pch, int nLength );
Cette classe est un peu dépréciée ou au moins vous êtes normalement dit d'utiliser d'autres classes.
Le problème avec strstream est qu'il est plus complexe à gérer la mémoire du tampon char * si en général vous préférez stringstream comme il le fait de la gestion de la mémoire pour vous. Toutefois, dans ce cas, vous gérez déjà la mémoire du char * si le bénéfice est normale dans ce cas un coût. En fait, dans ce cas strstream fait exactement ce que vous voulez avec un minimum de frais généraux dans le code ou la vitesse. Ceci est similaire à la discussion sur ostrsteram par Herb Sutter
Autres conseils
Il est en fait assez trivial d'écrire un std::streambuf
one-shot qui utilise la mémoire tampon en place le comportement par défaut de toutes les fonctions virtuelles de std::streambuf
fait la bonne chose ». Vous pouvez juste setg
la zone de lecture dans la construction et underflow
et en toute sécurité uflow
peut être laissé revenir traits_type::eof()
comme la fin de la zone get initiale est la fin du flux.
par exemple:.
#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 a un flux qui fonctionne comme un stringstream, mais encapsule un tableau natif, ce qui vous évite d'avoir à copier les données.
std :: stringstream crée toujours son propre tampon interne
Non testé, mais peut-être vaut un test ...
std::stringstream ss;
ss.write( blockPtr, blockLength );
ss.seekg(0);
Ensuite, appelez cette fonction de setBLOB avec art. Avez-vous encore que la mémoire tampon interne dans std :: stringstream comme jalf déjà mentionné cependant.