1 ////////////////////////////////////////////////////////////////////////////////
2 // decompression code license (ONLY decompression code)
4 // Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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
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.
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
) {
101 int networkOrder
, length
;
103 id
= data
[(*byteOffset
)++];
104 if (id
< 252) return id
;
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
;
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
);
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
);
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
;
157 void jambaseUnpack (void) {
158 if (jambase
== NULL
) {
161 int linecount
= 1, linenum
= 0;
163 if (lzUncompress((void *)jambasepk
, &txt
, &len
) != 0) {
164 fprintf(stderr
, "FATAL: decompression error!\n");
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 *));
176 char *e
= txt
+len
, ec
;
179 for (size_t f
= pos
; f
< len
; ++f
) {
180 if (txt
[f
] == '\n') { e
= txt
+f
+1; epos
= f
+1; break; }
185 //fprintf(stderr, "%d: %s", linenum, txt+pos);
186 jambase
[linenum
++] = strdup(txt
+pos
);
192 //fprintf(stderr, "lc=%d; ln=%d\n", linecount, linenum);
193 //fprintf(stderr, "::%s", jambase[0]);