6 /* Block Sorting Optimizado en memoria! */
8 typedef struct _dict_ {
14 #define PALABRA(a) {a, sizeof(a)-1, 0}
16 #define DICT_SIZE sizeof(dic)/sizeof(t_Diccionario)
18 /* ASCII Numero 3 como caracter de escape */
19 #define ESCAPE_CHARACTER 0x3
22 t_Diccionario dic[] = {
23 /* Preposiciones (no todas) */
29 /* PALABRA(" de"), XXX No se si conviene, solo ahorra 1 byte y puede romper localidad */
76 PALABRA(" existencia"),
91 PALABRA(" brillante"),
97 typedef struct _bs_decode_t_ {
102 char es_menor(char *data, t_BlockSort *bs, int i, int j);
104 int _compare(const void *d1, const void *d2) {
105 t_BlockSortDecode *s1, *s2;
107 s1 = (t_BlockSortDecode *)d1;
108 s2 = (t_BlockSortDecode *)d2;
110 /* Hack si es el mismo caracter, dejo como mejor la de menor sig */
111 if (s1->c == s2->c) {
112 return (s1->sig - s2->sig);
115 return (s1->c - s2->c);
118 int __compare(const void *d1, const void *d2) {
119 t_BlockSortData *s1, *s2;
121 s1 = (t_BlockSortData *)d1;
122 s2 = (t_BlockSortData *)d2;
124 return es_menor(s1->bs->data, s1->bs, s1->pos_inicial, s2->pos_inicial);
127 char es_menor(char *data, t_BlockSort *bs, int i, int j)
131 for(k=0; k<bs->len; k++) {
135 if (data[pi] > data[pj]) return 1; /* El primero es mayor */
136 if (data[pi] < data[pj]) return -1; /* El primero es menor */
143 void generar_array(char *data, t_BlockSort *bs)
146 for(i=0; i<bs->len; i++) {
147 bs->array[i].pos_inicial = i;
148 bs->array[i].pos_final = (i+bs->len-1)%bs->len;
149 bs->array[i].ord = (i==0)?1:0;
150 bs->array[i].bs = bs;
154 void ordenar_array(char *data, t_BlockSort *bs)
156 qsort(bs->array, bs->len, sizeof(t_BlockSortData), __compare);
159 int generar_salida(char *data, t_BlockSort *bs, char *salida)
164 /* Dejo lugar para guardar el K */
165 out = salida + sizeof(Uint32);
168 for(i=0; i<bs->len; i++) {
169 out[i] = data[bs->array[i].pos_final];
170 if (bs->array[i].ord == 1) k = i;
175 void bs_solve(char *in, char *out, t_BlockSort *bs, Uint32 *k, Uint32 leido)
179 /* Hack para pedasos menores a la pagina */
180 if (leido < bs->len) bs->len = leido;
183 generar_array(in, bs);
184 ordenar_array(in, bs);
185 (*k) = generar_salida(in, bs, out);
187 /* Guardo el k y el tamaño en el array */
188 memcpy(out, k, sizeof(Uint32));
192 void bs_restore(char *dst, char *c, Uint32 k, Uint32 len)
195 t_BlockSortDecode *in;
197 in = malloc(sizeof(t_BlockSortDecode)*len);
199 for(i=0; i<len; i++) {
204 qsort(in, len, sizeof(t_BlockSortDecode), _compare);
209 dst[i++] = in[current].c;
210 current = in[current].sig;
211 } while (current != k);
215 t_BlockSort *bs_create(Uint32 len)
219 tmp = malloc(sizeof(t_BlockSort));
220 tmp->array = malloc(sizeof(t_BlockSortData)*len);
227 void bs_destroy(t_BlockSort *bs)
234 void bs_EOL(char *data, Uint32 pagesize, Uint32 *j)
236 /* Trato de agregar 4 espacios antes y 4 despues de un \n */
239 /* Verifico poder hacerlo */
240 if ((i+9) >= pagesize) return; /* No pude! */
255 char check_hint(char c)
257 static int current_pos = 0;
262 for(i=0; i<DICT_SIZE; i++) {
263 /* Veo de no pasarme */
264 if (current_pos < dic[i].len) {
265 /* Si la palabra tiene suficientes hints */
266 if (dic[i].hits == current_pos) {
267 if (dic[i].word[current_pos] == c) {
270 if (dic[i].hits == dic[i].len) {
274 /* Esta palabra ya no tiene posibilidades */
287 return -1; /* No hay hints ! */
289 if (hits > 1) return -2; /* Tengo mas de 1 hint! */
291 if (hit_pos == -1) return -2; /* Tengo 1 solo hit pero no es completo */
293 /* Tengo 1 solo hint !!!! */
301 for(i=0; i<DICT_SIZE; i++) {
306 int bs_readblock(FILE *fp, char *data, Uint32 pagesize, int usar_dic)
313 while ((!feof(fp)) && ((i+buffer_pos) < pagesize)) {
321 if (c == ESCAPE_CHARACTER) {
328 hint = check_hint(c);
332 /* No hay hints, vacio el buffer y luego saco el c */
333 for(j=0; j<buffer_pos; j++)
334 data[i++] = buffer[j];
341 /* Tengo mas de 1 hit, tengo posibilidades, guardo este char en el buffer */
342 buffer[buffer_pos++] = c;
345 /* Me retornaron un numero positivo!!, eso quiere decir que ese numero
346 * es la posicion dentro del diccionario de la palabra que puedo reemplazar
348 data[i++] = ESCAPE_CHARACTER;
349 /* Trato de hacer que el caracter sea comun en textos, para que no me rompa
354 /* El buffer no lo necesito mas */
359 for(j=0; j<buffer_pos; j++)
360 data[i++] = buffer[j];
361 /* Saco un EOF que lee de mas */
367 char *bs_finalblock(char *data, Uint32 len, Uint32 *new_size)
373 for(i=0; i < len; i++) {
374 if (data[i] == ESCAPE_CHARACTER) {
376 if (data[i] == 0xF) {
377 /* Solo tengo que dejar el ESCAPE_CHARACTER */
379 out = (char *)realloc(out, size*sizeof(char));
380 out[size-1] = data[i];
381 /* Salteo ese caracter */
383 /* Va una palabra!! */
385 size += dic[(size_t)tmp].len;
386 out = (char *)realloc(out, size*sizeof(char));
387 for(j=0; j<dic[(size_t)tmp].len; j++) {
388 out[size-dic[(size_t)tmp].len+j] = dic[(size_t)tmp].word[j];
390 /* Salteo el caracter siguiente al de escape */
394 out = (char *)realloc(out, size*sizeof(char));
395 out[size-1] = data[i];