]> git.llucax.com Git - z.facultad/75.06/jacu.git/blob - src/jacu.c
Listo Huffman Canonico, con dos nuevos parametros s y m se permite grabar una tabla...
[z.facultad/75.06/jacu.git] / src / jacu.c
1
2 #include "blocksorting/bs.h"
3 #include "mtf/mtf.h"
4 #include "zerogrouping/zerogrouping.h"
5 #include "statichuff/statichuff.h"
6 #include "vfile/vfile.h"
7 #include "vfile/common.h"
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <unistd.h>
11
12 long get_file_size(const char* filename);
13
14 int main(int argc, char* argv[])
15 {       
16         int cflag = 0;
17         int dflag = 0;
18         int zflag = 0;
19         int tflag = 0;
20         int qflag = 0;
21         long int volumesize = 0;
22         size_t pagesize = 32768; /* 32KB */
23         int ch;
24         t_BlockSort *bs;
25         HUFF_STATE *shuff;
26                         
27         while ((ch = getopt(argc, argv, "cdzt:q:")) != -1) { 
28                  
29                 switch (ch) { 
30                         case 'c': cflag = 1; 
31                                           break;
32
33                         case 'd': dflag = 1; 
34                                           break; 
35
36                         case 'z': zflag = 1; 
37                                           break; 
38
39                         case 't': tflag = 1; 
40                                 volumesize = atol(optarg);
41                                 break; 
42
43                         case 'q': qflag = 1; 
44                                 switch (atoi(optarg))
45                                 {
46                                         case 0: pagesize = 1024; /* 1K */
47                                                 break;
48                                         case 1: pagesize = 2048; /* 2K */
49                                                 break;
50                                         case 2: pagesize = 4096; /* 4K */
51                                                 break;
52                                         case 3: pagesize = 8192; /* 8K */
53                                                 break;
54                                         case 4: pagesize = 16384; /* 16K */
55                                                 break;
56                                         case 5: pagesize = 32768; /* 32K */
57                                                 break;
58                                         case 6: pagesize = 65536; /* 64K */
59                                                 break;
60                                         case 7: pagesize = 131072; /* 128K */
61                                                 break;
62                                         case 8: pagesize = 262144; /* 256K */
63                                                 break;
64                                         case 9: pagesize = 524288; /* 512K */
65                                                 break;
66                                         default: pagesize = 0; /* error */
67                                 }
68                                 break; 
69
70                         default: fprintf(stderr, "Usage: %s [-cdpt] sourcefile targetfile\n", argv[0]); 
71                                          return(2);
72                 }
73         }
74                 
75         if ( (argc == 1) || (cflag & dflag) || !(cflag | dflag) || ((argc - optind) < 2) ) {
76                 fprintf(stderr, "Usage: %s [-cdt] sourcefile targetfile\n", argv[0]); 
77                 return (3);
78         }
79         if ((tflag) && (volumesize <= 0l)) {
80                 fprintf(stderr,"Error: The volume size must be a non-zero value\n");
81                 return (4);
82         }
83         if ((qflag) && (pagesize <= 1u)) {
84                 fprintf(stderr,"Error: El nivel de compresión debe ser entre 0 (menor) y 9 (mayor).\n");
85                 return (5);
86         }
87                 
88         if (cflag == 1) {
89                 /* Comprimo */
90                 /* No me gusta el tmpfile ... es para probar como anda todo junto */
91                 FILE *fp, *fp_out;
92                 Uint32 i, j, total, k;
93                 char *mtf;
94                 char *salida, *data, c;
95                 char *z;
96                 int z_len;
97
98                 data = malloc(sizeof(char)*pagesize);
99                 /* Reservo lugar tambien para guardar el k y el tamaño  */
100                 salida = malloc(sizeof(char)*pagesize+sizeof(Uint32)*2);
101                 bs = bs_create(pagesize);
102
103                 fp = fopen(argv[optind], "rb");
104                 fp_out = fopen("tmp.comp", "wb");
105
106                 /*c = fgetc(fp);*/
107                 total = 0;
108                 while (!feof(fp)) {
109                         i = 0;
110                         while ((!feof(fp)) && (i < pagesize)) {
111                                 data[i++] = fgetc(fp);
112                                 total++;
113                         }
114
115                         /* Saco un EOF que lee de mas */
116                         if (i<pagesize) i--;
117
118                         /* Hago el BS */
119                         bs_solve(data, salida, bs, &k, i);
120
121                         /*printf("BS k=%ld\n", *(Uint32 *)(salida+sizeof(Uint32)));
122                         printf("PageSize = %ld\n", *(Uint32 *)salida);
123
124                         printf("Antes de MTF = %ld [", i);
125                         {
126                                 int ii;
127                                 for(ii=0; ii<(i+sizeof(Uint32)); ii++)
128                                         printf("(%c)", salida[ii+sizeof(Uint32)]);
129                                 printf("]\n");
130                         }*/
131                         /* Le aplico el MTF, salteo el tamaño del bloque para que no se pierda. */
132                         mtf = jacu_mtf(salida+sizeof(Uint32), i+sizeof(Uint32), &z, &z_len);
133 /*
134                         printf("MTF Z (len=%d) = [", z_len);
135                         {
136                                 int ii;
137                                 for(ii=0; ii<z_len; ii++)
138                                         printf("(%c)", z[ii]);
139                                 printf("]\n");
140
141                         }*/
142                         /* Si me lo piden, aplico ZG. */
143                         if (zflag) {
144                                 size_t len;
145                                 char buff[2];
146                                 ZG zg;
147                                 zg_init(&zg);
148                                 /* TODO HACER LO MISMO QUE EN EL ELSE XXX */
149                                 for (j = 0; j < i; ++j)
150                                         if ((len = zg_group(&zg, buff, mtf[j]))) fwrite(buff, 1, len, fp_out);
151                         } else {
152                                 /* Guardo el PageSize */
153                                 fwrite(salida, sizeof(Uint32), 1, fp_out);
154
155                                 /* Guardo el Z len y el Z */
156                                 fwrite(&z_len, sizeof(int), 1, fp_out);
157                                 fwrite(z, z_len, sizeof(char), fp_out);
158
159                                 /* Guardo la salida del MTF */
160                                 /*printf("Despues de MTF : [");*/
161                                 for(j=0; j<(i+sizeof(Uint32)); j++) {
162                                         fputc(mtf[j], fp_out);
163                         /*              putchar('(');
164                                         fputc(mtf[j], stdout);
165                                         putchar(')');*/
166                                 }
167                                 /*printf("]\n");*/
168                         }
169                         free(mtf);
170                         free(z);
171                 }
172
173                 /* Limpiando */
174                 fclose(fp);
175                 fclose(fp_out);
176                 bs_destroy(bs);
177
178                 /* Comprimo con huffman */
179                 if ((shuff = shuff_init_encoder_byfile("tmp.comp", argv[optind+1], volumesize)) == NULL) return 1;
180                 shuff_encode_file(shuff);
181                 shuff_deinit_encoder(shuff);
182                 free(shuff);
183
184                 /* borro el temporal */
185                 remove("tmp.comp");
186
187                 /* Muestro bpb */
188                 printf("Comprimido a %.04f bpb.\n", get_file_size(argv[optind+1])*8.0/get_file_size(argv[optind]));
189                 return 0;
190         }
191         
192         if (dflag == 1) { 
193                 /* Descomprimo */
194                 FILE *fp_out;
195                 FILE *fp_in;
196                 Uint32 block_size, k;
197                 char *block, *mtf, *orig;
198                 char *z;
199                 int z_len;
200
201                 if ((shuff = shuff_init_decoder(argv[optind],"tmp.comp")) == NULL) return 1;
202                 shuff_decode_file(shuff);
203                 shuff_deinit_decoder(shuff);
204                 free(shuff);
205                 
206                 fp_in = fopen("tmp.comp", "rb");
207                 fp_out = fopen(argv[optind+1], "wb");
208
209                 while (!feof(fp_in)) {
210                         block_size = 0;
211                         fread(&block_size, sizeof(Uint32), 1, fp_in);
212                         if (block_size > 0) {
213                                 fread(&z_len, sizeof(int), 1, fp_in);
214                                 z = malloc(sizeof(char)*z_len);
215                                 fread(z, z_len, sizeof(char), fp_in);
216
217                                 /*printf("MTF Z (len=%d) = [", z_len);
218                                 {
219                                         int ii;
220                                         for(ii=0; ii<z_len; ii++)
221                                                 printf("(%c)", z[ii]);
222                                         printf("]\n");
223         
224                                 }*/
225                                 
226                                 block = malloc(block_size*sizeof(char)+sizeof(Uint32));
227                                 orig = malloc(block_size*sizeof(char));
228                                 fread(block, block_size+sizeof(Uint32), sizeof(char), fp_in);
229
230                                 /*printf("Antes MTF_inv = [");
231                                 {
232                                         int ii;
233                                         for(ii=0; ii<block_size+sizeof(Uint32); ii++)
234                                                 printf("(%c)", block[ii]);
235                                         printf("]\n");
236                                 }*/
237                                 /* Hago el MTF inverso */
238                                 mtf = jacu_mtf_inv(z, block, block_size*sizeof(char)+sizeof(Uint32));
239
240                                 /*printf("Luego de MTF Inv= [");
241                                 {
242                                         int ii;
243                                         for(ii=0; ii<block_size+sizeof(Uint32); ii++)
244                                                 printf("(%c)", mtf[ii]);
245                                         printf("]\n");
246                                 }*/
247
248                                 /* Luego de hacer el MTF inverso ya puedo recuperar el k */
249                                 memcpy(&k, mtf, sizeof(Uint32));
250
251                                 /*printf("Restored : k=%ld\n", k);*/
252                                 bs_restore(orig, mtf+sizeof(Uint32), k, block_size);
253
254                                 fwrite(orig, block_size, sizeof(char), fp_out);
255                                 free(block);
256                                 free(orig);
257                                 free(mtf);
258                                 free(z);
259                         }
260                 }
261                 fclose(fp_in);
262                 fclose(fp_out);
263         }
264
265         return 0;
266 }
267
268 long get_file_size(const char* filename)
269 {
270         FILE* file;
271         long  file_size;
272
273         if (!(file = fopen(filename, "ab"))) return -1;
274         file_size = ftell(file);
275         fclose(file);
276         return file_size;
277 }