32695067df51293834dfc4b876d20d4158743a83
[oweals/cde.git] / cde / lib / DtSearch / hencode.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *   COMPONENT_NAME: austext
25  *
26  *   FUNCTIONS: convert_str_2_char
27  *              gen_vec
28  *              hc_encode
29  *              main
30  *              process_char
31  *
32  *   ORIGINS: 27
33  *
34  *
35  *   (C) COPYRIGHT International Business Machines Corp. 1990,1995
36  *   All Rights Reserved
37  *   Licensed Materials - Property of IBM
38  *   US Government Users Restricted Rights - Use, duplication or
39  *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
40  */
41 /********************** HENCODE.C ***********************
42  * $XConsortium: hencode.c /main/9 1996/11/21 19:50:29 drk $
43  * Huffman encoder program.
44  *
45  * $Log$
46  * Revision 2.3  1996/03/13  22:56:39  miker
47  * Changed char to UCHAR several places.
48  *
49  * Revision 2.2  1995/10/26  15:11:42  miker
50  * Added prolog.
51  *
52  * Revision 2.1  1995/09/22  20:50:40  miker
53  * Freeze DtSearch 0.1, AusText 2.1.8
54  *
55  * Revision 1.3  1995/09/05  18:07:00  miker
56  * Name changes for DtSearch.
57  */
58 #include "SearchP.h"
59 #include <errno.h>
60 #include <stdlib.h>
61
62 #define X_INCLUDE_STRING_H
63 #define XOS_USE_NO_LOCKING
64 #include <X11/Xos_r.h>
65
66 #define PROGNAME        "HENCODE"
67 #define MS_huff         30      /* message catalog set number */
68 #define DELIMITERS      "\t\n"
69 #define LAST_BIT        '-'
70 #define LITERAL_NUM     256
71 #define NO_SPACE        0
72
73
74 /*------------------------ GLOBALS ---------------------------*/
75 long            gen_vec_hufid = 0L;
76
77 static struct or_blobrec blobrec;
78 static char    *huff_code[257];
79 static int      code_length[257];
80 static char     coded_bits_str[9];
81 static char     bit_pos = 0;
82 static char     bits_left;
83 static int      total_num_chars = 0;
84 static int      num_char_coded = 0;
85 static char     zero_str[] = "00000000";
86
87 #define MAX_NUM_CHAR    (sizeof(blobrec.or_blob) - 1)
88 #define MAX_NUM_BITS    (8 * MAX_NUM_CHAR)
89
90 /****************************************/
91 /*                                      */
92 /*            GENERATE VECTORS          */
93 /*                                      */
94 /****************************************/
95 void            gen_vec (char *fname_huffcode_tab)
96 {
97     char            temp[40];
98     int             i, j;
99     char            tab_filebuf[128];
100     unsigned char   ch;
101     FILE           *tab_stream;
102     _Xstrtokparams  strtok_buf;
103
104     if ((tab_stream = fopen (fname_huffcode_tab, "r")) == NULL) {
105         printf (catgets(dtsearch_catd, MS_huff, 1,
106             "%s: Cannot open huffman encode file '%s':\n"
107             "  %s\n  Exit Code = 2\n"),
108             PROGNAME"222", fname_huffcode_tab, strerror (errno));
109         DtSearchExit (2);
110     }
111     memset (huff_code, 0, sizeof(huff_code));
112     memset (code_length, 0, sizeof(code_length));
113     /*
114      * First line in the file contains time stamp. We have to read
115      * it separately. First token on first line is hufid. Save it
116      * in a global for optional use by caller. 
117      */
118     fgets (tab_filebuf, sizeof (tab_filebuf) - 1, tab_stream);
119     gen_vec_hufid = atol (tab_filebuf);
120
121     /*-------------- READ IN HUFFMAN FILE ------------*/
122     /*
123      * We are only interested in the character itself (index) and
124      * its Huffman Code 
125      */
126     while (fgets (tab_filebuf, sizeof (tab_filebuf) - 1, tab_stream)
127         != NULL) {
128         i = atoi (_XStrtok (tab_filebuf, DELIMITERS, strtok_buf)); /* char */
129         /* read current huff code */
130         strcpy (temp, _XStrtok (NULL, DELIMITERS, strtok_buf));
131         if (temp[0] == ' ') {
132             /* Empty huffcode associated with LITERAL CODE.
133              * Either this is literal char itself and literal
134              * encodeing has been turned off, or this char is
135              * so rare that it is coded using the literal char.
136              */
137             if (i == 256)
138                 continue;
139
140             /* current character has LITERAL CODE */
141             strcpy (temp, huff_code[LITERAL_NUM]);
142             *(code_length + i) = *(code_length + LITERAL_NUM) + 8;
143             ch = (unsigned char) i;
144             for (j = 0; j < 8; j++) {
145                 if (ch & 0x80) {
146                     temp[*(code_length + LITERAL_NUM) + j] =
147                         '1';
148                 }
149                 else {
150                     temp[*(code_length + LITERAL_NUM) + j] =
151                         '0';
152                 }
153                 ch = ch << 1;
154             }
155             temp[*(code_length + LITERAL_NUM) + 8] = '\0';
156             huff_code[i] =
157                 (char *) malloc (*(code_length + i) + 1);
158             strcpy (huff_code[i], temp);
159         }
160         else {
161             /* regular HUFFMAN code */
162             *(code_length + i) = strlen (temp);
163             huff_code[i] =
164                 (char *) malloc (*(code_length + i) + 1);
165             strcpy (huff_code[i], temp);
166         }
167     }
168     fclose (tab_stream);
169 }  /* end of function gen_vec */
170
171 /********************************************************/
172 /*                                                      */
173 /*      Convert Coded String to Coded Character         */
174 /*                                                      */
175 /********************************************************/
176 void            convert_str_2_char (char *code)
177 {
178     int             i, j;
179
180     *code = 0;
181     j = 1;
182     for (i = 0; i < 8; i++) {
183         if (*(coded_bits_str + (7 - i)) == '1') {
184             *code += j;
185         }
186         j = j * 2;
187     }
188     total_num_chars++;
189     return;
190 }
191
192 /****************************************/
193 /*                                      */
194 /*      Process Current Character       */
195 /*                                      */
196 /****************************************/
197 int             process_char (UCHAR ch, char *bitstr)
198 {
199     char            temp_code[40];
200     char            coded_char;
201     int             i, j;
202     int             num_of_bits_in_code;
203
204     i = (int) ch;
205     num_of_bits_in_code = *(code_length + i);
206     if ((MAX_NUM_BITS - total_num_chars * 8 - bit_pos) <
207         num_of_bits_in_code) {
208         return NO_SPACE;
209     }
210     strcpy (temp_code, huff_code[i]);
211     while (TRUE) {
212         /* fill new character with Huffman Code */
213         if (bit_pos == 0) {
214             if (num_of_bits_in_code == 8) {
215                 strcpy (coded_bits_str, temp_code);
216                 convert_str_2_char (&coded_char);
217                 bitstr[total_num_chars - 1] = coded_char;
218                 return TRUE;
219             }
220             if (num_of_bits_in_code < 8) {
221                 strcpy (coded_bits_str, temp_code);
222                 bit_pos = num_of_bits_in_code;
223                 bits_left = 8 - bit_pos;
224                 return TRUE;
225             }
226             if (num_of_bits_in_code > 8) {
227                 strncpy (coded_bits_str, temp_code, 8);
228                 coded_bits_str[8] = '\0';
229                 convert_str_2_char (&coded_char);
230                 bitstr[total_num_chars - 1] = coded_char;
231                 num_of_bits_in_code -= 8;
232                 strcpy (temp_code, &temp_code[8]);
233             }
234         }       /* end of bit_pos == 0 loop */
235         else {
236             j = bit_pos + num_of_bits_in_code;
237             if (j == 8) {
238                 bit_pos = 0;
239                 strcat (coded_bits_str, temp_code);
240                 convert_str_2_char (&coded_char);
241                 bitstr[total_num_chars - 1] = coded_char;
242                 return TRUE;
243             }
244             if (j < 8) {
245                 strcat (coded_bits_str, temp_code);
246                 bit_pos = j;
247                 bits_left = 8 - bit_pos;
248                 return TRUE;
249             }
250             if (j > 8) {
251                 strncat (coded_bits_str, temp_code,
252                     (size_t) bits_left);
253                 convert_str_2_char (&coded_char);
254                 bitstr[total_num_chars - 1] = coded_char;
255                 num_of_bits_in_code -= bits_left;
256                 strcpy (temp_code, &huff_code[i][bits_left]);
257                 bit_pos = 0;
258             }
259         }       /* end of else loop */
260     }   /* end of while(TRUE) loop */
261 }
262
263 /************************************************/
264 /*                                              */
265 /*                 HC Encode                    */
266 /*                                              */
267 /************************************************/
268 int             hc_encode (struct or_blobrec * targblobrec,
269                     UCHAR *charbuf,
270                     int charcount,
271                     int file_pos)
272 {
273 /********** replaced by blobrec above...
274         union charint
275                 {
276                 char ch[2];
277                 INT      orig_char_count;
278                 } un1;
279         static char temp1 [MAX_NUM_CHAR+1];  ...repl by blobrec;
280 ************/
281     char           *targ, *src;
282     int             i, j;
283     char            temp;
284     char            ret_code = TRUE;
285     char            write = FALSE;
286     char            last_call = FALSE;
287
288     if (charcount == 0) {
289         last_call = TRUE;
290         charcount = 1;
291     }
292     for (i = 0; i < charcount; i++) {
293         if (!last_call) {
294             ret_code = process_char (charbuf[i], (char *) blobrec.or_blob);
295         }
296         if ((ret_code == NO_SPACE) ||
297             (file_pos && (i == (charcount - 1)))) {
298             if (!last_call) {
299                 if (file_pos && (i == (charcount - 1))) {
300                     num_char_coded++;
301                 }
302             }
303             if (bit_pos) {
304                 strncat (coded_bits_str, zero_str,
305                     (size_t) bits_left);
306                 convert_str_2_char (&temp);
307                 blobrec.or_blob[total_num_chars - 1][0] = temp;
308             }
309             write = TRUE;
310             /**********
311                 un1.orig_char_count = num_char_coded;
312                 bitstring[0] = un1.ch[0];
313                 bitstring[1] = un1.ch[1];
314                 for (j = 0; j <= total_num_chars; j++) {
315                        *(bitstring + j + 2) = *(temp1 + j);
316                        };
317                 **************/
318             targblobrec->or_bloblen = num_char_coded;
319             targ = (char *) targblobrec->or_blob;
320             src = (char *) blobrec.or_blob;
321             for (j = 0; j < total_num_chars; j++)
322                 *targ++ = *src++;
323
324             num_char_coded = 0;
325             bit_pos = 0;
326             total_num_chars = 0;
327             if (file_pos && (i == (charcount - 1))) {
328                 return write;
329             }
330             i--;
331         }
332         else {
333             num_char_coded++;
334         }
335     }
336     return write;
337 }
338
339 #ifdef DEBUG_HENCODE
340 /****************************************/
341 /*                                      */
342 /*                 Main                 */
343 /*                                      */
344 /****************************************/
345 main (int argc, char *argv[])
346 {
347     FILE           *stream;
348     char            bitstring[MAX_NUM_CHAR + 2];
349     char            charbuf[MAX_NUM_CHAR + 1];
350     int             charcount = 0;
351     int             mychar;
352
353     if (argc < 2) {
354         fprintf (stderr, "Usage: try filename\n");
355         exit (1);
356     }
357     if ((stream = fopen (argv[1], "rb")) == NULL) {
358         fprintf (stderr, "Could not open input file '%s'\n", argv[1]);
359         exit (2);
360     }
361     fp = fopen ("codefile.dat", "wb");
362     gen_vec ();
363     while ((mychar = getc (stream)) != EOF) {
364         charbuf[charcount] = mychar;
365         charcount++;
366         if (charcount == MAX_NUM_CHAR) {
367             hc_encode (bitstring, charbuf, charcount, 0);
368             /*
369              * for (j = 0; j < charcount; j++) {
370              * fputc(bitstring[j], fp); } 
371              */
372             charcount = 0;
373         }
374     }
375     hc_encode (bitstring, charbuf, charcount, 1);
376     printf ("Total Number of Characters = %ld\n", total_num_chars);
377     fclose (fp);
378     fclose (stream);
379     return;
380 }
381
382 #endif
383 /********************** HENCODE.C ***********************/