| 141 | return z |
| 142 | |
| 143 | class HuffmanTable(object): |
| 144 | def __init__(self, bootstrap): |
| 145 | l = [] |
| 146 | start, bits = bootstrap[0] |
| 147 | for finish, endbits in bootstrap[1:]: |
| 148 | if bits: |
| 149 | for code in range(start, finish): |
| 150 | l.append(HuffmanLength(code, bits)) |
| 151 | start, bits = finish, endbits |
| 152 | if endbits == -1: |
| 153 | break |
| 154 | l.sort() |
| 155 | self.table = l |
| 156 | |
| 157 | def populate_huffman_symbols(self): |
| 158 | bits, symbol = -1, -1 |
| 159 | for x in self.table: |
| 160 | symbol += 1 |
| 161 | if x.bits != bits: |
| 162 | symbol <<= (x.bits - bits) |
| 163 | bits = x.bits |
| 164 | x.symbol = symbol |
| 165 | x.reverse_symbol = reverse_bits(symbol, bits) |
| 166 | #print printbits(x.symbol, bits), printbits(x.reverse_symbol, bits) |
| 167 | |
| 168 | def tables_by_bits(self): |
| 169 | d = {} |
| 170 | for x in self.table: |
| 171 | try: |
| 172 | d[x.bits].append(x) |
| 173 | except: |
| 174 | d[x.bits] = [x] |
| 175 | pass |
| 176 | |
| 177 | def min_max_bits(self): |
| 178 | self.min_bits, self.max_bits = 16, -1 |
| 179 | for x in self.table: |
| 180 | if x.bits < self.min_bits: self.min_bits = x.bits |
| 181 | if x.bits > self.max_bits: self.max_bits = x.bits |
| 182 | |
| 183 | def _find_symbol(self, bits, symbol, table): |
| 184 | for h in table: |
| 185 | if h.bits == bits and h.reverse_symbol == symbol: |
| 186 | #print "found, processing", h.code |
| 187 | return h.code |
| 188 | return -1 |
| 189 | |
| 190 | def find_next_symbol(self, field, reversed = True): |
| 191 | cached_length = -1 |
| 192 | cached = None |
| 193 | for x in self.table: |
| 194 | if cached_length != x.bits: |
| 195 | cached = field.snoopbits(x.bits) |
| 196 | cached_length = x.bits |
| 197 | if (reversed and x.reverse_symbol == cached) or (not reversed and x.symbol == cached): |
| 198 | field.readbits(x.bits) |
| 199 | return x.code |
| 200 | raise "unfound symbol, even after end of table @ " + `field.tell()` |