Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Encapsulation d'un buffer dans un stream

3 views
Skip to first unread message

Philippe MESMEUR

unread,
Dec 30, 2009, 4:12:51 AM12/30/09
to
Bonjour à tous,

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

Michael Doubez

unread,
Dec 30, 2009, 6:53:20 AM12/30/09
to

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

Philippe MESMEUR

unread,
Dec 30, 2009, 8:22:44 AM12/30/09
to
On 30 déc, 12:53, Michael Doubez <michael.dou...@free.fr> wrote:
> 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 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

Philippe MESMEUR

unread,
Dec 30, 2009, 8:30:45 AM12/30/09
to

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

Michael Doubez

unread,
Dec 30, 2009, 9:29:58 AM12/30/09
to

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

Philippe MESMEUR

unread,
Dec 30, 2009, 10:06:50 AM12/30/09
to

> Je parlait d'utiliser un streambuf pas un stringbuf. stringbuf
> redefinitsetbuf() 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";

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

Philippe MESMEUR

unread,
Dec 30, 2009, 11:12:27 AM12/30/09
to

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

Michael Doubez

unread,
Dec 30, 2009, 11:17:33 AM12/30/09
to

AMHA il vaut mieux que tu définisses ton propre streambuf quitte a
refaire quelque chose comme strstream (qui doit être pré-standard).

--
Michael

James Kanze

unread,
Dec 30, 2009, 3:17:14 PM12/30/09
to
On 30 Dec, 13:30, Philippe MESMEUR <philippe.mesm...@gmail.com> wrote:
> On 30 déc, 14:22, Philippe MESMEUR <philippe.mesm...@gmail.com> wrote:
> > On 30 déc, 12:53, Michael Doubez <michael.dou...@free.fr> wrote:

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

James Kanze

unread,
Dec 30, 2009, 3:20:24 PM12/30/09
to

> 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

James Kanze

unread,
Dec 30, 2009, 3:24:07 PM12/30/09
to
On 30 Dec, 15:06, Philippe MESMEUR <philippe.mesm...@gmail.com> wrote:

[...]


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

Fabien LE LEZ

unread,
Dec 31, 2009, 6:15:48 AM12/31/09
to
On Wed, 30 Dec 2009 01:12:51 -0800 (PST), Philippe MESMEUR
<philippe...@gmail.com>:

>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 ?

Mickaël Wolff

unread,
Dec 31, 2009, 3:23:39 PM12/31/09
to
Philippe MESMEUR a �crit :
> On 30 d�c, 16:06, Philippe MESMEUR <philippe.mesm...@gmail.com> wrote:

> 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

Fabien LE LEZ

unread,
Dec 31, 2009, 3:26:32 PM12/31/09
to
On Wed, 30 Dec 2009 08:12:27 -0800 (PST), Philippe MESMEUR
<philippe...@gmail.com>:

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

James Kanze

unread,
Jan 1, 2010, 7:47:55 AM1/1/10
to
On Dec 31 2009, 8:26 pm, Fabien LE LEZ <grams...@gramster.com> wrote:
> On Wed, 30 Dec 2009 08:12:27 -0800 (PST), Philippe MESMEUR
> <philippe.mesm...@gmail.com>:

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

0 new messages