Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <errno.h>
00012 #include <string.h>
00013
00014 #include "lists.h"
00015 #include "bitops.h"
00016 #include "lzw.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define BITBUF_TYPE unsigned int
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 struct lzw_dict_s {
00087 char c;
00088 int code;
00089 int freq;
00090 struct lzw_dict_s *children;
00091 struct lzw_dict_s *next;
00092 };
00093 typedef struct lzw_dict_s lzw_dict_t;
00094
00095
00096
00097
00098
00099
00100
00101
00102 struct lzw_state_s {
00103
00104 int n;
00105 lzw_dict_t *d;
00106 lzw_dict_t *s;
00107
00108
00109 BITBUF_TYPE buf;
00110 int bufsize;
00111 int eod;
00112 };
00113 typedef struct lzw_state_s lzw_state_t;
00114
00115
00116
00117
00118
00119 static void lzw_free_dict(lzw_dict_t *s) {
00120 lzw_dict_t *e;
00121
00122 list_forall_unlink(e, s) {
00123 lzw_free_dict(e->children);
00124 free(e);
00125 }
00126 }
00127
00128
00129
00130 static void lzw_clear_table(lzw_state_t *st) {
00131
00132 lzw_free_dict(st->d);
00133 st->d = NULL;
00134 st->n = 258;
00135 st->s = NULL;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144 static inline void lzw_emit(int code, lzw_state_t *st) {
00145 BITBUF_TYPE mask;
00146 int bits = hibit(st->n);
00147
00148
00149 mask = (1 << bits) - 1;
00150 code &= mask;
00151
00152 st->buf |= code << (8*sizeof(BITBUF_TYPE) - st->bufsize - bits);
00153 st->bufsize += bits;
00154 }
00155
00156
00157
00158 static inline void lzw_read_bitbuf(lzw_stream_t *s) {
00159 int ch;
00160 lzw_state_t *st = (lzw_state_t *)s->internal;
00161
00162 ch = st->buf >> (8*sizeof(BITBUF_TYPE)-8);
00163 st->buf <<= 8;
00164 st->bufsize -= 8;
00165
00166 s->next_out[0] = ch;
00167 s->next_out++;
00168 s->avail_out--;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178 static int lzw_encode_char(lzw_state_t *st, char c) {
00179 lzw_dict_t *e;
00180
00181
00182
00183
00184 if (st->s == NULL) {
00185 lzw_emit(256, st);
00186 goto singleton;
00187 }
00188
00189
00190 list_find(e, st->s->children, e->c == c);
00191 if (e) {
00192 e->freq++;
00193 st->s = e;
00194 return 0;
00195 }
00196
00197
00198
00199
00200
00201 lzw_emit(st->s->code, st);
00202 if (st->n >= 4094) {
00203 st->n++;
00204 lzw_emit(256, st);
00205 goto dictfull;
00206 }
00207
00208
00209 e = (lzw_dict_t *)malloc(sizeof(lzw_dict_t));
00210 if (!e) {
00211 return 1;
00212 }
00213 e->c = c;
00214 e->code = st->n;
00215 e->freq = 1;
00216 e->children = NULL;
00217 list_prepend(st->s->children, e);
00218 st->n++;
00219 goto singleton;
00220
00221 dictfull:
00222 lzw_clear_table(st);
00223
00224
00225 singleton:
00226 list_find(e, st->d, e->c == c);
00227 if (!e) {
00228 e = (lzw_dict_t *)malloc(sizeof(lzw_dict_t));
00229 if (!e) {
00230 return 1;
00231 }
00232 e->c = c;
00233 e->code = (int)(unsigned char)c;
00234 e->freq = 0;
00235 e->children = NULL;
00236 list_prepend(st->d, e);
00237 }
00238 e->freq++;
00239 st->s = e;
00240 return 0;
00241 }
00242
00243
00244
00245
00246
00247 static void lzw_encode_eod(lzw_state_t *st) {
00248
00249
00250
00251 if (st->s == NULL) {
00252 lzw_emit(256, st);
00253 st->n=258;
00254 lzw_emit(257, st);
00255 return;
00256 }
00257
00258
00259
00260
00261 lzw_emit(st->s->code, st);
00262 st->n++;
00263 lzw_emit(257, st);
00264 return;
00265 }
00266
00267
00268
00269
00270
00271 lzw_stream_t *lzw_init(void) {
00272 lzw_stream_t *s = NULL;
00273 lzw_state_t *st = NULL;
00274
00275 s = (lzw_stream_t *)malloc(sizeof(lzw_stream_t));
00276 if (s==NULL) {
00277 goto fail;
00278 }
00279 st = (lzw_state_t *)malloc(sizeof(lzw_state_t));
00280 if (st==NULL) {
00281 goto fail;
00282 }
00283 st->buf = 0;
00284 st->bufsize = 0;
00285 st->eod = 0;
00286 st->d = NULL;
00287 lzw_clear_table(st);
00288 s->internal = (void *) st;
00289 return s;
00290
00291 fail:
00292 free(s);
00293 free(st);
00294 return NULL;
00295 }
00296
00297 int lzw_compress(lzw_stream_t *s, int mode) {
00298 int r;
00299 lzw_state_t *st = (lzw_state_t *)s->internal;
00300
00301 while (st->eod == 0) {
00302
00303 while (st->bufsize > 7) {
00304 if (s->avail_out == 0) {
00305 return 0;
00306 } else {
00307 lzw_read_bitbuf(s);
00308 }
00309 }
00310
00311 if (s->avail_in == 0) {
00312 break;
00313 } else {
00314 r = lzw_encode_char(st, s->next_in[0]);
00315 if (r) {
00316 if (r==2) {
00317 errno = EINVAL;
00318 }
00319 return 1;
00320 }
00321 s->next_in++;
00322 s->avail_in--;
00323 }
00324 }
00325
00326 if (mode==LZW_EOD && st->eod == 0) {
00327 st->eod = 1;
00328 lzw_encode_eod(st);
00329 }
00330
00331
00332 if (st->eod) {
00333 while (st->bufsize > 0) {
00334 if (s->avail_out == 0) {
00335 return 0;
00336 } else {
00337 lzw_read_bitbuf(s);
00338 }
00339 }
00340 }
00341
00342 return 0;
00343 }
00344
00345 void lzw_free(lzw_stream_t *s) {
00346 lzw_state_t *st = (lzw_state_t *)s->internal;
00347
00348 lzw_free_dict(st->d);
00349 free(st);
00350 free(s);
00351 }
00352
00353
00354
00355
00356 #ifdef LZW_MAIN
00357
00358 int main() {
00359 lzw_stream_t *s;
00360 int ch;
00361 char inbuf[100];
00362 char outbuf[100];
00363 int i, r;
00364 int mode;
00365
00366 s = lzw_init();
00367 if (!s) {
00368 goto error;
00369 }
00370 mode = LZW_NORMAL;
00371
00372 while (1) {
00373
00374 for (i=0; i<100; i++) {
00375 ch = fgetc(stdin);
00376 if (ch==EOF) {
00377 break;
00378 }
00379 inbuf[i] = ch;
00380 }
00381 if (i<100) {
00382 mode = LZW_EOD;
00383 }
00384
00385
00386 s->next_in = inbuf;
00387 s->avail_in = i;
00388 do {
00389 s->next_out = outbuf;
00390 s->avail_out = 100;
00391 r = lzw_compress(s, mode);
00392 if (r) {
00393 goto error;
00394 }
00395 fwrite(outbuf, 1, 100-s->avail_out, stdout);
00396 } while (s->avail_out==0);
00397 if (mode == LZW_EOD) {
00398 break;
00399 }
00400 }
00401 fflush(stdout);
00402 lzw_free(s);
00403
00404 return 0;
00405
00406 error:
00407 fprintf(stderr, "lzw: %s\n", strerror(errno));
00408 lzw_free(s);
00409 return 1;
00410
00411 }
00412 #endif
00413