1 /*
2 * Copyright (C) 2001, 2002, and 2003 Roy Keene
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * email: dact@rkeene.org
19 */
20
21
22 #include "dact.h"
23 #include "comp_text.h"
24 #include "buffer.h"
25 #include <stdio.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35
36
37 /*
38 mode - DACT_MODE_COMPR or DACT_MODE_DECMP
39 Determine whether to compress or decompress.
40 prev_block - Previous (uncompressed) block.
41 curr_block - The data to be compressed.
42 out_block - Where to put data after compression.
43 blk_size - Size of prev_block and curr_block.
44 */
45
46 #if defined(USE_MODULES) && defined(AS_MODULE)
47 #include "module.h"
48 uint32_t DC_NUM=3;
49 uint32_t DC_TYPE=DACT_MOD_TYPE_COMP;
50 void *DC_ALGO=comp_text_algo;
51 char *DC_NAME="Text Compression (MOD)";
52 #endif
53
comp_text_algo(int mode,unsigned char * prev_block,unsigned char * curr_block,char * out_block,int blk_size,int bufsize)54 int comp_text_algo(int mode, unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int bufsize) {
55 switch(mode) {
56 case DACT_MODE_COMPR:
57 return(comp_text_compress(prev_block, curr_block, out_block, blk_size, bufsize));
58 break; /* Heh */
59 case DACT_MODE_DECMP:
60 return(comp_text_decompress(prev_block, curr_block, out_block, blk_size, bufsize));
61 break;
62 default:
63 printf("Unsupported mode: %i\n", mode);
64 return(-1);
65 }
66 }
67
comp_text_compress(unsigned char * prev_block,unsigned char * curr_block,char * out_block,int blk_size,int bufsize)68 int comp_text_compress(unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int bufsize) {
69 unsigned char low_byte=255, high_byte=0;
70 unsigned char byte_buf;
71 unsigned int range;
72 int i,x=0,y;
73
74
75 bit_buffer_purge();
76
77 for (i=0;i<blk_size;i++) {
78 if (((unsigned char) curr_block[i])<low_byte) low_byte=curr_block[i];
79 if (((unsigned char) curr_block[i])>high_byte) high_byte=curr_block[i];
80 }
81
82 range=(unsigned int) (high_byte-low_byte);
83
84 out_block[x++]=low_byte;
85 out_block[x++]=high_byte;
86
87 if (range==0)
88 return(2);
89
90 for (y=1;y<=8;y++)
91 if ((range>>y)==0) break;
92 if (y==8) return(-1);
93
94 for (i=0;i<blk_size;i++) {
95 byte_buf=(unsigned char) (curr_block[i]-low_byte);
96 /*
97 if ((byte_buf>>y)==1) {
98 return(-1);
99 }
100 */
101 bit_buffer_write(byte_buf,y);
102
103 while (bit_buffer_size()>=8) {
104 out_block[x++]=bit_buffer_read(8);
105 }
106 }
107 /* Remove any less-than-one-byte data */
108 if ((i=bit_buffer_size())!=0) {
109 out_block[x++]=(bit_buffer_read(i)<<(8-i));
110 }
111
112 return(x);
113 }
114
comp_text_decompress(unsigned char * prev_block,unsigned char * curr_block,char * out_block,int blk_size,int bufsize)115 int comp_text_decompress(unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int bufsize) {
116 unsigned char high_byte, low_byte;
117 unsigned int range;
118 int i=0,x=0,y;
119
120 low_byte=curr_block[x++];
121 high_byte=curr_block[x++];
122 range=(unsigned int) (high_byte-low_byte);
123
124 if (range==0) {
125 memset(out_block, low_byte, bufsize);
126 return(bufsize);
127 }
128 for (y=1;y<=8;y++)
129 if ((range>>y)==0) break;
130
131 bit_buffer_purge();
132
133 while (1) {
134 if (bit_buffer_size()<y) bit_buffer_write((unsigned char) curr_block[x++],8);
135 out_block[i++]=(bit_buffer_read(y)+low_byte);
136 if ((x==blk_size) && (bit_buffer_size()<y)) break;
137 if (i>=(bufsize)) break;
138 }
139
140 return(i);
141 }
142