-
Notifications
You must be signed in to change notification settings - Fork 16
/
libzpaq.c++.txt
165 lines (147 loc) · 9.85 KB
/
libzpaq.c++.txt
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
LIBZPAQ
HEADERS ==> #libzpaq.h, l'endroit varie, car il faut souvent le
#télécharger soi-même.
LIBRARIES ==> #Pas de libraries, mais il faut compiler avec un fichier
#source libzpaq.cpp et libzpaqo.cpp, et lier
#-lboost_filesystem
#Il faut aussi définir :
# - libzpaq::error(const char*)
#Et créer des classes dérivées de READER et de WRITER,
#dont les membres get() et put() sont définis.
NAMESPACE ==> #libzpaq::
COMPRESSION ==> #Offre une compression lossless, forte, mais demandant
#de la RAM et du temps, et fonctionnant surtout sur
#les streams de grande taille.
#Peut diviser par 7 la taille d'un fichier texte, de 2
#un fichier exécutable, mais quasiment rien d'une image
#déjà compressée (.jpeg ou .png par exemple).
#Un bloc compressé .zpaq est composé, dans l'ordre (O
#signifie optionnel, et N nécessaire) :
# N) d'un header, indiquant les Tags utilisés, la
# compression utilisée, etc.
# O) de data (commentaires/garbage/data)
# O) d'un Tag indiquant la fin de ces data (13 octets,
# ainsi, un tag aléatoire peut suffir), et
# n'apparaissant dans ces data
# N) d'une suite de segments.
#Chaque segment (souvent = 1 fichier) est composé :
# O) d'une string (souvent le filename)
# O) d'une seconde string de commentaires (souvent la
# taille)
# N) des données compressées.
# O) de la somme SHA1 de ces données (pour vérification
# d'erreur de transfert). Cette checksum peut être
# checkée lors de la décompression.
#La commande Unix zpaq peut être utilisée avec les
#fichiers à compresser/décompresser de cette librarie.
#Cependant, voir les limitations de compress() et
#decompress() par rapport à Decompresser et Compressor.
Reader #Classe à faire hériter par une classe propre, et qui
#désigne un stream/fichier à [dé]compresser.
READER.get() #Classe à définir, devant lire les données à
#[dé]compresser et renvoyer un INT_VAL désignant
#l'octet lu, ou -1 si EOF.
Writer #Classe à faire hériter par une classe propre, et qui
#désigne un stream/fichier écrivant les données
#décompressées.
WRITER.put(INT_VAL) #Classe à définir, devant écrire les données
#[dé]compressées, à savoir l'octet INT_VAL, et ne rien
#renvoyer.
#En résumé cela fait :
# - get() -> [dé]compression -> put()
compress(READER_ADR, #Compresse les données lues dans READER, et les écrit
WRITER_ADR, INT_VAL) #dans WRITER. INT_VAL désigne le niveau de compression :
#1 à 3, 3 pour le maximum.
#Est plus simple que l'utilisation de Compressor, mais :
# - tout est écrit dans un seul block, un seul segment.
# - il n'y a ni filename, ni comment, ni checksum, ni
# data précédant le block possible. Ainsi, il est
# impossible pour READER de contenir plusieurs
# fichiers, car sans filenames, ils ne pourront pas
# être décompressés en plusieurs fichiers. Sans
# filename, pas de décompression via la commande Unix
# zpaq non plus.
decompress(READER_ADR, #Décompresse les données lues dans READER_ADR, et les
WRITER_ADR) #écrit dans WRITER_ADR.
#Est plus simple que Decompresser, mais :
# - tout est extrait et concaténé vers un seul fichier.
# - les data avant les blocks, filenames, comments,
# checksums sont ignorés.
Compressor #Classe servant à compresser des READER vers des WRITER.
COMPRESSOR()
COMPRESSOR.setInput #
(READER_ADR) #Désigne/modifie le READER.
COMPRESSOR.setOutput #
(WRITER_ADR) #Désigne/modifie le WRITER.
COMPRESSOR.writeTag() #Ecrit un Tag aléatoire. A faire si l'on a écrit des
#data destinées à être avant un block (à faire donc
#avant startBlock())
COMPRESSOR.startBlock #
(INT_VAL) #Commence un bloc de compression INT_VAL (1 à 3)
COMPRESSOR.startSegment #Commence un segment dont le filename et comment sont
([STR1[, STR2]]) #STR1 et STR2 (par défaut null). Doit être dans un bloc.
COMPRESSOR.postProcess()#Commande à faire avant le compress() du premier segment
#d'un bloc (et seulement du premier).
COMPRESSOR.compress #Lit INT_VAL octets (si -1 (défaut), lit jusqu'à lire
([INT_VAL]) #EOF (-1)) de READER, le compresse, et l'écrit dans
#WRITER. Renvoie true s'il y a encore des octets à lire
#dans READER, false sinon.
#De même que pour DECOMPRESSER.decompress(), INT_VAL
#est utile pour afficher la progression, et pour le
#streaming.
#Doit être dans un segment.
COMPRESSOR.endSegment #Termine un segment. Si STR n'est pas null, il s'agit
([STR]) #de la checksum SHA1 du segment, obtenu via
#SHA1.result(), et qui est écrite sur le segment. Il
#vaut mieux avoir calculer SHA1 de READER avant d'avoir
#fait compress();
COMPRESSOR.endBlock() #Termine le bloc.
Decompresser #Classe servant à décompresser des READER vers des
#WRITER.
DECOMPRESSER()
DECOMPRESSER.setInput #
([READER_ADR]) #Désigne/modifie le READER.
DECOMPRESSER.setOutput #
(WRITER_ADR) #Désigne/modifie le WRITER.
DECOMPRESSER.findBlock #Se place sur le début du prochain bloc, en skippant les
([DOUBLE_ADR]) #data optionnelles d'avant le segment, et renvoie false
#s'il s'agissait du dernier bloc. A faire avant
#d'analyser chaque bloc, et après avoir analyser ces
#data.
#Si DOUBLE_ADR est indiqué, la mémoire requise pour
#procéder à la décompression de ce bloc est indiquée
#dans DOUBLE_VAR.
DECOMPRESSER. #Se place sur le début du prochain segment dans le bloc
findFilename #courant, et renvoie false s'il n'y en a plus. Si
([WRITER_ADR]) #WRITER_ADR est précisé et que le segment a un filename,
#écrit celui-ci sur WRITER (sans le terminer par un
#'\0')
DECOMPRESSER. #Lit/skippe le comment du segment courant. Si
readComment #WRITER_ADR est précisé, l'enregistre sur WRITER, sans
([WRITER_ADR]) #le terminer par un '\0'
DECOMPRESSER.setSHA1 #Spécifie un SHA1 qui procédera automatiquement via son
(SHA1_ADR) #put() au calcul de la checksum lorsque decompress()
#sera appelé, et qui pourra donc renvoyé celle-ci
#ensuite via result()
DECOMPRESSER.decompress #Lit INT_VAL octets (si -1 (défaut), lit jusqu'à lire
([INT_VAL]) #EOF (-1)) de READER, le décompresse, et l'écrit dans
#WRITER. Renvoie true s'il y a encore des octets à lire
#dans READER, false sinon.
#Doit être dans un segment, et doit être après un
#readComment().
DECOMPRESSER. #Termine un segment, que decompress() ait été appelé ou
readSegmentEnd([STR]) #non.
#STR est un buffer de 21 octets. Si précisé : si le
#segment a une checksum écrite, les 20 derniers octets
#la reçoivent, et STR[0] == 1 ; sinon STR[0] == 0. STR
#peut ensuite, selon, être comparé avec la checksum
#calculée via setSHA1().
SHA1 #Classe calculant des checksums.
SHA1()
SHA1.put(INT_VAL) #Rajoute un octet dans la machine.
SHA1.result() #Renvoie la checksum SHA1 de tous les octets dans la
#machine, et remet tout à zéro.
SHA1.size() #Renvoie le nombre d'octets dans la machine.
error(STR) #Error handler, à redéfinir (type void).