je cherche à encapsuler un buffer dans un ostream afin de pouvoir y
accéder de la manière suivante:
void TestOutStream(ostream & a_oStream)
{
a_oStream << "HELLO" << endl << "WORLD" << endl;
a_oStream << "FOO\nBAR" << endl;
a_oStream << "\001\002\003" << endl;
cout << "=> tellp: " << a_oStream.tellp() << endl;
}
const unsigned int SIZE = 32;
char buf[SIZE];
ostream.SetBuffer(buf, SIZE); /// voici ce que j'aimerais arriver à
faire
TestOutStream(ostream);
cout << buf << endl;
L'écriture dans le ostream (ou classe dérivée, bien entendu)
entrainerait une écriture dans le buffer buf. Le débordement serait
également géré.
Existe-t-il des classes std faisant ce que je viens de décrire?
Comment dois-je m'y prendre?
Merci beaucoup pour votre aide
Philippe
Il existe ostringstream mais je suppose que tu veux t'épargner une
copy.
> Comment dois-je m'y prendre?
Il est peut être possible d'utiliser un streambuf() nu en utilisant
pubsetbuf() pour positionner le buffer. Je n'ai jamais essayé
Sinon, faire un bufferbuf sur le modèle de stringbuf.
En rapide: hériter de streambuf et redefinir:
- underflow(): lire un char du buffer
- overflow(): écrire un char dans le buffer
--
Michael
> Il est peut être possible d'utiliser un streambuf() nu en utilisant
> pubsetbuf() pour positionner lebuffer. Je n'ai jamais essayé
>
J'avais oublié de le marqué dans mon premier message mais j'ai fais le
test avec pubsetbuf().
const unsigned int SIZE = 32;
char buf[SIZE];
ostringstream testStream(ostringstream::out | ostringstream::in);
testStream.rdbuf()->pubsetbuf(buf, SIZE);
TestOutStream(testStream);
à la sortie, buf n'est absolument pas modifié, et pour cause:
_Myt *pubsetbuf(_Elem *_Buffer, streamsize _Count)
{ // offer _Buffer to external agent
return (setbuf(_Buffer, _Count));
}
virtual _Myt *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize)
{ // offer buffer to external agent (do nothing)
return (this);
}
ces deux méthodes sont définie dans la classe basic_streambuf
Très surprenant, jusqu'à présent je faisais mes tests sous Visual
Studio 2005 mais il semble que le même code (utilisant la méthode
pubsetbuf()) fonctionne correctement sous Cygwin. Dois-je en déduire
que c'est l'implémentation des stream std de Microsoft qui est..
foireuse?
Philippe
Je parlait d'utiliser un streambuf pas un stringbuf. stringbuf
redefinit setbuf() donc tu as un comportement qui dépends de
l'implémentation et en plus, ton buffer peut être 'vidé' vers la
string.
Je pensais plutôt à:
streambuf sbuf;
sbuf.pubsetbuf(buf,sizeof(buf));
ostream os(sbuf);
os<<"test";
Je ne sais pas comment ostream gère le buffer en cas d'overflow() qui
rate (je suppose que c'est le comportement par défaut d'overflow()).
Tu vas sûrement avoir un flag bad_bit levé.
--
Michael
le problème est que streambuf n'est pas instanciable: "This is an
abstract base class, therefore no objects can be directly instantiated
from it. The standard hierarchy defines two classes derived from this
one that can be used to directly instantiate objects: filebuf and
stringbuf."
A ce que je comprend, je ne peux utiliser que stringbuf ou filebuf
mais filebuf ne me parrait pas adapté.
A la vue de ce que tu me montre, j'ai légerement changé mon code. A la
place de
ostringstream testStream(ostringstream::out | ostringstream::in);
testStream.rdbuf()->pubsetbuf(buf, SIZE);
TestOutStream(testStream);
j'ai écris
stringbuf sbuf;
sbuf.pubsetbuf(buf, SIZE);
ostream os(&sbuf);
Je suis obligé d'écrire stringbuf et pas streambuf car cette dernière
n'est pas instanciable.
Au final, le problème reste le même: ça marche sous Cygwin/G++ et pas
sous Visual Studio 2005, problème toujours dans la fonction
basic_streambuf::setbuf.
(a ce propos, je me dis que même si streambuf était instanciable, elle
réutiliserait également la fonction setbuf de basic_streambuf et donc
aurait le même problème)
Même si le problème s'avère plus délicat que ce que je pensais au
début, merci encore de votre aide.
Philippe
Je viens de trouver qu'il existe une classe qui fait ce que je veux:
strstream
strstream myStrStream(buf, SIZE);
TestOutStream(myStrStream);
Cependant, elle est indiqué comme étant obsolète!!! et il est
conseillé d'utiliser les classe de définies dans le header sstream.
Quelqu'un sait-il comment faire faire l'équivalent de strstream avec
les classes de sstream?
Merci d'avance pour votre aide
Philippe
AMHA il vaut mieux que tu définisses ton propre streambuf quitte a
refaire quelque chose comme strstream (qui doit être pré-standard).
--
Michael
> > > On 30 déc, 10:12, Philippe MESMEUR <philippe.mesm...@gmail.com> wrote:
> > > Il est peut être possible d'utiliser un streambuf() nu en
> > > utilisant pubsetbuf() pour positionner lebuffer. Je n'ai
> > > jamais essayé
> > J'avais oublié de le marqué dans mon premier message mais
> > j'ai fais le test avecpubsetbuf().
> > const unsigned int SIZE = 32;
> > char buf[SIZE];
> > ostringstream testStream(ostringstream::out | ostringstream::in);
> > testStream.rdbuf()->pubsetbuf(buf, SIZE);
> > TestOutStream(testStream);
> > à la sortie, buf n'est absolument pas modifié, et pour cause:
> > _Myt *pubsetbuf(_Elem *_Buffer, streamsize _Count)
> > { // offer _Buffer to external agent
> > return (setbuf(_Buffer, _Count));
> > }
> > virtual _Myt *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize)
> > { // offer buffer to external agent (do nothing)
> > return (this);
> > }
> > ces deux méthodes sont définie dans la classe basic_streambuf
Si mes souvenirs sont bons, c'est ce qu'exige la norme. Mais tu
ne te sers pas de basic_streambuf.
> > > Sinon, faire un bufferbuf sur le modèle de stringbuf.
> > > En rapide: hériter de streambuf et redefinir:
> > > - underflow(): lire un char dubuffer
> > > - overflow(): écrire un char dans lebuffer
> Très surprenant, jusqu'à présent je faisais mes tests sous
> Visual Studio 2005 mais il semble que le même code (utilisant
> la méthode pubsetbuf()) fonctionne correctement sous Cygwin.
> Dois-je en déduire que c'est l'implémentation des stream std
> de Microsoft qui est.. foireuse?
D'abord, il faudrait savoir exactement ce que tu as fais.
L'implémentation a le droit de réfuser un setbuf : selon
l'implémentation, elle le fera dans des cas différents :
-- systèmatiquement dans le cas de stringstreambuf,
-- s'il y a déjà eu des sorties sur le streambuf,
-- si les iostream sont encore couplés avec les FILE*,
et sans doute d'autres aussi.
--
James Kanze
> os<<"test";
ostream ne le gère pas. ostream appelle toujours ou sputc ou
sputn pour ses sorties. C'est le streambuf même qui le gère.
Pour garder la trace de ce qui a été sortie, la solution la plus
simple, c'est un streambuf filtrant qui sauve chaque caractère
dans un buffer à lui.
--
James Kanze
[...]
> > Je pensais plutôt à:
> > streambuf sbuf;
> > sbuf.pubsetbuf(buf,sizeof(buf));
> > ostream os(sbuf);
> > os<<"test";
> le problème est que streambuf n'est pas instanciable: "This is
> an abstract base class, therefore no objects can be directly
> instantiated from it. The standard hierarchy defines two
> classes derived from this one that can be used to directly
> instantiate objects: filebuf and stringbuf."
La standard en définit deux (en fait trois), mais tu peux en
définir autant que tu veux. C'est assez rare que je n'ai pas de
streambuf maison dans une application.
> A ce que je comprend, je ne peux utiliser que stringbuf ou
> filebuf mais filebuf ne me parrait pas adapté.
> A la vue de ce que tu me montre, j'ai légerement changé mon
> code. A la place de
> ostringstream testStream(ostringstream::out | ostringstream::in);
> testStream.rdbuf()->pubsetbuf(buf, SIZE);
> TestOutStream(testStream);
> j'ai écris
> stringbuf sbuf;
> sbuf.pubsetbuf(buf, SIZE);
> ostream os(&sbuf);
> Je suis obligé d'écrire stringbuf et pas streambuf car cette
> dernière n'est pas instanciable.
> Au final, le problème reste le même: ça marche sous Cygwin/G++
> et pas sous Visual Studio 2005, problème toujours dans la
> fonction basic_streambuf::setbuf.
Qui n'est pas ce que tu veux. Tu veux un comportement un peu
spécial de ton streambuf. La façon à l'obtenir, c'est d'écrire
un streambuf qui fait ce que tu veux.
--
James Kanze
>je cherche � encapsuler un buffer dans un ostream
Je peux me gourer, mais... est-ce que std::strstream ne ferait pas
exactement ce que tu veux ?
> Quelqu'un sait-il comment faire faire l'�quivalent de strstream avec
> les classes de sstream?
>
La version standard doit �tre std::stringstream ?
Au fait, pourquoi utilises-tu un vieil environnement MSVS ?
--
Micka�l Wolff aka Lupus Michaelis
http://lupusmic.org
>Cependant, elle est indiqu� comme �tant obsol�te
Oui et non.
L'id�e m�me d'utiliser un buffer sous la forme d'un char[] est
mauvaise la plupart du temps. Par cons�quent, strstream ne sert plus �
grand chose, et est remplac� par stringstream.
Il a �t� annonc� que strstream est "deprecated", et pourrait �tre
supprim� d'un prochain standard. Il y a toutefois peu de chances pour
que �a arrive dans un avenir proche.
Par ailleurs, Visual C++ a tendance � balancer des warnings "This
stuff is deprecated". Du coup, il faut syst�matiquement ajouter
/D_CRT_SECURE_NO_WARNINGS sur la ligne de commande.
> >Cependant, elle est indiqué comme étant obsolète
> Oui et non.
> L'idée même d'utiliser un buffer sous la forme d'un char[] est
> mauvaise la plupart du temps.
Sauf quand il ne l'est pas. Je m'en sers assez souvent en
sortie, pour formatter des données in situ dans un bloc destiné
à un autre protocol. Quand on travaille à un niveau assez bas,
c'est utile.
Mais évidemment, elle a beaucoup de bagage en trop pour ça. Ça
fait longtemps que j'ai écris mon propre memory_streambuf,
ultra-simplifié.
> Par conséquent, strstream ne sert plus à grand chose, et est
> remplacé par stringstream.
> Il a été annoncé que strstream est "deprecated", et pourrait
> être supprimé d'un prochain standard. Il y a toutefois peu de
> chances pour que ça arrive dans un avenir proche.
D'autant plus qu'il y a certains qui poussent à elever le
« deprecated ».
> Par ailleurs, Visual C++ a tendance à balancer des warnings
> "This stuff is deprecated". Du coup, il faut systématiquement
> ajouter /D_CRT_SECURE_NO_WARNINGS sur la ligne de commande.
Oui. Mais dans ce cas-ci, g++ a le même problème (avec quelque
chose de différent qu'il faut définir),
--
James Kanze