Dériver (?) fstream pour obtenir un stream à partir d'autre chose qu'un fichier
4 réponses
Yannick Patois
Bonjour,
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose"
"trucread" et "trucwrite" doté de la même interface et du même
comportement que leurs analogues Unix (http://linux.die.net/man/2/open,
http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un
fichier Unix standard (sinon les fonctions natives suffiraient
évidemment), mais sur un fichier distant au travers d'un protocole
réseau. Je ne crois pas que les seek et quelques autres fonctions du
genre soient implémentées, mais je n'en ai a priori pas besoin (je vais
de toute façon open et lire séquenciellement)
Une application déjà écrite en C++ utilise (bien sûr) ifstream pour
ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la
même chose en ofstream). Je voudrais une classe qui se comporte de la
même façon que je puisse poser exactement à la place de la classe
ifstream pour permettre à cette application de faire le même travail
avec un fichier géré par le protocole de ma bibliothèque C.
Je me suis dis, bon, dérivons un (f?)stream, et remplaçons les appels
"open" unix par des appels à ma bibliothèque, etc. Mais là, je suis
assez dépassé. J'ai jeté un oeil à l'implémentation de fstream dans GCC
pour me faire une idée, et franchement, ça me semble très chevelu, et
largement au dessus de ce que je comprend du C++. J'ai cependant eu
l'impression que je devais avant tout fabriquer un stream à partir de
mes fonctions, donc écrire un dérivé de ios_base, mais je reste très
dans le flou...
Par quel bout prendre le problème? Comment faire le plus proprement
possible à partir de mes 4 fonctions C une classe qui réponde aux
besoins énoncés plus haut?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Marc
Yannick Patois wrote:
Bonjour,
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose" "trucread" et "trucwrite" doté de la même interface et du même comportement que leurs analogues Unix (http://linux.die.net/man/2/open, http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un fichier Unix standard (sinon les fonctions natives suffiraient évidemment), mais sur un fichier distant au travers d'un protocole réseau. Je ne crois pas que les seek et quelques autres fonctions du genre soient implémentées, mais je n'en ai a priori pas besoin (je vais de toute façon open et lire séquenciellement)
Une application déjà écrite en C++ utilise (bien sûr) ifstream pour ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la même chose en ofstream). Je voudrais une classe qui se comporte de la même façon que je puisse poser exactement à la place de la classe ifstream pour permettre à cette application de faire le même travail avec un fichier géré par le protocole de ma bibliothèque C.
Je me suis dis, bon, dérivons un (f?)stream, et remplaçons les appels "open" unix par des appels à ma bibliothèque, etc. Mais là, je suis assez dépassé. J'ai jeté un oeil à l'implémentation de fstream dans GCC pour me faire une idée, et franchement, ça me semble très chevelu, et largement au dessus de ce que je comprend du C++. J'ai cependant eu l'impression que je devais avant tout fabriquer un stream à partir de mes fonctions, donc écrire un dérivé de ios_base, mais je reste très dans le flou...
Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream construit sur streambuf, et quand on prend le cas particulier ifstream, il est construit sur filebuf qui dérive de streambuf. Donc il semblerait raisonnable de commencer par dériver de filebuf (ou streambuf), c'est là que les fonctions trucopen vont servir, et ensuite voir comment remonter au niveau istream.
Je n'ai jamais fait ce genre de chose, mais il traîne un certain nombre d'exemples de filtering streambuf sur internet qui pourraient aider à se faire un idée de comment ça marche.
Yannick Patois wrote:
Bonjour,
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose"
"trucread" et "trucwrite" doté de la même interface et du même
comportement que leurs analogues Unix (http://linux.die.net/man/2/open,
http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un
fichier Unix standard (sinon les fonctions natives suffiraient
évidemment), mais sur un fichier distant au travers d'un protocole
réseau. Je ne crois pas que les seek et quelques autres fonctions du
genre soient implémentées, mais je n'en ai a priori pas besoin (je vais
de toute façon open et lire séquenciellement)
Une application déjà écrite en C++ utilise (bien sûr) ifstream pour
ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la
même chose en ofstream). Je voudrais une classe qui se comporte de la
même façon que je puisse poser exactement à la place de la classe
ifstream pour permettre à cette application de faire le même travail
avec un fichier géré par le protocole de ma bibliothèque C.
Je me suis dis, bon, dérivons un (f?)stream, et remplaçons les appels
"open" unix par des appels à ma bibliothèque, etc. Mais là, je suis
assez dépassé. J'ai jeté un oeil à l'implémentation de fstream dans GCC
pour me faire une idée, et franchement, ça me semble très chevelu, et
largement au dessus de ce que je comprend du C++. J'ai cependant eu
l'impression que je devais avant tout fabriquer un stream à partir de
mes fonctions, donc écrire un dérivé de ios_base, mais je reste très
dans le flou...
Par quel bout prendre le problème? Comment faire le plus proprement
possible à partir de mes 4 fonctions C une classe qui réponde aux
besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream
construit sur streambuf, et quand on prend le cas particulier
ifstream, il est construit sur filebuf qui dérive de streambuf. Donc
il semblerait raisonnable de commencer par dériver de filebuf (ou
streambuf), c'est là que les fonctions trucopen vont servir, et
ensuite voir comment remonter au niveau istream.
Je n'ai jamais fait ce genre de chose, mais il traîne un certain
nombre d'exemples de filtering streambuf sur internet qui pourraient
aider à se faire un idée de comment ça marche.
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose" "trucread" et "trucwrite" doté de la même interface et du même comportement que leurs analogues Unix (http://linux.die.net/man/2/open, http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un fichier Unix standard (sinon les fonctions natives suffiraient évidemment), mais sur un fichier distant au travers d'un protocole réseau. Je ne crois pas que les seek et quelques autres fonctions du genre soient implémentées, mais je n'en ai a priori pas besoin (je vais de toute façon open et lire séquenciellement)
Une application déjà écrite en C++ utilise (bien sûr) ifstream pour ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la même chose en ofstream). Je voudrais une classe qui se comporte de la même façon que je puisse poser exactement à la place de la classe ifstream pour permettre à cette application de faire le même travail avec un fichier géré par le protocole de ma bibliothèque C.
Je me suis dis, bon, dérivons un (f?)stream, et remplaçons les appels "open" unix par des appels à ma bibliothèque, etc. Mais là, je suis assez dépassé. J'ai jeté un oeil à l'implémentation de fstream dans GCC pour me faire une idée, et franchement, ça me semble très chevelu, et largement au dessus de ce que je comprend du C++. J'ai cependant eu l'impression que je devais avant tout fabriquer un stream à partir de mes fonctions, donc écrire un dérivé de ios_base, mais je reste très dans le flou...
Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream construit sur streambuf, et quand on prend le cas particulier ifstream, il est construit sur filebuf qui dérive de streambuf. Donc il semblerait raisonnable de commencer par dériver de filebuf (ou streambuf), c'est là que les fonctions trucopen vont servir, et ensuite voir comment remonter au niveau istream.
Je n'ai jamais fait ce genre de chose, mais il traîne un certain nombre d'exemples de filtering streambuf sur internet qui pourraient aider à se faire un idée de comment ça marche.
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le re copie ici. Boost a une bibliotheque sensee aider a l'ecriture de bufstream, je ne l'ai jamais utilisee.
#include <stdio.h> #include <assert.h>
#include <iostream> #include <streambuf>
// streambuf minimal encapsulant un FILE* // - utilise les tampons de FILE donc n'a pas de tampon interne en // sortie et a un tampon interne de taille 1 en entree car l'interface // de streambuf ne permet pas de faire moins; // - ne permet pas la mise en place d'un tampon // - une version plus complete devrait permettre d'acceder aux // informations d'erreur plus precises de FILE* et interfacer aussi // les autres possibilites de FILE* (entre autres synchroniser les // sungetc/sputbackc avec la possibilite correspondante de FILE*)
class FILEbuf: public std::streambuf { public:
explicit FILEbuf(FILE* cstream); // cstream doit etre non NULL.
FILEbuf::FILEbuf(FILE* cstream) : cstream_(cstream) { // le constructeur de streambuf equivaut a // setp(NULL, NULL); // setg(NULL, NULL, NULL); assert(cstream != NULL); }
std::streambuf* FILEbuf::setbuf(char_type* s, std::streamsize n) { // ne fait rien, ce qui est autorise. Une version plus complete // devrait vraissemblablement utiliser setvbuf return NULL; }
FILEbuf::int_type FILEbuf::overflow(int_type c) { if (traits_type::eq_int_type(c, traits_type::eof())) { // la norme ne le demande pas exactement, mais si on nous passe eof // la coutume est de faire la meme chose que sync() return (sync() == 0 ? traits_type::not_eof(c) : traits_type::eof()); } else { return ((fputc(c, cstream_) != EOF) ? traits_type::not_eof(c) : traits_type::eof()); } }
FILEbuf::int_type FILEbuf::underflow() { // Assurance contre des implementations pas strictement conformes a la // norme qui guaranti que le test est vrai. Cette guarantie n'existait // pas dans les IOStream classiques. if (gptr() == NULL || gptr() >= egptr()) { int gotted = fgetc(cstream_); if (gotted == EOF) { return traits_type::eof(); } else { *inputBuffer_ = gotted; setg(inputBuffer_, inputBuffer_, inputBuffer_+1); return traits_type::to_int_type(*inputBuffer_); } } else { return traits_type::to_int_type(*inputBuffer_); } }
// ostream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf, ce qui permet de s'assurer // qu'il est bien initialise avant std::ostream
class oFILEstream: private FILEbuf, public std::ostream { public: explicit oFILEstream(FILE* cstream); };
// istream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf, ce qui permet de s'assurer // qu'il est bien initialise avant std::istream
class iFILEstream: private FILEbuf, public std::istream { public: explicit iFILEstream(FILE* cstream); };
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le re copie
ici. Boost a une bibliotheque sensee aider a l'ecriture de bufstream,
je ne l'ai jamais utilisee.
#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <streambuf>
// streambuf minimal encapsulant un FILE*
// - utilise les tampons de FILE donc n'a pas de tampon interne en
// sortie et a un tampon interne de taille 1 en entree car l'interface
// de streambuf ne permet pas de faire moins;
// - ne permet pas la mise en place d'un tampon
// - une version plus complete devrait permettre d'acceder aux
// informations d'erreur plus precises de FILE* et interfacer aussi
// les autres possibilites de FILE* (entre autres synchroniser les
// sungetc/sputbackc avec la possibilite correspondante de FILE*)
class FILEbuf: public std::streambuf
{
public:
explicit FILEbuf(FILE* cstream);
// cstream doit etre non NULL.
FILEbuf::FILEbuf(FILE* cstream)
: cstream_(cstream)
{
// le constructeur de streambuf equivaut a
// setp(NULL, NULL);
// setg(NULL, NULL, NULL);
assert(cstream != NULL);
}
std::streambuf* FILEbuf::setbuf(char_type* s, std::streamsize n)
{
// ne fait rien, ce qui est autorise. Une version plus complete
// devrait vraissemblablement utiliser setvbuf
return NULL;
}
FILEbuf::int_type FILEbuf::overflow(int_type c)
{
if (traits_type::eq_int_type(c, traits_type::eof())) {
// la norme ne le demande pas exactement, mais si on nous passe eof
// la coutume est de faire la meme chose que sync()
return (sync() == 0
? traits_type::not_eof(c)
: traits_type::eof());
} else {
return ((fputc(c, cstream_) != EOF)
? traits_type::not_eof(c)
: traits_type::eof());
}
}
FILEbuf::int_type FILEbuf::underflow()
{
// Assurance contre des implementations pas strictement conformes a la
// norme qui guaranti que le test est vrai. Cette guarantie n'existait
// pas dans les IOStream classiques.
if (gptr() == NULL || gptr() >= egptr()) {
int gotted = fgetc(cstream_);
if (gotted == EOF) {
return traits_type::eof();
} else {
*inputBuffer_ = gotted;
setg(inputBuffer_, inputBuffer_, inputBuffer_+1);
return traits_type::to_int_type(*inputBuffer_);
}
} else {
return traits_type::to_int_type(*inputBuffer_);
}
}
// ostream minimal facilitant l'utilisation d'un FILEbuf
// herite de maniere privee de FILEbuf, ce qui permet de s'assurer
// qu'il est bien initialise avant std::ostream
class oFILEstream: private FILEbuf, public std::ostream
{
public:
explicit oFILEstream(FILE* cstream);
};
// istream minimal facilitant l'utilisation d'un FILEbuf
// herite de maniere privee de FILEbuf, ce qui permet de s'assurer
// qu'il est bien initialise avant std::istream
class iFILEstream: private FILEbuf, public std::istream
{
public:
explicit iFILEstream(FILE* cstream);
};
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index. html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le re copie ici. Boost a une bibliotheque sensee aider a l'ecriture de bufstream, je ne l'ai jamais utilisee.
#include <stdio.h> #include <assert.h>
#include <iostream> #include <streambuf>
// streambuf minimal encapsulant un FILE* // - utilise les tampons de FILE donc n'a pas de tampon interne en // sortie et a un tampon interne de taille 1 en entree car l'interface // de streambuf ne permet pas de faire moins; // - ne permet pas la mise en place d'un tampon // - une version plus complete devrait permettre d'acceder aux // informations d'erreur plus precises de FILE* et interfacer aussi // les autres possibilites de FILE* (entre autres synchroniser les // sungetc/sputbackc avec la possibilite correspondante de FILE*)
class FILEbuf: public std::streambuf { public:
explicit FILEbuf(FILE* cstream); // cstream doit etre non NULL.
FILEbuf::FILEbuf(FILE* cstream) : cstream_(cstream) { // le constructeur de streambuf equivaut a // setp(NULL, NULL); // setg(NULL, NULL, NULL); assert(cstream != NULL); }
std::streambuf* FILEbuf::setbuf(char_type* s, std::streamsize n) { // ne fait rien, ce qui est autorise. Une version plus complete // devrait vraissemblablement utiliser setvbuf return NULL; }
FILEbuf::int_type FILEbuf::overflow(int_type c) { if (traits_type::eq_int_type(c, traits_type::eof())) { // la norme ne le demande pas exactement, mais si on nous passe eof // la coutume est de faire la meme chose que sync() return (sync() == 0 ? traits_type::not_eof(c) : traits_type::eof()); } else { return ((fputc(c, cstream_) != EOF) ? traits_type::not_eof(c) : traits_type::eof()); } }
FILEbuf::int_type FILEbuf::underflow() { // Assurance contre des implementations pas strictement conformes a la // norme qui guaranti que le test est vrai. Cette guarantie n'existait // pas dans les IOStream classiques. if (gptr() == NULL || gptr() >= egptr()) { int gotted = fgetc(cstream_); if (gotted == EOF) { return traits_type::eof(); } else { *inputBuffer_ = gotted; setg(inputBuffer_, inputBuffer_, inputBuffer_+1); return traits_type::to_int_type(*inputBuffer_); } } else { return traits_type::to_int_type(*inputBuffer_); } }
// ostream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf, ce qui permet de s'assurer // qu'il est bien initialise avant std::ostream
class oFILEstream: private FILEbuf, public std::ostream { public: explicit oFILEstream(FILE* cstream); };
// istream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf, ce qui permet de s'assurer // qu'il est bien initialise avant std::istream
class iFILEstream: private FILEbuf, public std::istream { public: explicit iFILEstream(FILE* cstream); };
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose" "trucread" et "trucwrite" doté de la même interface et du même comportement que leurs analogues Unix (http://linux.die.net/man/2/open, http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un Une application déjà écrite en C++ utilise (bien sûr) ifstream pour ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la même chose en ofstream). Je voudrais une classe qui se comporte de la même façon que je puisse poser exactement à la place de la classe ifstream pour permettre à cette application de faire le même travail avec un fichier géré par le protocole de ma bibliothèque C. Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream construit sur streambuf, et quand on prend le cas particulier ifstream, il est construit sur filebuf qui dérive de streambuf. Donc il semblerait raisonnable de commencer par dériver de filebuf (ou streambuf), c'est là que les fonctions trucopen vont servir, et ensuite voir comment remonter au niveau istream.
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose"
"trucread" et "trucwrite" doté de la même interface et du même
comportement que leurs analogues Unix (http://linux.die.net/man/2/open,
http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un
Une application déjà écrite en C++ utilise (bien sûr) ifstream pour
ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la
même chose en ofstream). Je voudrais une classe qui se comporte de la
même façon que je puisse poser exactement à la place de la classe
ifstream pour permettre à cette application de faire le même travail
avec un fichier géré par le protocole de ma bibliothèque C.
Par quel bout prendre le problème? Comment faire le plus proprement
possible à partir de mes 4 fonctions C une classe qui réponde aux
besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream
construit sur streambuf, et quand on prend le cas particulier
ifstream, il est construit sur filebuf qui dérive de streambuf. Donc
il semblerait raisonnable de commencer par dériver de filebuf (ou
streambuf), c'est là que les fonctions trucopen vont servir, et
ensuite voir comment remonter au niveau istream.
Merci pour ces précieuses indications.
Yannick
--
_/ Yannick Patois ___________________________________________________
| web: http://feelingsurfer.net/garp/ | Garp sur irc undernet |
| email: patois@altespace.org | |
| http://www.jean-luc-melenchon.fr/ Le blog de campagne de Mélenchon |
Je dispose d'une bibliothèque C doté de fonctions "trucopen" "trucclose" "trucread" et "trucwrite" doté de la même interface et du même comportement que leurs analogues Unix (http://linux.die.net/man/2/open, http://linux.die.net/man/2/read, etc.). Elles n'opèrent pas sur un Une application déjà écrite en C++ utilise (bien sûr) ifstream pour ouvrir et lire des fichiers locaux (et sans doute que j'aurai à faire la même chose en ofstream). Je voudrais une classe qui se comporte de la même façon que je puisse poser exactement à la place de la classe ifstream pour permettre à cette application de faire le même travail avec un fichier géré par le protocole de ma bibliothèque C. Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
Si on regarde comment la bibliothèque est faite, on a istream construit sur streambuf, et quand on prend le cas particulier ifstream, il est construit sur filebuf qui dérive de streambuf. Donc il semblerait raisonnable de commencer par dériver de filebuf (ou streambuf), c'est là que les fonctions trucopen vont servir, et ensuite voir comment remonter au niveau istream.
Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le recopie ici.
Ton exemple m'est d'une très grande aide pour comprendre le fonctionnement d'un stream.
Boost a une bibliotheque sensee aider a l'ecriture de bufstream, je ne l'ai jamais utilisee.
Je vais aussi y jeter un oeil; mon application utilise déjà Boost.
Par quel bout prendre le problème? Comment faire le plus proprement
possible à partir de mes 4 fonctions C une classe qui réponde aux besoins
énoncés plus haut?
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le recopie
ici.
Ton exemple m'est d'une très grande aide pour comprendre le
fonctionnement d'un stream.
Boost a une bibliotheque sensee aider a l'ecriture de bufstream,
je ne l'ai jamais utilisee.
Je vais aussi y jeter un oeil; mon application utilise déjà Boost.
Merci beaucoup.
Yannick
--
_/ Yannick Patois ___________________________________________________
| web: http://feelingsurfer.net/garp/ | Garp sur irc undernet |
| email: patois@altespace.org | |
| http://www.jean-luc-melenchon.fr/ Le blog de campagne de Mélenchon |
Par quel bout prendre le problème? Comment faire le plus proprement possible à partir de mes 4 fonctions C une classe qui réponde aux besoins énoncés plus haut?
La FAQ, maintenant inaccessible, contenait un exemple minimaliste. Je le recopie ici.
Ton exemple m'est d'une très grande aide pour comprendre le fonctionnement d'un stream.
Boost a une bibliotheque sensee aider a l'ecriture de bufstream, je ne l'ai jamais utilisee.
Je vais aussi y jeter un oeil; mon application utilise déjà Boost.