annotate ezBAMQC/src/htslib/cram/cram_codecs.c @ 0:dfa3745e5fd8

Uploaded
author youngkim
date Thu, 24 Mar 2016 17:12:52 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
2 Copyright (c) 2012-2013 Genome Research Ltd.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
3 Author: James Bonfield <jkb@sanger.ac.uk>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
4
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
5 Redistribution and use in source and binary forms, with or without
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
6 modification, are permitted provided that the following conditions are met:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
7
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
8 1. Redistributions of source code must retain the above copyright notice,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
9 this list of conditions and the following disclaimer.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
10
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
11 2. Redistributions in binary form must reproduce the above copyright notice,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
12 this list of conditions and the following disclaimer in the documentation
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
13 and/or other materials provided with the distribution.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
14
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
15 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
16 Institute nor the names of its contributors may be used to endorse or promote
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
17 products derived from this software without specific prior written permission.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
18
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
19 THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
22 DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
29 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
30
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
31 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
32 * FIXME: add checking of cram_external_type to return NULL on unsupported
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
33 * {codec,type} tuples.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
34 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
35
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
36 #ifdef HAVE_CONFIG_H
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
37 #include "io_lib_config.h"
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
38 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
39
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
40 #include <stdlib.h>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
41 #include <string.h>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
42 #include <assert.h>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
43 #include <limits.h>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
44
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
45 #include "cram/cram.h"
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
46
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
47 static char *codec2str(enum cram_encoding codec) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
48 switch (codec) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
49 case E_NULL: return "NULL";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
50 case E_EXTERNAL: return "EXTERNAL";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
51 case E_GOLOMB: return "GOLOMB";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
52 case E_HUFFMAN: return "HUFFMAN";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
53 case E_BYTE_ARRAY_LEN: return "BYTE_ARRAY_LEN";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
54 case E_BYTE_ARRAY_STOP: return "BYTE_ARRAY_STOP";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
55 case E_BETA: return "BETA";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
56 case E_SUBEXP: return "SUBEXP";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
57 case E_GOLOMB_RICE: return "GOLOMB_RICE";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
58 case E_GAMMA: return "GAMMA";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
59 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
60
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
61 return "(unknown)";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
62 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
63
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
64 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
65 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
66 * Block bit-level I/O functions.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
67 * All defined static here to promote easy inlining by the compiler.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
68 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
69
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
70 #if 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
71 /* Get a single bit, MSB first */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
72 static signed int get_bit_MSB(cram_block *block) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
73 unsigned int val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
74
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
75 if (block->byte > block->alloc)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
76 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
77
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
78 val = block->data[block->byte] >> block->bit;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
79 if (--block->bit == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
80 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
81 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
82 //printf("(%02X)", block->data[block->byte]);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
83 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
84
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
85 //printf("-B%d-", val&1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
86
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
87 return val & 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
88 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
89 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
90
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
91 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
92 * Count number of successive 0 and 1 bits
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
93 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
94 static int get_one_bits_MSB(cram_block *block) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
95 int n = 0, b;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
96 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
97 b = block->data[block->byte] >> block->bit;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
98 if (--block->bit == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
99 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
100 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
101 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
102 n++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
103 } while (b&1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
104
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
105 return n-1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
106 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
107
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
108 static int get_zero_bits_MSB(cram_block *block) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
109 int n = 0, b;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
110 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
111 b = block->data[block->byte] >> block->bit;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
112 if (--block->bit == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
113 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
114 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
115 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
116 n++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
117 } while (!(b&1));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
118
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
119 return n-1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
120 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
121
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
122 #if 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
123 /* Stores a single bit */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
124 static void store_bit_MSB(cram_block *block, unsigned int bit) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
125 if (block->byte >= block->alloc) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
126 block->alloc = block->alloc ? block->alloc*2 : 1024;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
127 block->data = realloc(block->data, block->alloc);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
128 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
129
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
130 if (bit)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
131 block->data[block->byte] |= (1 << block->bit);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
132
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
133 if (--block->bit == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
134 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
135 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
136 block->data[block->byte] = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
137 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
138 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
139 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
140
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
141 #if 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
142 /* Rounds to the next whole byte boundary first */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
143 static void store_bytes_MSB(cram_block *block, char *bytes, int len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
144 if (block->bit != 7) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
145 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
146 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
147 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
148
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
149 while (block->byte + len >= block->alloc) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
150 block->alloc = block->alloc ? block->alloc*2 : 1024;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
151 block->data = realloc(block->data, block->alloc);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
152 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
153
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
154 memcpy(&block->data[block->byte], bytes, len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
155 block->byte += len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
156 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
157 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
158
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
159 /* Local optimised copy for inlining */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
160 static inline unsigned int get_bits_MSB(cram_block *block, int nbits) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
161 unsigned int val = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
162 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
163
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
164 #if 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
165 // Fits within the current byte */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
166 if (nbits <= block->bit+1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
167 val = (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
168 if ((block->bit -= nbits) == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
169 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
170 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
171 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
172 return val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
173 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
174
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
175 // partial first byte
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
176 val = block->data[block->byte] & ((1<<(block->bit+1))-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
177 nbits -= block->bit+1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
178 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
179 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
180
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
181 // whole middle bytes
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
182 while (nbits >= 8) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
183 val = (val << 8) | block->data[block->byte++];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
184 nbits -= 8;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
185 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
186
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
187 val <<= nbits;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
188 val |= (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
189 block->bit -= nbits;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
190 return val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
191 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
192
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
193 #if 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
194 /* Inefficient implementation! */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
195 //printf("{");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
196 for (i = 0; i < nbits; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
197 //val = (val << 1) | get_bit_MSB(block);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
198 GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
199 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
200
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
201 #if 1
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
202 /* Combination of 1st two methods */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
203 if (nbits <= block->bit+1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
204 val = (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
205 if ((block->bit -= nbits) == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
206 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
207 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
208 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
209 return val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
210 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
211
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
212 switch(nbits) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
213 // case 15: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
214 // case 14: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
215 // case 13: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
216 // case 12: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
217 // case 11: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
218 // case 10: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
219 // case 9: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
220 case 8: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
221 case 7: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
222 case 6: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
223 case 5: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
224 case 4: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
225 case 3: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
226 case 2: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
227 case 1: GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
228 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
229
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
230 default:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
231 for (i = 0; i < nbits; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
232 //val = (val << 1) | get_bit_MSB(block);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
233 GET_BIT_MSB(block, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
234 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
235 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
236
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
237 //printf("=0x%x}", val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
238
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
239 return val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
240 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
241
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
242 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
243 * Can store up to 24-bits worth of data encoded in an integer value
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
244 * Possibly we'd want to have a less optimal store_bits function when dealing
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
245 * with nbits > 24, but for now we assume the codes generated are never
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
246 * that big. (Given this is only possible with 121392 or more
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
247 * characters with exactly the correct frequency distribution we check
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
248 * for it elsewhere.)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
249 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
250 static int store_bits_MSB(cram_block *block, unsigned int val, int nbits) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
251 /* fprintf(stderr, " store_bits: %02x %d\n", val, nbits); */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
252
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
253 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
254 * Use slow mode until we tweak the huffman generator to never generate
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
255 * codes longer than 24-bits.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
256 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
257 unsigned int mask;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
258
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
259 if (block->byte+4 >= block->alloc) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
260 if (block->byte) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
261 block->alloc *= 2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
262 block->data = realloc(block->data, block->alloc + 4);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
263 if (!block->data)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
264 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
265 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
266 block->alloc = 1024;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
267 block->data = realloc(block->data, block->alloc + 4);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
268 if (!block->data)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
269 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
270 block->data[0] = 0; // initialise first byte of buffer
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
271 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
272 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
273
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
274 /* fits in current bit-field */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
275 if (nbits <= block->bit+1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
276 block->data[block->byte] |= (val << (block->bit+1-nbits));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
277 if ((block->bit-=nbits) == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
278 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
279 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
280 block->data[block->byte] = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
281 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
282 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
283 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
284
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
285 block->data[block->byte] |= (val >> (nbits -= block->bit+1));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
286 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
287 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
288 block->data[block->byte] = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
289
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
290 mask = 1<<(nbits-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
291 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
292 if (val & mask)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
293 block->data[block->byte] |= (1 << block->bit);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
294 if (--block->bit == -1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
295 block->bit = 7;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
296 block->byte++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
297 block->data[block->byte] = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
298 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
299 mask >>= 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
300 } while(--nbits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
301
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
302 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
303 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
304
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
305 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
306 * Returns the next 'size' bytes from a block, or NULL if insufficient
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
307 * data left.This is just a pointer into the block data and not an
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
308 * allocated object, so do not free the result.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
309 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
310 static char *cram_extract_block(cram_block *b, int size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
311 char *cp = (char *)b->data + b->idx;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
312 b->idx += size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
313 if (b->idx > b->uncomp_size)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
314 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
315
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
316 return cp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
317 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
318
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
319 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
320 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
321 * EXTERNAL
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
322 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
323 int cram_external_decode_int(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
324 cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
325 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
326 char *cp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
327 cram_block *b = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
328
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
329 /* Find the external block */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
330 if (slice->block_by_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
331 if (!(b = slice->block_by_id[c->external.content_id]))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
332 return *out_size?-1:0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
333 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
334 for (i = 0; i < slice->hdr->num_blocks; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
335 b = slice->block[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
336 if (b && b->content_type == EXTERNAL &&
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
337 b->content_id == c->external.content_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
338 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
339 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
340 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
341 if (i == slice->hdr->num_blocks || !b)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
342 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
343 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
344
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
345 cp = (char *)b->data + b->idx;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
346 // E_INT and E_LONG are guaranteed single item queries
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
347 b->idx += itf8_get(cp, (int32_t *)out);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
348 *out_size = 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
349
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
350 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
351 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
352
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
353 int cram_external_decode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
354 cram_block *in, char *out,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
355 int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
356 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
357 char *cp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
358 cram_block *b = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
359
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
360 /* Find the external block */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
361 if (slice->block_by_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
362 if (!(b = slice->block_by_id[c->external.content_id]))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
363 return *out_size?-1:0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
364 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
365 for (i = 0; i < slice->hdr->num_blocks; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
366 b = slice->block[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
367 if (b && b->content_type == EXTERNAL &&
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
368 b->content_id == c->external.content_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
369 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
370 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
371 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
372 if (i == slice->hdr->num_blocks || !b)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
373 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
374 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
375
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
376 cp = cram_extract_block(b, *out_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
377 if (!cp)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
378 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
379
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
380 memcpy(out, cp, *out_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
381 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
382 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
383
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
384 static int cram_external_decode_block(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
385 cram_block *in, char *out_,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
386 int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
387 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
388 char *cp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
389 cram_block *b = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
390 cram_block *out = (cram_block *)out_;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
391
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
392 /* Find the external block */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
393 if (slice->block_by_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
394 if (!(b = slice->block_by_id[c->external.content_id]))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
395 return *out_size?-1:0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
396 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
397 for (i = 0; i < slice->hdr->num_blocks; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
398 b = slice->block[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
399 if (b && b->content_type == EXTERNAL &&
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
400 b->content_id == c->external.content_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
401 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
402 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
403 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
404 if (i == slice->hdr->num_blocks || !b)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
405 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
406 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
407
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
408 cp = cram_extract_block(b, *out_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
409 if (!cp)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
410 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
411
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
412 BLOCK_APPEND(out, cp, *out_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
413 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
414 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
415
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
416 void cram_external_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
417 if (c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
418 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
419 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
420
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
421 cram_codec *cram_external_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
422 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
423 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
424 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
425 char *cp = data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
426
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
427 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
428 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
429
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
430 c->codec = E_EXTERNAL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
431 if (option == E_INT || option == E_LONG)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
432 c->decode = cram_external_decode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
433 else if (option == E_BYTE_ARRAY || option == E_BYTE)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
434 c->decode = cram_external_decode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
435 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
436 c->decode = cram_external_decode_block;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
437 c->free = cram_external_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
438
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
439 cp += itf8_get(cp, &c->external.content_id);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
440
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
441 if (cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
442 fprintf(stderr, "Malformed external header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
443 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
444 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
445 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
446
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
447 c->external.type = option;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
448
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
449 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
450 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
451
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
452 int cram_external_encode_int(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
453 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
454 uint32_t *i32 = (uint32_t *)in;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
455
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
456 itf8_put_blk(c->out, *i32);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
457 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
458 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
459
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
460 int cram_external_encode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
461 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
462 BLOCK_APPEND(c->out, in, in_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
463 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
464 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
465
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
466 void cram_external_encode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
467 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
468 return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
469 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
470 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
471
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
472 int cram_external_encode_store(cram_codec *c, cram_block *b, char *prefix,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
473 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
474 char tmp[99], *tp = tmp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
475 int len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
476
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
477 if (prefix) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
478 size_t l = strlen(prefix);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
479 BLOCK_APPEND(b, prefix, l);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
480 len += l;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
481 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
482
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
483 tp += itf8_put(tp, c->e_external.content_id);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
484 len += itf8_put_blk(b, c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
485 len += itf8_put_blk(b, tp-tmp);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
486 BLOCK_APPEND(b, tmp, tp-tmp);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
487 len += tp-tmp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
488
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
489 return len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
490 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
491
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
492 cram_codec *cram_external_encode_init(cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
493 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
494 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
495 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
496 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
497
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
498 c = malloc(sizeof(*c));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
499 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
500 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
501 c->codec = E_EXTERNAL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
502 c->free = cram_external_encode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
503 if (option == E_INT || option == E_LONG)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
504 c->encode = cram_external_encode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
505 else if (option == E_BYTE_ARRAY || option == E_BYTE)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
506 c->encode = cram_external_encode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
507 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
508 abort();
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
509 c->store = cram_external_encode_store;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
510
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
511 c->e_external.content_id = (size_t)dat;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
512
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
513 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
514 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
515
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
516 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
517 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
518 * BETA
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
519 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
520 int cram_beta_decode_int(cram_slice *slice, cram_codec *c, cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
521 int32_t *out_i = (int32_t *)out;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
522 int i, n;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
523
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
524 if (c->beta.nbits) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
525 for (i = 0, n = *out_size; i < n; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
526 out_i[i] = get_bits_MSB(in, c->beta.nbits) - c->beta.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
527 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
528 for (i = 0, n = *out_size; i < n; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
529 out_i[i] = -c->beta.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
530 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
531
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
532 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
533 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
534
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
535 int cram_beta_decode_char(cram_slice *slice, cram_codec *c, cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
536 int i, n;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
537
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
538 if (c->beta.nbits) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
539 for (i = 0, n = *out_size; i < n; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
540 out[i] = get_bits_MSB(in, c->beta.nbits) - c->beta.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
541 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
542 for (i = 0, n = *out_size; i < n; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
543 out[i] = -c->beta.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
544 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
545
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
546 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
547 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
548
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
549 void cram_beta_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
550 if (c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
551 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
552 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
553
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
554 cram_codec *cram_beta_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
555 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
556 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
557 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
558 char *cp = data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
559
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
560 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
561 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
562
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
563 c->codec = E_BETA;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
564 if (option == E_INT || option == E_LONG)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
565 c->decode = cram_beta_decode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
566 else if (option == E_BYTE_ARRAY || option == E_BYTE)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
567 c->decode = cram_beta_decode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
568 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
569 abort();
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
570 c->free = cram_beta_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
571
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
572 cp += itf8_get(cp, &c->beta.offset);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
573 cp += itf8_get(cp, &c->beta.nbits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
574
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
575 if (cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
576 fprintf(stderr, "Malformed beta header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
577 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
578 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
579 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
580
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
581 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
582 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
583
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
584 int cram_beta_encode_store(cram_codec *c, cram_block *b,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
585 char *prefix, int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
586 int len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
587
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
588 if (prefix) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
589 size_t l = strlen(prefix);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
590 BLOCK_APPEND(b, prefix, l);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
591 len += l;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
592 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
593
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
594 len += itf8_put_blk(b, c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
595 len += itf8_put_blk(b, itf8_size(c->e_beta.offset)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
596 + itf8_size(c->e_beta.nbits)); // codec length
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
597 len += itf8_put_blk(b, c->e_beta.offset);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
598 len += itf8_put_blk(b, c->e_beta.nbits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
599
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
600 return len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
601 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
602
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
603 int cram_beta_encode_int(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
604 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
605 int *syms = (int *)in;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
606 int i, r = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
607
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
608 for (i = 0; i < in_size; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
609 r |= store_bits_MSB(c->out, syms[i] + c->e_beta.offset,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
610 c->e_beta.nbits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
611
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
612 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
613 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
614
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
615 int cram_beta_encode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
616 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
617 unsigned char *syms = (unsigned char *)in;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
618 int i, r = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
619
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
620 for (i = 0; i < in_size; i++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
621 r |= store_bits_MSB(c->out, syms[i] + c->e_beta.offset,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
622 c->e_beta.nbits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
623
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
624 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
625 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
626
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
627 void cram_beta_encode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
628 if (c) free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
629 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
630
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
631 cram_codec *cram_beta_encode_init(cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
632 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
633 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
634 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
635 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
636 int min_val, max_val, len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
637
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
638 c = malloc(sizeof(*c));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
639 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
640 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
641 c->codec = E_BETA;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
642 c->free = cram_beta_encode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
643 if (option == E_INT)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
644 c->encode = cram_beta_encode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
645 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
646 c->encode = cram_beta_encode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
647 c->store = cram_beta_encode_store;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
648
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
649 if (dat) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
650 min_val = ((int *)dat)[0];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
651 max_val = ((int *)dat)[1];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
652 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
653 min_val = INT_MAX;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
654 max_val = INT_MIN;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
655 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
656 for (i = 0; i < MAX_STAT_VAL; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
657 if (!st->freqs[i])
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
658 continue;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
659 if (min_val > i)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
660 min_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
661 max_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
662 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
663 if (st->h) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
664 khint_t k;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
665
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
666 for (k = kh_begin(st->h); k != kh_end(st->h); k++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
667 if (!kh_exist(st->h, k))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
668 continue;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
669
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
670 i = kh_key(st->h, k);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
671 if (min_val > i)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
672 min_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
673 if (max_val < i)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
674 max_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
675 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
676 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
677 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
678
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
679 assert(max_val >= min_val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
680 c->e_beta.offset = -min_val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
681 max_val -= min_val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
682 while (max_val) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
683 len++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
684 max_val >>= 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
685 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
686 c->e_beta.nbits = len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
687
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
688 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
689 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
690
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
691 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
692 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
693 * SUBEXP
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
694 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
695 int cram_subexp_decode(cram_slice *slice, cram_codec *c, cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
696 int32_t *out_i = (int32_t *)out;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
697 int n, count;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
698 int k = c->subexp.k;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
699
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
700 for (count = 0, n = *out_size; count < n; count++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
701 int i = 0, tail;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
702 int val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
703
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
704 /* Get number of 1s */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
705 //while (get_bit_MSB(in) == 1) i++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
706 i = get_one_bits_MSB(in);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
707
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
708 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
709 * Val is
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
710 * i > 0: 2^(k+i-1) + k+i-1 bits
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
711 * i = 0: k bits
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
712 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
713 if (i) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
714 tail = i + k-1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
715 val = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
716 while (tail) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
717 //val = val<<1; val |= get_bit_MSB(in);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
718 GET_BIT_MSB(in, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
719 tail--;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
720 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
721 val += 1 << (i + k-1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
722 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
723 tail = k;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
724 val = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
725 while (tail) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
726 //val = val<<1; val |= get_bit_MSB(in);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
727 GET_BIT_MSB(in, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
728 tail--;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
729 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
730 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
731
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
732 out_i[count] = val - c->subexp.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
733 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
734
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
735 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
736 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
737
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
738 void cram_subexp_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
739 if (c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
740 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
741 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
742
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
743 cram_codec *cram_subexp_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
744 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
745 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
746 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
747 char *cp = data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
748
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
749 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
750 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
751
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
752 c->codec = E_SUBEXP;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
753 c->decode = cram_subexp_decode;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
754 c->free = cram_subexp_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
755
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
756 cp += itf8_get(cp, &c->subexp.offset);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
757 cp += itf8_get(cp, &c->subexp.k);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
758
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
759 if (cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
760 fprintf(stderr, "Malformed subexp header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
761 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
762 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
763 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
764
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
765 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
766 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
767
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
768 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
769 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
770 * GAMMA
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
771 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
772 int cram_gamma_decode(cram_slice *slice, cram_codec *c, cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
773 int32_t *out_i = (int32_t *)out;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
774 int i, n;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
775
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
776 for (i = 0, n = *out_size; i < n; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
777 int nz = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
778 int val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
779 //while (get_bit_MSB(in) == 0) nz++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
780 nz = get_zero_bits_MSB(in);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
781 val = 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
782 while (nz > 0) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
783 //val <<= 1; val |= get_bit_MSB(in);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
784 GET_BIT_MSB(in, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
785 nz--;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
786 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
787
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
788 out_i[i] = val - c->gamma.offset;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
789 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
790
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
791 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
792 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
793
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
794 void cram_gamma_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
795 if (c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
796 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
797 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
798
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
799 cram_codec *cram_gamma_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
800 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
801 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
802 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
803 char *cp = data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
804
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
805 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
806 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
807
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
808 c->codec = E_GAMMA;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
809 c->decode = cram_gamma_decode;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
810 c->free = cram_gamma_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
811
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
812 cp += itf8_get(cp, &c->gamma.offset);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
813
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
814 if (cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
815 fprintf(stderr, "Malformed gamma header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
816 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
817 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
818 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
819
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
820 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
821 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
822
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
823 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
824 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
825 * HUFFMAN
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
826 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
827
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
828 static int code_sort(const void *vp1, const void *vp2) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
829 const cram_huffman_code *c1 = (const cram_huffman_code *)vp1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
830 const cram_huffman_code *c2 = (const cram_huffman_code *)vp2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
831
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
832 if (c1->len != c2->len)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
833 return c1->len - c2->len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
834 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
835 return c1->symbol - c2->symbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
836 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
837
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
838 void cram_huffman_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
839 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
840 return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
841
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
842 if (c->huffman.codes)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
843 free(c->huffman.codes);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
844 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
845 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
846
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
847 int cram_huffman_decode_char0(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
848 cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
849 int i, n;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
850
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
851 /* Special case of 0 length codes */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
852 for (i = 0, n = *out_size; i < n; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
853 out[i] = c->huffman.codes[0].symbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
854 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
855 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
856 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
857
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
858 int cram_huffman_decode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
859 cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
860 int i, n, ncodes = c->huffman.ncodes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
861 const cram_huffman_code * const codes = c->huffman.codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
862
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
863 for (i = 0, n = *out_size; i < n; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
864 int idx = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
865 int val = 0, len = 0, last_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
866
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
867 for (;;) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
868 int dlen = codes[idx].len - last_len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
869 if (dlen <= 0 || (in->alloc - in->byte)*8 + in->bit + 7 < dlen)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
870 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
871
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
872 //val <<= dlen;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
873 //val |= get_bits_MSB(in, dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
874 //last_len = (len += dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
875
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
876 last_len = (len += dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
877 for (; dlen; dlen--) GET_BIT_MSB(in, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
878
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
879 idx = val - codes[idx].p;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
880 if (idx >= ncodes || idx < 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
881 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
882
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
883 if (codes[idx].code == val && codes[idx].len == len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
884 out[i] = codes[idx].symbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
885 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
886 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
887 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
888 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
889
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
890 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
891 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
892
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
893 int cram_huffman_decode_int0(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
894 cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
895 int32_t *out_i = (int32_t *)out;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
896 int i, n;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
897 const cram_huffman_code * const codes = c->huffman.codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
898
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
899 /* Special case of 0 length codes */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
900 for (i = 0, n = *out_size; i < n; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
901 out_i[i] = codes[0].symbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
902 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
903 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
904 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
905
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
906 int cram_huffman_decode_int(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
907 cram_block *in, char *out, int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
908 int32_t *out_i = (int32_t *)out;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
909 int i, n, ncodes = c->huffman.ncodes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
910 const cram_huffman_code * const codes = c->huffman.codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
911
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
912 for (i = 0, n = *out_size; i < n; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
913 int idx = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
914 int val = 0, len = 0, last_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
915
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
916 // Now one bit at a time for remaining checks
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
917 for (;;) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
918 int dlen = codes[idx].len - last_len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
919 if (dlen <= 0 || (in->alloc - in->byte)*8 + in->bit + 7 < dlen)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
920 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
921
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
922 //val <<= dlen;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
923 //val |= get_bits_MSB(in, dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
924 //last_len = (len += dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
925
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
926 last_len = (len += dlen);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
927 for (; dlen; dlen--) GET_BIT_MSB(in, val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
928
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
929 idx = val - codes[idx].p;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
930 if (idx >= ncodes || idx < 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
931 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
932
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
933 if (codes[idx].code == val && codes[idx].len == len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
934 out_i[i] = codes[idx].symbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
935 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
936 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
937 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
938 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
939
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
940 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
941 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
942
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
943 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
944 * Initialises a huffman decoder from an encoding data stream.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
945 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
946 cram_codec *cram_huffman_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
947 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
948 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
949 int32_t ncodes, i, j;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
950 char *cp = data, *data_end = &data[size];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
951 cram_codec *h;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
952 cram_huffman_code *codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
953 int32_t val, last_len, max_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
954
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
955 cp += itf8_get(cp, &ncodes);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
956 h = calloc(1, sizeof(*h));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
957 if (!h)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
958 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
959
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
960 h->free = cram_huffman_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
961
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
962 h->huffman.ncodes = ncodes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
963 codes = h->huffman.codes = malloc(ncodes * sizeof(*codes));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
964 if (!codes) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
965 free(h);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
966 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
967 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
968
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
969 /* Read symbols and bit-lengths */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
970 for (i = 0; i < ncodes && cp < data_end; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
971 cp += itf8_get(cp, &codes[i].symbol);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
972 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
973
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
974 if (cp >= data_end) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
975 fprintf(stderr, "Malformed huffman header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
976 free(h);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
977 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
978 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
979 cp += itf8_get(cp, &i);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
980 if (i != ncodes) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
981 fprintf(stderr, "Malformed huffman header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
982 free(h);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
983 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
984 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
985
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
986 if (ncodes == 0) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
987 /* NULL huffman stream */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
988 return h;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
989 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
990
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
991 for (i = 0; i < ncodes && cp < data_end; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
992 cp += itf8_get(cp, &codes[i].len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
993 if (max_len < codes[i].len)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
994 max_len = codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
995 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
996 if (cp - data != size || max_len >= ncodes) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
997 fprintf(stderr, "Malformed huffman header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
998 free(h);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
999 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1000 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1001
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1002 /* Sort by bit length and then by symbol value */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1003 qsort(codes, ncodes, sizeof(*codes), code_sort);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1004
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1005 /* Assign canonical codes */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1006 val = -1, last_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1007 for (i = 0; i < ncodes; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1008 val++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1009 if (codes[i].len > last_len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1010 while (codes[i].len > last_len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1011 val <<= 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1012 last_len++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1013 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1014 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1015 codes[i].code = val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1016 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1017
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1018 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1019 * Compute the next starting point, offset by the i'th value.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1020 * For example if codes 10, 11, 12, 13 are 30, 31, 32, 33 then
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1021 * codes[10..13].p = 30 - 10.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1022 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1023 last_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1024 for (i = j = 0; i < ncodes; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1025 if (codes[i].len > last_len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1026 j = codes[i].code - i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1027 last_len = codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1028 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1029 codes[i].p = j;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1030 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1031
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1032 // puts("==HUFF LEN==");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1033 // for (i = 0; i <= last_len+1; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1034 // printf("len %d=%d prefix %d\n", i, h->huffman.lengths[i], h->huffman.prefix[i]);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1035 // }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1036 // puts("===HUFFMAN CODES===");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1037 // for (i = 0; i < ncodes; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1038 // int j;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1039 // printf("%d: %d %d %d ", i, codes[i].symbol, codes[i].len, codes[i].code);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1040 // j = codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1041 // while (j) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1042 // putchar(codes[i].code & (1 << --j) ? '1' : '0');
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1043 // }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1044 // printf(" %d\n", codes[i].code);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1045 // }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1046
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1047 h->codec = E_HUFFMAN;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1048 if (option == E_BYTE || option == E_BYTE_ARRAY) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1049 if (h->huffman.codes[0].len == 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1050 h->decode = cram_huffman_decode_char0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1051 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1052 h->decode = cram_huffman_decode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1053 } else if (option == E_BYTE_ARRAY_BLOCK) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1054 abort();
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1055 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1056 if (h->huffman.codes[0].len == 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1057 h->decode = cram_huffman_decode_int0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1058 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1059 h->decode = cram_huffman_decode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1060 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1061
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1062 return (cram_codec *)h;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1063 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1064
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1065 int cram_huffman_encode_char0(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1066 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1067 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1068 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1069
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1070 int cram_huffman_encode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1071 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1072 int i, code, len, r = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1073 unsigned char *syms = (unsigned char *)in;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1074
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1075 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1076 int sym = *syms++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1077 if (sym >= -1 && sym < MAX_HUFF) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1078 i = c->e_huffman.val2code[sym+1];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1079 assert(c->e_huffman.codes[i].symbol == sym);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1080 code = c->e_huffman.codes[i].code;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1081 len = c->e_huffman.codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1082 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1083 /* Slow - use a lookup table for when sym < MAX_HUFF? */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1084 for (i = 0; i < c->e_huffman.nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1085 if (c->e_huffman.codes[i].symbol == sym)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1086 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1087 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1088 if (i == c->e_huffman.nvals)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1089 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1090
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1091 code = c->e_huffman.codes[i].code;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1092 len = c->e_huffman.codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1093 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1094
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1095 r |= store_bits_MSB(c->out, code, len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1096 } while (--in_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1097
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1098 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1099 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1100
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1101 int cram_huffman_encode_int0(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1102 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1103 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1104 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1105
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1106 int cram_huffman_encode_int(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1107 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1108 int i, code, len, r = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1109 int *syms = (int *)in;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1110
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1111 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1112 int sym = *syms++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1113
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1114 if (sym >= -1 && sym < MAX_HUFF) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1115 i = c->e_huffman.val2code[sym+1];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1116 assert(c->e_huffman.codes[i].symbol == sym);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1117 code = c->e_huffman.codes[i].code;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1118 len = c->e_huffman.codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1119 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1120 /* Slow - use a lookup table for when sym < MAX_HUFFMAN_SYM? */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1121 for (i = 0; i < c->e_huffman.nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1122 if (c->e_huffman.codes[i].symbol == sym)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1123 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1124 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1125 if (i == c->e_huffman.nvals)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1126 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1127
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1128 code = c->e_huffman.codes[i].code;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1129 len = c->e_huffman.codes[i].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1130 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1131
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1132 r |= store_bits_MSB(c->out, code, len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1133 } while (--in_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1134
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1135 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1136 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1137
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1138 void cram_huffman_encode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1139 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1140 return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1141
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1142 if (c->e_huffman.codes)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1143 free(c->e_huffman.codes);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1144 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1145 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1146
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1147 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1148 * Encodes a huffman tree.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1149 * Returns number of bytes written.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1150 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1151 int cram_huffman_encode_store(cram_codec *c, cram_block *b, char *prefix,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1152 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1153 int i, len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1154 cram_huffman_code *codes = c->e_huffman.codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1155 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1156 * Up to code length 127 means 2.5e+26 bytes of data required (worst
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1157 * case huffman tree needs symbols with freqs matching the Fibonacci
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1158 * series). So guaranteed 1 byte per code.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1159 *
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1160 * Symbols themselves could be 5 bytes (eg -1 is 5 bytes in itf8).
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1161 *
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1162 * Therefore 6*ncodes + 5 + 5 + 1 + 5 is max memory
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1163 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1164 char *tmp = malloc(6*c->e_huffman.nvals+16);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1165 char *tp = tmp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1166
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1167 if (!tmp)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1168 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1169
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1170 if (prefix) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1171 size_t l = strlen(prefix);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1172 BLOCK_APPEND(b, prefix, l);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1173 len += l;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1174 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1175
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1176 tp += itf8_put(tp, c->e_huffman.nvals);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1177 for (i = 0; i < c->e_huffman.nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1178 tp += itf8_put(tp, codes[i].symbol);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1179 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1180
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1181 tp += itf8_put(tp, c->e_huffman.nvals);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1182 for (i = 0; i < c->e_huffman.nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1183 tp += itf8_put(tp, codes[i].len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1184 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1185
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1186 len += itf8_put_blk(b, c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1187 len += itf8_put_blk(b, tp-tmp);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1188 BLOCK_APPEND(b, tmp, tp-tmp);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1189 len += tp-tmp;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1190
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1191 free(tmp);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1192
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1193 return len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1194 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1195
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1196 cram_codec *cram_huffman_encode_init(cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1197 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1198 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1199 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1200 int *vals = NULL, *freqs = NULL, vals_alloc = 0, *lens, code, len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1201 int nvals, i, ntot = 0, max_val = 0, min_val = INT_MAX, k;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1202 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1203 cram_huffman_code *codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1204
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1205 c = malloc(sizeof(*c));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1206 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1207 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1208 c->codec = E_HUFFMAN;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1209
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1210 /* Count number of unique symbols */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1211 for (nvals = i = 0; i < MAX_STAT_VAL; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1212 if (!st->freqs[i])
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1213 continue;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1214 if (nvals >= vals_alloc) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1215 vals_alloc = vals_alloc ? vals_alloc*2 : 1024;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1216 vals = realloc(vals, vals_alloc * sizeof(int));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1217 freqs = realloc(freqs, vals_alloc * sizeof(int));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1218 if (!vals || !freqs) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1219 if (vals) free(vals);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1220 if (freqs) free(freqs);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1221 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1222 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1223 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1224 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1225 vals[nvals] = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1226 freqs[nvals] = st->freqs[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1227 assert(st->freqs[i] > 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1228 ntot += freqs[nvals];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1229 if (max_val < i) max_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1230 if (min_val > i) min_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1231 nvals++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1232 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1233 if (st->h) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1234 khint_t k;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1235
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1236 for (k = kh_begin(st->h); k != kh_end(st->h); k++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1237 if (!kh_exist(st->h, k))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1238 continue;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1239 if (nvals >= vals_alloc) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1240 vals_alloc = vals_alloc ? vals_alloc*2 : 1024;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1241 vals = realloc(vals, vals_alloc * sizeof(int));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1242 freqs = realloc(freqs, vals_alloc * sizeof(int));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1243 if (!vals || !freqs)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1244 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1245 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1246 vals[nvals]= kh_key(st->h, k);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1247 freqs[nvals] = kh_val(st->h, k);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1248 assert(freqs[nvals] > 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1249 ntot += freqs[nvals];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1250 if (max_val < i) max_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1251 if (min_val > i) min_val = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1252 nvals++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1253 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1254 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1255
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1256 assert(nvals > 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1257
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1258 freqs = realloc(freqs, 2*nvals*sizeof(*freqs));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1259 lens = calloc(2*nvals, sizeof(*lens));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1260 if (!lens || !freqs)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1261 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1262
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1263 /* Inefficient, use pointers to form chain so we can insert and maintain
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1264 * a sorted list? This is currently O(nvals^2) complexity.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1265 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1266 for (;;) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1267 int low1 = INT_MAX, low2 = INT_MAX;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1268 int ind1 = 0, ind2 = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1269 for (i = 0; i < nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1270 if (freqs[i] < 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1271 continue;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1272 if (low1 > freqs[i])
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1273 low2 = low1, ind2 = ind1, low1 = freqs[i], ind1 = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1274 else if (low2 > freqs[i])
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1275 low2 = freqs[i], ind2 = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1276 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1277 if (low2 == INT_MAX)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1278 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1279
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1280 freqs[nvals] = low1 + low2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1281 lens[ind1] = nvals;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1282 lens[ind2] = nvals;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1283 freqs[ind1] *= -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1284 freqs[ind2] *= -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1285 nvals++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1286 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1287 nvals = nvals/2+1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1288
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1289 /* Assign lengths */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1290 for (i = 0; i < nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1291 int code_len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1292 for (k = lens[i]; k; k = lens[k])
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1293 code_len++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1294 lens[i] = code_len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1295 freqs[i] *= -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1296 //fprintf(stderr, "%d / %d => %d\n", vals[i], freqs[i], lens[i]);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1297 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1298
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1299
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1300 /* Sort, need in a struct */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1301 if (!(codes = malloc(nvals * sizeof(*codes))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1302 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1303 for (i = 0; i < nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1304 codes[i].symbol = vals[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1305 codes[i].len = lens[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1306 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1307 qsort(codes, nvals, sizeof(*codes), code_sort);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1308
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1309 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1310 * Generate canonical codes from lengths.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1311 * Sort by length.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1312 * Start with 0.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1313 * Every new code of same length is +1.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1314 * Every new code of new length is +1 then <<1 per extra length.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1315 *
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1316 * /\
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1317 * a/\
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1318 * /\/\
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1319 * bcd/\
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1320 * ef
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1321 *
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1322 * a 1 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1323 * b 3 4 (0+1)<<2
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1324 * c 3 5
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1325 * d 3 6
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1326 * e 4 14 (6+1)<<1
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1327 * f 5 15
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1328 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1329 code = 0; len = codes[0].len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1330 for (i = 0; i < nvals; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1331 while (len != codes[i].len) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1332 code<<=1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1333 len++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1334 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1335 codes[i].code = code++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1336
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1337 if (codes[i].symbol >= -1 && codes[i].symbol < MAX_HUFF)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1338 c->e_huffman.val2code[codes[i].symbol+1] = i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1339
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1340 //fprintf(stderr, "sym %d, code %d, len %d\n",
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1341 // codes[i].symbol, codes[i].code, codes[i].len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1342 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1343
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1344 free(lens);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1345 free(vals);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1346 free(freqs);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1347
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1348 c->e_huffman.codes = codes;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1349 c->e_huffman.nvals = nvals;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1350
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1351 c->free = cram_huffman_encode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1352 if (option == E_BYTE || option == E_BYTE_ARRAY) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1353 if (c->e_huffman.codes[0].len == 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1354 c->encode = cram_huffman_encode_char0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1355 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1356 c->encode = cram_huffman_encode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1357 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1358 if (c->e_huffman.codes[0].len == 0)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1359 c->encode = cram_huffman_encode_int0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1360 else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1361 c->encode = cram_huffman_encode_int;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1362 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1363 c->store = cram_huffman_encode_store;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1364
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1365 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1366 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1367
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1368 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1369 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1370 * BYTE_ARRAY_LEN
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1371 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1372 int cram_byte_array_len_decode(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1373 cram_block *in, char *out,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1374 int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1375 /* Fetch length */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1376 int32_t len, one = 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1377
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1378 c->byte_array_len.len_codec->decode(slice, c->byte_array_len.len_codec, in, (char *)&len, &one);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1379 //printf("ByteArray Len=%d\n", len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1380
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1381 if (c->byte_array_len.value_codec) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1382 c->byte_array_len.value_codec->decode(slice,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1383 c->byte_array_len.value_codec,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1384 in, out, &len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1385 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1386 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1387 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1388
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1389 *out_size = len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1390
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1391 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1392 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1393
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1394 void cram_byte_array_len_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1395 if (!c) return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1396
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1397 if (c->byte_array_len.len_codec)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1398 c->byte_array_len.len_codec->free(c->byte_array_len.len_codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1399
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1400 if (c->byte_array_len.value_codec)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1401 c->byte_array_len.value_codec->free(c->byte_array_len.value_codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1402
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1403 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1404 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1405
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1406 cram_codec *cram_byte_array_len_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1407 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1408 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1409 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1410 char *cp = data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1411 int32_t encoding;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1412 int32_t sub_size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1413
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1414 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1415 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1416
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1417 c->codec = E_BYTE_ARRAY_LEN;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1418 c->decode = cram_byte_array_len_decode;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1419 c->free = cram_byte_array_len_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1420
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1421 cp += itf8_get(cp, &encoding);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1422 cp += itf8_get(cp, &sub_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1423 c->byte_array_len.len_codec = cram_decoder_init(encoding, cp, sub_size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1424 E_INT, version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1425 cp += sub_size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1426
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1427 cp += itf8_get(cp, &encoding);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1428 cp += itf8_get(cp, &sub_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1429 c->byte_array_len.value_codec = cram_decoder_init(encoding, cp, sub_size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1430 option, version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1431 cp += sub_size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1432
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1433 if (cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1434 fprintf(stderr, "Malformed byte_array_len header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1435 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1436 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1437 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1438
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1439 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1440 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1441
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1442 int cram_byte_array_len_encode(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1443 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1444 int32_t i32 = in_size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1445 int r = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1446
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1447 r |= c->e_byte_array_len.len_codec->encode(slice,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1448 c->e_byte_array_len.len_codec,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1449 (char *)&i32, 1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1450 r |= c->e_byte_array_len.val_codec->encode(slice,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1451 c->e_byte_array_len.val_codec,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1452 in, in_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1453 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1454 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1455
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1456 void cram_byte_array_len_encode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1457 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1458 return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1459
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1460 if (c->e_byte_array_len.len_codec)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1461 c->e_byte_array_len.len_codec->free(c->e_byte_array_len.len_codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1462
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1463 if (c->e_byte_array_len.val_codec)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1464 c->e_byte_array_len.val_codec->free(c->e_byte_array_len.val_codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1465
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1466 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1467 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1468
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1469 int cram_byte_array_len_encode_store(cram_codec *c, cram_block *b,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1470 char *prefix, int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1471 int len = 0, len2, len3;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1472 cram_codec *tc;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1473 cram_block *b_len, *b_val;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1474
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1475 if (prefix) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1476 size_t l = strlen(prefix);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1477 BLOCK_APPEND(b, prefix, l);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1478 len += l;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1479 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1480
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1481 tc = c->e_byte_array_len.len_codec;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1482 b_len = cram_new_block(0, 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1483 len2 = tc->store(tc, b_len, NULL, version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1484
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1485 tc = c->e_byte_array_len.val_codec;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1486 b_val = cram_new_block(0, 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1487 len3 = tc->store(tc, b_val, NULL, version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1488
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1489 len += itf8_put_blk(b, c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1490 len += itf8_put_blk(b, len2+len3);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1491 BLOCK_APPEND(b, BLOCK_DATA(b_len), BLOCK_SIZE(b_len));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1492 BLOCK_APPEND(b, BLOCK_DATA(b_val), BLOCK_SIZE(b_val));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1493
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1494 cram_free_block(b_len);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1495 cram_free_block(b_val);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1496
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1497 return len + len2 + len3;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1498 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1499
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1500 cram_codec *cram_byte_array_len_encode_init(cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1501 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1502 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1503 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1504 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1505 cram_byte_array_len_encoder *e = (cram_byte_array_len_encoder *)dat;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1506
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1507 c = malloc(sizeof(*c));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1508 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1509 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1510 c->codec = E_BYTE_ARRAY_LEN;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1511 c->free = cram_byte_array_len_encode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1512 c->encode = cram_byte_array_len_encode;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1513 c->store = cram_byte_array_len_encode_store;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1514
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1515 c->e_byte_array_len.len_codec = cram_encoder_init(e->len_encoding,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1516 NULL, E_INT,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1517 e->len_dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1518 version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1519 c->e_byte_array_len.val_codec = cram_encoder_init(e->val_encoding,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1520 NULL, E_BYTE_ARRAY,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1521 e->val_dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1522 version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1523
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1524 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1525 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1526
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1527 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1528 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1529 * BYTE_ARRAY_STOP
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1530 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1531 static int cram_byte_array_stop_decode_char(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1532 cram_block *in, char *out,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1533 int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1534 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1535 cram_block *b = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1536 char *cp, ch;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1537
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1538 if (slice->block_by_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1539 if (!(b = slice->block_by_id[c->byte_array_stop.content_id]))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1540 return *out_size?-1:0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1541 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1542 for (i = 0; i < slice->hdr->num_blocks; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1543 b = slice->block[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1544 if (b && b->content_type == EXTERNAL &&
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1545 b->content_id == c->byte_array_stop.content_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1546 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1547 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1548 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1549 if (i == slice->hdr->num_blocks || !b)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1550 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1551 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1552
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1553 if (b->idx >= b->uncomp_size)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1554 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1555
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1556 cp = (char *)b->data + b->idx;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1557 while ((ch = *cp) != (char)c->byte_array_stop.stop) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1558 if (cp - (char *)b->data >= b->uncomp_size)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1559 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1560 *out++ = ch;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1561 cp++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1562 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1563
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1564 *out_size = cp - (char *)(b->data + b->idx);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1565 b->idx = cp - (char *)b->data + 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1566
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1567 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1568 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1569
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1570 int cram_byte_array_stop_decode_block(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1571 cram_block *in, char *out_,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1572 int *out_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1573 cram_block *b = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1574 cram_block *out = (cram_block *)out_;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1575 char *cp, *out_cp, *cp_end;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1576 char stop;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1577
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1578 if (slice->block_by_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1579 if (!(b = slice->block_by_id[c->byte_array_stop.content_id]))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1580 return *out_size?-1:0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1581 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1582 int i;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1583 for (i = 0; i < slice->hdr->num_blocks; i++) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1584 b = slice->block[i];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1585 if (b && b->content_type == EXTERNAL &&
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1586 b->content_id == c->byte_array_stop.content_id) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1587 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1588 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1589 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1590 if (i == slice->hdr->num_blocks || !b)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1591 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1592 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1593
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1594 if (b->idx >= b->uncomp_size)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1595 return -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1596 cp = (char *)b->data + b->idx;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1597 cp_end = (char *)b->data + b->uncomp_size;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1598 out_cp = (char *)BLOCK_END(out);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1599
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1600 stop = c->byte_array_stop.stop;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1601 if (cp_end - cp < out->alloc - out->byte) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1602 while (*cp != stop && cp != cp_end)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1603 *out_cp++ = *cp++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1604 BLOCK_SIZE(out) = out_cp - (char *)BLOCK_DATA(out);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1605 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1606 char *cp_start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1607 for (cp_start = cp; *cp != stop && cp != cp_end; cp++)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1608 ;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1609 BLOCK_APPEND(out, cp_start, cp - cp_start);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1610 BLOCK_GROW(out, cp - cp_start);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1611 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1612
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1613 *out_size = cp - (char *)(b->data + b->idx);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1614 b->idx = cp - (char *)b->data + 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1615
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1616 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1617 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1618
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1619 void cram_byte_array_stop_decode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1620 if (!c) return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1621
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1622 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1623 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1624
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1625 cram_codec *cram_byte_array_stop_decode_init(char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1626 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1627 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1628 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1629 unsigned char *cp = (unsigned char *)data;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1630
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1631 if (!(c = malloc(sizeof(*c))))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1632 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1633
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1634 c->codec = E_BYTE_ARRAY_STOP;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1635 c->decode = (option == E_BYTE_ARRAY_BLOCK)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1636 ? cram_byte_array_stop_decode_block
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1637 : cram_byte_array_stop_decode_char;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1638 c->free = cram_byte_array_stop_decode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1639
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1640 c->byte_array_stop.stop = *cp++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1641 if (CRAM_MAJOR_VERS(version) == 1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1642 c->byte_array_stop.content_id = cp[0] + (cp[1]<<8) + (cp[2]<<16)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1643 + (cp[3]<<24);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1644 cp += 4;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1645 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1646 cp += itf8_get(cp, &c->byte_array_stop.content_id);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1647 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1648
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1649 if ((char *)cp - data != size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1650 fprintf(stderr, "Malformed byte_array_stop header stream\n");
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1651 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1652 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1653 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1654
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1655 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1656 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1657
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1658 int cram_byte_array_stop_encode(cram_slice *slice, cram_codec *c,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1659 char *in, int in_size) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1660 BLOCK_APPEND(c->out, in, in_size);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1661 BLOCK_APPEND_CHAR(c->out, c->e_byte_array_stop.stop);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1662 return 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1663 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1664
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1665 void cram_byte_array_stop_encode_free(cram_codec *c) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1666 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1667 return;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1668 free(c);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1669 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1670
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1671 int cram_byte_array_stop_encode_store(cram_codec *c, cram_block *b,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1672 char *prefix, int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1673 int len = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1674 char buf[20], *cp = buf;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1675
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1676 if (prefix) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1677 size_t l = strlen(prefix);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1678 BLOCK_APPEND(b, prefix, l);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1679 len += l;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1680 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1681
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1682 cp += itf8_put(cp, c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1683
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1684 if (CRAM_MAJOR_VERS(version) == 1) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1685 cp += itf8_put(cp, 5);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1686 *cp++ = c->e_byte_array_stop.stop;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1687 *cp++ = (c->e_byte_array_stop.content_id >> 0) & 0xff;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1688 *cp++ = (c->e_byte_array_stop.content_id >> 8) & 0xff;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1689 *cp++ = (c->e_byte_array_stop.content_id >> 16) & 0xff;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1690 *cp++ = (c->e_byte_array_stop.content_id >> 24) & 0xff;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1691 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1692 cp += itf8_put(cp, 1 + itf8_size(c->e_byte_array_stop.content_id));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1693 *cp++ = c->e_byte_array_stop.stop;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1694 cp += itf8_put(cp, c->e_byte_array_stop.content_id);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1695 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1696
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1697 BLOCK_APPEND(b, buf, cp-buf);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1698 len += cp-buf;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1699
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1700 return len;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1701 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1702
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1703 cram_codec *cram_byte_array_stop_encode_init(cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1704 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1705 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1706 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1707 cram_codec *c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1708
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1709 c = malloc(sizeof(*c));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1710 if (!c)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1711 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1712 c->codec = E_BYTE_ARRAY_STOP;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1713 c->free = cram_byte_array_stop_encode_free;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1714 c->encode = cram_byte_array_stop_encode;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1715 c->store = cram_byte_array_stop_encode_store;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1716
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1717 c->e_byte_array_stop.stop = ((int *)dat)[0];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1718 c->e_byte_array_stop.content_id = ((int *)dat)[1];
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1719
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1720 return c;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1721 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1722
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1723 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1724 * ---------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1725 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1726
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1727 char *cram_encoding2str(enum cram_encoding t) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1728 switch (t) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1729 case E_NULL: return "NULL";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1730 case E_EXTERNAL: return "EXTERNAL";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1731 case E_GOLOMB: return "GOLOMB";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1732 case E_HUFFMAN: return "HUFFMAN";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1733 case E_BYTE_ARRAY_LEN: return "BYTE_ARRAY_LEN";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1734 case E_BYTE_ARRAY_STOP: return "BYTE_ARRAY_STOP";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1735 case E_BETA: return "BETA";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1736 case E_SUBEXP: return "SUBEXP";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1737 case E_GOLOMB_RICE: return "GOLOMB_RICE";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1738 case E_GAMMA: return "GAMMA";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1739 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1740 return "?";
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1741 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1742
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1743 static cram_codec *(*decode_init[])(char *data,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1744 int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1745 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1746 int version) = {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1747 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1748 cram_external_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1749 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1750 cram_huffman_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1751 cram_byte_array_len_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1752 cram_byte_array_stop_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1753 cram_beta_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1754 cram_subexp_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1755 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1756 cram_gamma_decode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1757 };
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1758
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1759 cram_codec *cram_decoder_init(enum cram_encoding codec,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1760 char *data, int size,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1761 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1762 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1763 if (decode_init[codec]) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1764 return decode_init[codec](data, size, option, version);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1765 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1766 fprintf(stderr, "Unimplemented codec of type %s\n", codec2str(codec));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1767 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1768 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1769 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1770
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1771 static cram_codec *(*encode_init[])(cram_stats *stx,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1772 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1773 void *opt,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1774 int version) = {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1775 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1776 cram_external_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1777 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1778 cram_huffman_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1779 cram_byte_array_len_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1780 cram_byte_array_stop_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1781 cram_beta_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1782 NULL, //cram_subexp_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1783 NULL,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1784 NULL, //cram_gamma_encode_init,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1785 };
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1786
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1787 cram_codec *cram_encoder_init(enum cram_encoding codec,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1788 cram_stats *st,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1789 enum cram_external_type option,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1790 void *dat,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1791 int version) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1792 if (st && !st->nvals)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1793 return NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1794
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1795 if (encode_init[codec]) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1796 cram_codec *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1797 if ((r = encode_init[codec](st, option, dat, version)))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1798 r->out = NULL;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1799 return r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1800 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1801 fprintf(stderr, "Unimplemented codec of type %s\n", codec2str(codec));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1802 abort();
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1803 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1804 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1805
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1806 /*
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1807 * Returns the content_id used by this codec, also in id2 if byte_array_len.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1808 * Returns -1 for the CORE block and -2 for unneeded.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1809 * id2 is only filled out for BYTE_ARRAY_LEN which uses 2 codecs.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1810 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1811 int cram_codec_to_id(cram_codec *c, int *id2) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1812 int bnum1, bnum2 = -2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1813
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1814 switch (c->codec) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1815 case E_HUFFMAN:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1816 bnum1 = c->huffman.ncodes == 1 ? -2 : -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1817 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1818 case E_GOLOMB:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1819 case E_BETA:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1820 case E_SUBEXP:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1821 case E_GOLOMB_RICE:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1822 case E_GAMMA:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1823 bnum1 = -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1824 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1825 case E_EXTERNAL:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1826 bnum1 = c->external.content_id;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1827 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1828 case E_BYTE_ARRAY_LEN:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1829 bnum1 = cram_codec_to_id(c->byte_array_len.len_codec, NULL);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1830 bnum2 = cram_codec_to_id(c->byte_array_len.value_codec, NULL);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1831 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1832 case E_BYTE_ARRAY_STOP:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1833 bnum1 = c->byte_array_stop.content_id;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1834 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1835 case E_NULL:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1836 bnum1 = -2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1837 break;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1838 default:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1839 fprintf(stderr, "Unknown codec type %d\n", c->codec);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1840 bnum1 = -1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1841 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1842
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1843 if (id2)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1844 *id2 = bnum2;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1845 return bnum1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1846 }