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"),
95 /* Algunas cosas de ingles para mejorar otros textos */
100 PALABRA(" program "),
115 typedef struct _bs_decode_t_ {
120 char es_menor(char *data, t_BlockSort *bs, int i, int j);
122 int _compare(const void *d1, const void *d2) {
123 t_BlockSortDecode *s1, *s2;
125 s1 = (t_BlockSortDecode *)d1;
126 s2 = (t_BlockSortDecode *)d2;
128 /* Hack si es el mismo caracter, dejo como mejor la de menor sig */
129 if (s1->c == s2->c) {
130 return (s1->sig - s2->sig);
133 return (s1->c - s2->c);
136 int __compare(const void *d1, const void *d2) {
137 t_BlockSortData *s1, *s2;
139 s1 = (t_BlockSortData *)d1;
140 s2 = (t_BlockSortData *)d2;
142 return es_menor(s1->bs->data, s1->bs, s1->pos_inicial, s2->pos_inicial);
145 char es_menor(char *data, t_BlockSort *bs, int i, int j)
149 for(k=0; k<bs->len; k++) {
153 if (data[pi] > data[pj]) return 1; /* El primero es mayor */
154 if (data[pi] < data[pj]) return -1; /* El primero es menor */
161 void generar_array(char *data, t_BlockSort *bs)
164 for(i=0; i<bs->len; i++) {
165 bs->array[i].pos_inicial = i;
166 bs->array[i].pos_final = (i+bs->len-1)%bs->len;
167 bs->array[i].ord = (i==0)?1:0;
168 bs->array[i].bs = bs;
172 void ordenar_array(char *data, t_BlockSort *bs)
174 qsort(bs->array, bs->len, sizeof(t_BlockSortData), __compare);
177 int generar_salida(char *data, t_BlockSort *bs, char *salida)
182 /* Dejo lugar para guardar el K */
183 out = salida + sizeof(Uint32);
186 for(i=0; i<bs->len; i++) {
187 out[i] = data[bs->array[i].pos_final];
188 if (bs->array[i].ord == 1) k = i;
193 void bs_solve(char *in, char *out, t_BlockSort *bs, Uint32 *k, Uint32 leido)
197 /* Hack para pedasos menores a la pagina */
198 if (leido < bs->len) bs->len = leido;
201 generar_array(in, bs);
202 ordenar_array(in, bs);
203 (*k) = generar_salida(in, bs, out);
205 /* Guardo el k y el tamaño en el array */
206 memcpy(out, k, sizeof(Uint32));
210 void bs_restore(char *dst, char *c, Uint32 k, Uint32 len)
213 t_BlockSortDecode *in;
215 in = malloc(sizeof(t_BlockSortDecode)*len);
217 for(i=0; i<len; i++) {
222 qsort(in, len, sizeof(t_BlockSortDecode), _compare);
227 dst[i++] = in[current].c;
228 current = in[current].sig;
229 } while (current != k);
233 t_BlockSort *bs_create(Uint32 len)
237 tmp = malloc(sizeof(t_BlockSort));
238 tmp->array = malloc(sizeof(t_BlockSortData)*len);
245 void bs_destroy(t_BlockSort *bs)
252 void bs_EOL(char *data, Uint32 pagesize, Uint32 *j)
254 /* Trato de agregar 4 espacios antes y 4 despues de un \n */
257 /* Verifico poder hacerlo */
258 if ((i+9) >= pagesize) return; /* No pude! */
273 char check_hint(char c)
275 static int current_pos = 0;
280 for(i=0; i<DICT_SIZE; i++) {
281 /* Veo de no pasarme */
282 if (current_pos < dic[i].len) {
283 /* Si la palabra tiene suficientes hints */
284 if (dic[i].hits == current_pos) {
285 if (dic[i].word[current_pos] == c) {
288 if (dic[i].hits == dic[i].len) {
292 /* Esta palabra ya no tiene posibilidades */
305 return -1; /* No hay hints ! */
307 if (hits > 1) return -2; /* Tengo mas de 1 hint! */
309 if (hit_pos == -1) return -2; /* Tengo 1 solo hit pero no es completo */
311 /* Tengo 1 solo hint !!!! */
319 for(i=0; i<DICT_SIZE; i++) {
324 int bs_readblock(FILE *fp, char *data, Uint32 pagesize, int usar_dic)
331 while ((!feof(fp)) && ((i+buffer_pos) < pagesize)) {
339 if (c == ESCAPE_CHARACTER) {
346 hint = check_hint(c);
350 /* No hay hints, vacio el buffer y luego saco el c */
351 for(j=0; j<buffer_pos; j++)
352 data[i++] = buffer[j];
359 /* Tengo mas de 1 hit, tengo posibilidades, guardo este char en el buffer */
360 buffer[buffer_pos++] = c;
363 /* Me retornaron un numero positivo!!, eso quiere decir que ese numero
364 * es la posicion dentro del diccionario de la palabra que puedo reemplazar
366 data[i++] = ESCAPE_CHARACTER;
367 /* Trato de hacer que el caracter sea comun en textos, para que no me rompa
372 /* El buffer no lo necesito mas */
377 for(j=0; j<buffer_pos; j++)
378 data[i++] = buffer[j];
379 /* Saco un EOF que lee de mas */
385 char *bs_finalblock(char *data, Uint32 len, Uint32 *new_size)
391 for(i=0; i < len; i++) {
392 if (data[i] == ESCAPE_CHARACTER) {
394 if (data[i] == 0xF) {
395 /* Solo tengo que dejar el ESCAPE_CHARACTER */
397 out = (char *)realloc(out, size*sizeof(char));
398 out[size-1] = data[i];
399 /* Salteo ese caracter */
401 /* Va una palabra!! */
403 size += dic[(size_t)tmp].len;
404 out = (char *)realloc(out, size*sizeof(char));
405 for(j=0; j<dic[(size_t)tmp].len; j++) {
406 out[size-dic[(size_t)tmp].len+j] = dic[(size_t)tmp].word[j];
408 /* Salteo el caracter siguiente al de escape */
412 out = (char *)realloc(out, size*sizeof(char));
413 out[size-1] = data[i];