2010-01-17 18 views
5

Je suis en train d'écrire une sorte de bibliothèque de systèmes de fichiers virtuels pour les jeux vidéo dans le genre de ROFS de CRI Middleware (voir Wikipedia). Mon intention avec la bibliothèque est de fournir des moyens naturels d'accéder aux ressources des jeux que je développe, qui stockent certaines données intégrées dans l'exécutable, certaines sur les médias et d'autres sur le disque dur de l'utilisateur local (préférences, sauvegarde des fichiers de jeu, etc.) .Pourquoi std :: istream n'at-il pas la propriété de son streambuf?

L'accès à ces ressources doit être aussi simple que de faire un appel comme

std::auto_ptr<std::istream> defaultConfigIStream(
    fslib.inputStream("self://defaultConfig.ini")); 
std::auto_ptr<std::ostream> defaultConfigOStream(
    fslib.outputStream("localappdata://config.ini")); 

// Copies default configuration to local user's appdata folder 
defaultConfigIStream >> defaultConfigOStream; 

La façon réelle de faire les choses est en fait différente, avec une autre couche d'abstraction utilisée pour le chargement d'arrière-plan, mais ce n'est pas important.

Ce que je veux savoir comment puis-je retourner que auto_ptr<> (ou unique_ptr<>, vous choisissez) considérant que le std::streambuf<> associé au std::[i/o]stream<> n'est pas supprimé par quand il est détruit. Je considère std::[i/o]stream<> ne pas assumer la propriété sur le streambuf passé à la construction car le constructeur ne présente pas la sémantique de transfert de propriété et la référence STDCXX d'Apache ne mentionne pas le transfert de propriété (pas plus que le stdlib références que j'ai trouvées sur internet).

Quelles alternatives ai-je? Je pourrais aussi bien retourner un pointeur partagé et continuer à le regarder jusqu'à ce que le gestionnaire FSlib garde une copie unique du pointeur partagé, auquel cas il détruirait sa copie unique ainsi que le streambuf. C'est pratique, compte tenu du modèle organisationnel de la bibliothèque, mais ce n'est pas très élégant ni efficace d'ailleurs. J'ai essayé de jeter un oeil à Boost.Iostreams, mais il semble que les choses soient encore pires pour moi, car les flux eux-mêmes ont leurs types de périphériques fortement attachés à leur type (le périphérique pour un flux doit être défini dans son paramètre de template). Ce problème semble rendre l'utilisation de Boost.Iostreams irréalisable pour ma bibliothèque, car elle doit abstraire l'implémentation concrète "source/sink" des flux afin que les flux puissent être utilisés de façon transparente pour ouvrir un fichier situé dans l'exécutable lui-même, dans un fichier du système de fichiers du système ou dans un fichier de type archive, par exemple.

Je pourrais écrire une classe de conteneur qui gère ces problèmes, mais je préfère le faire plus proprement (c'est-à-dire juste retourner le flux déjà, c'est tout ce dont il devrait avoir besoin;).

Suggestions?

Répondre

7

Vous pouvez simplement dériver vos propres classes de flux à partir de istream resp. ostream, définissez le tampon dans le constructeur et détruisez-le dans le destructeur.

Quelque chose comme:

class config_istream : public std::istream { 
public: 
    config_istream(std::string name) : 
     std::istream(fslib.InputStream(name.c_str())) 
    { 
    } 

    ~config_istream() { delete rdbuf(); } 
}; 

Jetez un oeil sur la façon dont les fstream classes sont mises en œuvre, ils faire face à un problème similaire (filebuf doit être supprimé en même temps que fstream)

+0

Oui, comme je le disais par la fin de la question, je pense que je vais devoir faire cela. Je voulais juste savoir s'il y avait un moyen plus facile de le faire XD Merci –