inflate a block with dynamic of fixed Huffman tree*/
| 1101 | |
| 1102 | /*inflate a block with dynamic of fixed Huffman tree*/ |
| 1103 | static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, |
| 1104 | size_t* pos, size_t inlength, unsigned btype) |
| 1105 | { |
| 1106 | unsigned error = 0; |
| 1107 | HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ |
| 1108 | HuffmanTree tree_d; /*the huffman tree for distance codes*/ |
| 1109 | size_t inbitlength = inlength * 8; |
| 1110 | |
| 1111 | HuffmanTree_init(&tree_ll); |
| 1112 | HuffmanTree_init(&tree_d); |
| 1113 | |
| 1114 | if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d); |
| 1115 | else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength); |
| 1116 | |
| 1117 | while(!error) /*decode all symbols until end reached, breaks at end code*/ |
| 1118 | { |
| 1119 | /*code_ll is literal, length or end code*/ |
| 1120 | unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength); |
| 1121 | if(code_ll <= 255) /*literal symbol*/ |
| 1122 | { |
| 1123 | /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/ |
| 1124 | if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/); |
| 1125 | out->data[*pos] = (unsigned char)code_ll; |
| 1126 | (*pos)++; |
| 1127 | } |
| 1128 | else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ |
| 1129 | { |
| 1130 | unsigned code_d, distance; |
| 1131 | unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ |
| 1132 | size_t start, forward, backward, length; |
| 1133 | |
| 1134 | /*part 1: get length base*/ |
| 1135 | length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; |
| 1136 | |
| 1137 | /*part 2: get extra bits and add the value of that to length*/ |
| 1138 | numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; |
| 1139 | if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ |
| 1140 | length += readBitsFromStream(bp, in, numextrabits_l); |
| 1141 | |
| 1142 | /*part 3: get distance code*/ |
| 1143 | code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength); |
| 1144 | if(code_d > 29) |
| 1145 | { |
| 1146 | if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ |
| 1147 | { |
| 1148 | /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol |
| 1149 | (10=no endcode, 11=wrong jump outside of tree)*/ |
| 1150 | error = (*bp) > inlength * 8 ? 10 : 11; |
| 1151 | } |
| 1152 | else error = 18; /*error: invalid distance code (30-31 are never used)*/ |
| 1153 | break; |
| 1154 | } |
| 1155 | distance = DISTANCEBASE[code_d]; |
| 1156 | |
| 1157 | /*part 4: get extra bits from distance*/ |
| 1158 | numextrabits_d = DISTANCEEXTRA[code_d]; |
| 1159 | if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ |
| 1160 |
no test coverage detected