Salut,

tu n'aimes pas les class fonctor ? tu vas pas aimer la suite.

Dans la plus part des langages de prog (non prototypé)
comment vous faite un filestream compressé chiffré ?

exemple en java (fictif)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
var monfile=new FileStream("monfichier.truc")
var monenc=new Encrypter(monfile,"mon mot de passe")
var monzip=new zipper(monenc, 9)
monzip.write(...)
mouuuais c'est lourd !!!
selon le langage il faudra fermer les fichiers dans l'ordre

voyons comment on peut profiter du multiclass CPP pour "fabriquer" un stream comme on le veux

On definit d'abord la "destination" du stream
par exemple un fichier, un socket, un port com...

puis on defini des "modificateur" (par exemple le zipper, le chiffreux, le tar..

ca pourrais donner un truc comme ca en CPP (fictif):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
class MonStream:public FileStream, public Zip, public Enc}{} monStream;
monStream.setKey("mon mot de passe")
monStream.open("mon fichier");
monStream.write(...)
monStream.close();
AAaah c'est pas mieux la ?

le probleme est qu'en CPP les class multiple s'ignore...
affaire classé...
... wait...
bon, vous connaissez l'adage... c'est parce que on ne savait pas que ce n'etait pas possible
qu'on la fait..

Ma 1er tentative etait de passer par un static
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
class Server{ // parait qu'il ne faut plus utiliser le mot master c pas sjw...
 static vector<Client>mesclients;
}
... (30 lignes de code)...
le linker m'a insulté en klingon (a priori le linker n'aime pas trop les static dans les multiclass)

2eme tentative je passe par un global...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
class Client{}
vector<Client>clients
... (30 lignes de code)...
ca marche plutot bien mais ce n'est pas thread-safe...

hmm... comment faire pour que mes "modificateur" reçoivent le "this" du "server" lors de la construction..
j'ecris a tout hasard (j'ai enlevé les "public" pour la lisibilité)

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
class client{
 client(server *slf){}
}
class a:client{}
class b:client()
class server{}
... main...
class Myserv:server,a,b{
 Myserv():a(this),b(this){} // <- oui cette iigne est total nawak
} myserv;
g++ montruc.cpp

je m'attends a un flot d'insulte en klingon du sud.
et la, paf la marmotte fait des chocapic dans du papier alu...
ca compile trankilou...

Ah AAAah !!! je tiens ma solution!!!

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include <iostream>
#include <string>
 
using namespace std;
 
class ModStream;
 
using TModStreamIO  =int (ModStream::*)(char** buf,int sz); 
using TModStreamOCF =int (ModStream::*)();
using TModStreamSeek=int (ModStream::*)(int pos);
 
// j'arrive a faire les using de class fonctor maintenant NA !
 
struct CB{
    ModStream*     ctx;
    TModStreamIO   _read;
    TModStreamIO   _write;
    TModStreamOCF  _open;
    TModStreamOCF  _close;
    TModStreamOCF  _flush;
    TModStreamSeek _seek;
} cb;
 
class ServerStream{
    public:
        string type=""; // CTTI :p
        CB cb;
        ServerStream(){
            cb.ctx=NULL;
        }
        virtual int write(char** buf, int sz){
            return (cb.ctx->*cb._write)(buf, sz);
        }
        virtual int read(char** buf, int sz){
            return (cb.ctx->*cb._read)(buf, sz);
        }
};
 
class ModStream{
    protected:
        CB oldcb;
        virtual int _read(char** buf,int sz){
            if(!oldcb.ctx) return 0;
            if(oldcb._read) return (oldcb.ctx->*oldcb._read)(buf,sz);
            return -1;
        }
        virtual int _write(char** buf, int sz){
            if(!oldcb.ctx) return 0;
            if(oldcb._write) return (oldcb.ctx->*oldcb._write)(buf,sz);
            return -1;
        }
        virtual int _open(){
            if(!oldcb.ctx) return 0;
            if(oldcb._open)return (oldcb.ctx->*oldcb._open)();
            return -1;
        }
        virtual int _close(){
            if(!oldcb.ctx) return 0;
            if(oldcb._close) return (oldcb.ctx->*oldcb._close)();
            return -1;
        }
        virtual int _flush(){
            if(!oldcb.ctx) return 0;
            if(oldcb._flush) return (oldcb.ctx->*oldcb._flush)();
            return -1;
        }
        virtual int _seek(int pos){
            if(!oldcb.ctx) return 0;
            if(oldcb._seek) return (oldcb.ctx->*oldcb._seek)(pos);
            return pos;
        }
    public:
        ModStream(ServerStream *slf){
            oldcb=slf->cb;
            slf->cb.ctx=this;
            slf->cb._open =(TModStreamOCF)&ModStream::_open;
            slf->cb._close=(TModStreamOCF)&ModStream::_close;
            slf->cb._flush=(TModStreamOCF)&ModStream::_open;
            slf->cb._write=(TModStreamIO) &ModStream::_write;
            slf->cb._read =(TModStreamIO) &ModStream::_read;
        }
};
 
class FileStream:public ServerStream{
    protected:
        string filename;
        bool opened=false;       
    public:
        FileStream(){
            cout << "File::"<<endl;
            type="FileStream";
        }
        int open(string fn){
            filename=fn;
            cout << "File::open name="<<filename<<endl;
            opened=true;
            return (cb.ctx->*cb._open)();
        }
        int flush(string fn){
            cout << "File::flush name="<<filename<<endl;
            return (cb.ctx->*cb._open)();
        }
        int close(){
            int err=(cb.ctx->*cb._close)();
            cout << "File::close name="<<filename<<endl;
            return err;
        }
        virtual int read(char** buf, int sz){
            cout <<"File::read in "<<filename<<endl;
            return ServerStream::read(buf,sz);
        }
        virtual int write(char** buf, int sz){
            cout <<"File::write in "<<filename<<endl;
            int err= ServerStream::write(buf,sz);
            return err;
        }
};
 
class Enc:public ModStream{
    private:
        string key;
        bool opened=false;
    protected:
        virtual int _read(char** buf,int sz){
            cout << "Enc::read"<<endl;
            return ModStream::_read(buf,sz);
        }
        virtual int _write(char** buf, int sz){
            cout << "Enc::write key="<<key <<endl;
            return ModStream::_read(buf,sz);
        }
        virtual int _open(){
            if(key.empty()) return -1;
            opened=true;
            cout << "Enc::open key="<<key << endl;
            return ModStream::_open();
        }
        virtual int _close(){
            cout << "Enc::close"<<endl;
            return ModStream::_close();
        }
        virtual int _flush(){
            cout << "Enc::flush"<<endl;
            return ModStream::_flush();
        }
        virtual int _seek(int pos){
            cout << "Enc::seek"<<endl;
            return ModStream::_seek(pos);;
        }
    public:
        Enc(ServerStream* slf):ModStream(slf){
            slf->type+="+Enc";
            cout << "Enc::"<<endl;
        }
        int setKey(string k){
            if (opened) return -1;
            key=k;
            return 0;
        }
};
 
class Zip:public ModStream{
    public:
        int ratio=9;
        bool opened=false;
    protected:
        virtual int _read(char** buf,int sz){
            cout << "Zip::read ratio="<<ratio<<endl;
            return ModStream::_read(buf,sz);
        }
        virtual int _write(char** buf, int sz){
            cout << "Zip::write"<<endl;
            return ModStream::_read(buf,sz);
        }
        virtual int _open(){
            cout << "Zip::open ratio="<<ratio<<endl;
            return ModStream::_open();
        }
        virtual int _close(){
            cout << "Zip::close"<<endl;
            return ModStream::_close();
        }
        virtual int _flush(){
            cout << "Zip::flush"<<endl;
            return ModStream::_flush();
        }
        virtual int _seek(int pos){
            cout << "Zip::seek"<<endl;
            return ModStream::_seek(pos);
        }
    public:
        Zip(ServerStream* slf):ModStream(slf){
            slf->type+="+Zip";
            cout << "Zip::"<<endl;
        }
        int setRatio(int r){
            if(opened) return -1;
            ratio=r;
            return 0;
        }
};
 
// ce que le ender user ecrira //
class MyStream:public FileStream,public Zip,public Enc{
    public:
        MyStream():Zip(this),Enc(this){};
};
 
int main(int argc, char** argv){
 MyStream myStream;
 cout << myStream.type << endl;
 myStream.setKey("1234");
 myStream.setRatio(5);
 cout << myStream.open("totor.txt") << endl;
}
en sorti d'ecran
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
(construction de l'objet myStream)
File:: 
Zip::
Enc::
(contenu de myStream.type)
FileStream+Zip+Enc
(mySteam.open)
File::open name=totor.txt <- myStream.open
Enc::open key=1234 <- Enc recois l'open 
Zip::open ratio=5 <-Zip recois l'open
(cout << open)
0 <-code d'erreur de l'open
reste à remplacer les cout par du vrai code...

on pourra rajouter d'autre server, d'autre modificator
des buffered, de l'IO bit a bit, un tar/fakestream etc etc...

ou pas...

5u