2010-10-07 2 views
2

J'aimerais fournir un code std::ostream qui peut ou non, du point de vue de l'utilisateur, chiffrer son contenu.Manipulation transparente des chaînes insérées dans un ostream

Imaginez une fonction aléatoire qui utilise un std::ostream&:

void write_stuff(std::ostream& stream) { 
    os << "stuff"; 
} 

Que stuff est sortie en texte clair ou est chiffré dépend de la façon dont l'argument stream a été initialisé.

Je songe à hériter de std::basic_streambuf, mais je ne suis pas sûr que ce soit la meilleure solution. Je pense que le scénario idéal est une sorte d'objet filtre qui est exécuté avant que le contenu ne soit réellement sorti. De cette façon, il serait facile de chaîner des opérations, par ex. cryptage, puis codage hexadécimal, ce qui est un avantage que mon propre basic_streambuf ne semble pas donner (pas facilement au moins).

Des conseils?

Merci.

MISE À JOUR: J'ai suivi la stratégie définie par la réponse acceptée. J'ai trouvé cet article sur l'écriture d'un custom streambuf which performs XOR obfuscation pour être extrêmement utile comme point de départ.

+0

pouvez-vous partager votre solution? Merci.En passant, est-ce que votre enregistreur est basé sur Petru Marginean's publié dans Dr. Dobbs environ un mois avant votre publication? http://www.drdobbs.com/cpp/logging-in-c/201804215 – user1823664

Répondre

4

Un streambuf peut être implémenté en termes d'un autre streambuf arbitraire qui est passé en tant qu'argument au constructeur ou défini avec une fonction membre spéciale. Et cela vous permet d'empiler streambuf implémentations comme vous le pensiez.

Vous pouvez même faire un manipulateur qui utilise la ostream « fonction de rdbuf pour obtenir le streambuf courant, une fonction sur votre streambuf qui définit le« empilés streambuf de streambuf, puis appelle rdbuf à nouveau pour remplacer le ostream » avec le tien.

aes_ctr_streambuf encrypter(key); 
zlib_streambuf compressor; 
::std::cout << stack_streambuf(encrypter) << stack_streambuf(compressor); 
+0

C'est ce que j'ai fini par faire. Je souhaite qu'il y avait un moyen plus facile d'écrire des filtres iostreams, cependant. Merci. –

+0

@Pedro - De rien. :-) – Omnifarious

0

Je ne suis pas sûr que ce que je suis sur le point de suggérer est exactement ce dont vous avez besoin (et son trop compliqué pour être un commentaire), mais vous avez déjà entendu parler du flux Manipulateurs?

#include <iostream> 
#include <iomanip> 

int main(int, char**) 
{ 
    int a = 10; 
    std::cout << "a: " << a << std::endl; //outputs: "a: 10" 
    std::cout << "a: " << std::hex << a << std::endl; //outputs: "a: a" 
    std::cout << "a: " << std::dec << a << std::endl; //outputs: "a: 10" 

    return EXIT_SUCCESS; 
} 

Vous peut en effet utiliser un modèle similaire (cela correspond à ce que vous appelez en fait un objet « filtre ») de changer en quelque sorte l'état de votre objet de flux personnalisé.

2

Il est difficile de décrire en bref ce que vous devez faire pour créer un I/O stream pour la nouvelle source ou un évier. Heureusement, Jonathan Turkanis et CodeRage, LLC ont créé de très jolis blocs de construction avec une documentation exceptionnelle qui peut vous aider à économiser des centaines d'heures de recherche et de développement de nouveaux flux. La bibliothèque est appelée Boost.Iostreams. La documentation second example dans la documentation montre exactement comment résoudre votre problème. Notez également qu'ils ont déjà un flux de sortie avec compression zip. Alors peut-être n'avez-vous même pas besoin d'écrire une seule ligne de code.

Bonne chance!

+0

Ouais, Boost.Iostreams est venu à l'esprit. J'essaie de le faire pour un module de journalisation, donc je préfère garder les dépendances externes à un minimum afin de faciliter l'ajout de journaux à un projet existant (il s'agit actuellement d'un seul fichier d'en-tête). Si l'écriture de mon propre «streambuf» s'avère être un peu trop compliqué, je vais sûrement regarder dans Boost.Iostreams. Merci. –

+0

@Pedro d'Aquino: Au cas où, vous pourriez vouloir regarder l'utilitaire 'bcp'. Il extrait des parties du Boost pour que vous puissiez les utiliser dans votre projet et ne pas vous soucier de l'ensemble du projet Boost. Voir http://www.boost.org/doc/libs/1_41_0/tools/bcp/bcp.html –