encoding.c: Upgrade upcase table and rewrite decompression code
[wimlib] / tools / compress_upcase_table.c
1 /*
2  * compress_upcase_table.c
3  *
4  * Compress a table that maps each UCS-2 character to its upper case equivalent.
5  *
6  * ----------------------------------------------------------------------------
7  *
8  * Copyright (C) 2015 Eric Biggers
9  *
10  * This file is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU Lesser General Public License as published by the Free
12  * Software Foundation; either version 3 of the License, or (at your option) any
13  * later version.
14  *
15  * This file is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this file; if not, see http://www.gnu.org/licenses/.
22  */
23
24 #include <fcntl.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <sys/mman.h>
29
30 #define LEN 65536
31 #define SIZE (65536 * sizeof(uint16_t))
32
33 static uint16_t
34 match_length(const uint16_t *p1, const uint16_t *p2, uint16_t max_len)
35 {
36         uint16_t len = 0;
37
38         while (len < max_len && p1[len] == p2[len])
39                 len++;
40
41         return len;
42 }
43
44 static void
45 longest_match(const uint16_t *tab, uint16_t cur_pos,
46               uint16_t *len_ret, uint16_t *src_pos_ret)
47 {
48         uint16_t max_len = LEN - cur_pos;
49         uint16_t src_pos;
50         *len_ret = 0;
51         *src_pos_ret = 0;
52         for (src_pos = 0; src_pos < cur_pos; src_pos++) {
53                 /* check for match at this pos  */
54                 uint16_t len = match_length(&tab[cur_pos], &tab[src_pos], max_len);
55                 if (len > *len_ret) {
56                         *len_ret = len;
57                         *src_pos_ret = src_pos;
58                 }
59         }
60 }
61
62 static void
63 output(uint16_t v)
64 {
65         printf("0x%04x, ", v);
66 }
67
68 int main()
69 {
70         int fd = open("upcase.tab", O_RDONLY);
71         if (fd < 0) {
72                 fprintf(stderr, "ERROR: upcase.tab not found\n");
73                 return 1;
74         }
75         uint16_t *tab = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
76         uint32_t i;
77
78         /* Delta filter  */
79         for (i = 0; i < LEN; i++)
80                 tab[i] -= i;
81
82         /* Simple LZ encoder  */
83         for (i = 0; i < LEN; ) {
84                 uint16_t len, src_pos;
85                 longest_match(tab, i, &len, &src_pos);
86                 if (len <= 1) {
87                         /* Literal  */
88                         output(0);
89                         output(tab[i]);
90                         i++;
91                 } else {
92                         /* Match  */
93                         output(len);
94                         output(src_pos);
95                         i += len;
96                 }
97         }
98         return 0;
99 }