built-in jambase is packed now
[k8jam.git] / src / jbunpack.c
blob36d51c914b165778a113876b3d0b70e34b93420a
1 ////////////////////////////////////////////////////////////////////////////////
2 // decompression code license (ONLY decompression code)
3 //
4 // Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
18 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 // SUCH DAMAGE.
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
36 #include "jambase.h"
39 #define FICL_BIT_NUMBER(x) (1<<(x))
41 #define FICL_LZ_TYPE_BITS (1)
42 #define FICL_LZ_OFFSET_BITS (12)
43 #define FICL_LZ_LENGTH_BITS (5)
44 #define FICL_LZ_NEXT_BITS (8)
45 #define FICL_LZ_PHRASE_BITS (FICL_LZ_TYPE_BITS + FICL_LZ_OFFSET_BITS + FICL_LZ_LENGTH_BITS + FICL_LZ_NEXT_BITS)
46 #define FICL_LZ_SYMBOL_BITS (FICL_LZ_TYPE_BITS + FICL_LZ_NEXT_BITS)
49 ** if you match fewer characters than this, don't bother,
50 ** it's smaller to encode it as a sequence of symbol tokens.
51 **/
52 #define FICL_LZ_MINIMUM_USEFUL_MATCH ((int)(FICL_LZ_PHRASE_BITS / FICL_LZ_SYMBOL_BITS))
54 #define FICL_LZ_WINDOW_SIZE (FICL_BIT_NUMBER(FICL_LZ_OFFSET_BITS))
55 #define FICL_LZ_BUFFER_SIZE (FICL_BIT_NUMBER(FICL_LZ_LENGTH_BITS) + FICL_LZ_MINIMUM_USEFUL_MATCH)
57 #define FICL_MIN(a, b) (((a) < (b)) ? (a) : (b))
60 static uint16_t ficlNetworkUnsigned16 (uint16_t number) {
61 uint8_t *pointer = (uint8_t *)&number;
63 return (uint16_t)(((uint16_t)(pointer[0]<<8))|(pointer[1]));
67 static uint32_t ficlNetworkUnsigned32 (uint32_t number) {
68 uint16_t *pointer = (uint16_t *)&number;
70 return ((uint32_t)(ficlNetworkUnsigned16(pointer[0])<<16))|ficlNetworkUnsigned16(pointer[1]);
74 static inline void bitSet (unsigned char *bits, size_t index, int value) {
75 int byteIndex = index >> 3;
76 int bitIndex = index & 7;
77 unsigned char mask = (unsigned char)(128 >> bitIndex);
79 if (value) bits[byteIndex] |= mask; else bits[byteIndex] &= ~mask;
83 static int bitGet (const unsigned char *bits, size_t index) {
84 int byteIndex = index >> 3;
85 int bitIndex = index & 7;
86 unsigned char mask = (unsigned char)(128 >> bitIndex);
88 return ((mask & bits[byteIndex]) ? 1 : 0);
92 static void bitGetString (unsigned char *destination, const unsigned char *source, int offset, int count, int destAlignment) {
93 int bit = destAlignment-count;
95 while (count--) bitSet(destination, bit++, bitGet(source, offset++));
99 static int lzDecodeHeaderField (const unsigned char *data, int *byteOffset) {
100 unsigned char id;
101 int networkOrder, length;
103 id = data[(*byteOffset)++];
104 if (id < 252) return id;
105 networkOrder = 0;
106 length = (id == 253) ? 2: 4;
107 bitGetString(((unsigned char *)&networkOrder), data, (*byteOffset)*8, length*8, sizeof(networkOrder)*8);
108 (*byteOffset) += length;
109 return ficlNetworkUnsigned32(networkOrder);
113 static int lzUncompress (const unsigned char *compressed, char **uncompressed_p, size_t *uncompressedSize_p) {
114 unsigned char *window, *buffer, *uncompressed, *initialWindow;
115 int bitstreamLength, inputPosition, uncompressedSize;
117 *uncompressed_p = NULL;
118 inputPosition = 0;
119 bitstreamLength = lzDecodeHeaderField(compressed, &inputPosition);
120 uncompressedSize = lzDecodeHeaderField(compressed, &inputPosition);
121 inputPosition <<= 3; /* same as * 8 */
122 bitstreamLength += inputPosition;
123 uncompressed = (unsigned char *)calloc(uncompressedSize+1, 1);
124 if (uncompressed == NULL) return -1;
125 window = buffer = uncompressed;
126 initialWindow = buffer+FICL_LZ_WINDOW_SIZE;
127 while (inputPosition != bitstreamLength) {
128 int length, token = bitGet(compressed, inputPosition);
129 ++inputPosition;
130 if (token) {
131 /* phrase token */
132 int offset = 0;
134 bitGetString((unsigned char *)&offset, compressed, inputPosition, FICL_LZ_PHRASE_BITS-(1+FICL_LZ_NEXT_BITS), sizeof(offset)*8);
135 offset = ficlNetworkUnsigned32(offset);
136 inputPosition += FICL_LZ_PHRASE_BITS-(1+FICL_LZ_NEXT_BITS);
137 length = (offset & ((1 << FICL_LZ_LENGTH_BITS)-1))+FICL_LZ_MINIMUM_USEFUL_MATCH;
138 offset >>= FICL_LZ_LENGTH_BITS;
139 memmove(buffer, window+offset, length);
140 buffer += length;
141 ++length;
142 } else {
143 length = 1;
145 /* symbol token */
146 *buffer = 0;
147 bitGetString(buffer++, compressed, inputPosition, FICL_LZ_NEXT_BITS, sizeof(*buffer) * 8);
148 inputPosition += FICL_LZ_NEXT_BITS;
149 if (buffer > initialWindow) window = buffer-FICL_LZ_WINDOW_SIZE;
151 *uncompressed_p = (char *)uncompressed;
152 *uncompressedSize_p = uncompressedSize;
153 return 0;
157 void jambaseUnpack (void) {
158 if (jambase == NULL) {
159 char *txt;
160 size_t len, pos;
161 int linecount = 1, linenum = 0;
163 if (lzUncompress((void *)jambasepk, &txt, &len) != 0) {
164 fprintf(stderr, "FATAL: decompression error!\n");
165 exit(1);
168 //fprintf(stderr, "len=%u\n", len);
169 //fprintf(stderr, "%s\n", txt);
170 for (size_t f = 0; f < len; ++f) if (txt[f] == '\n') ++linecount;
171 //fprintf(stderr, "lc=%d\n", linecount);
173 jambase = (char **)calloc(linecount, sizeof(char *));
174 pos = 0;
175 while (pos < len) {
176 char *e = txt+len, ec;
177 size_t epos = len;
179 for (size_t f = pos; f < len; ++f) {
180 if (txt[f] == '\n') { e = txt+f+1; epos = f+1; break; }
183 ec = *e;
184 *e = 0;
185 //fprintf(stderr, "%d: %s", linenum, txt+pos);
186 jambase[linenum++] = strdup(txt+pos);
187 *e = ec;
188 pos = epos;
190 free(txt);
192 //fprintf(stderr, "lc=%d; ln=%d\n", linecount, linenum);
193 //fprintf(stderr, "::%s", jambase[0]);