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