360 for (
int i = 0, e = inputData.size(); i < e; ++i) {
361 const auto value = uchar(inputData[i]);
362 write_huffman_code(outputStream, staticHuffmanCodeTable[value]);
366 if (outputStream.bitLength() % 8)
367 outputStream.writeBits(0xff, 8 - outputStream.bitLength() % 8);
388 const auto nCodes =
sizeof staticHuffmanCodeTable /
sizeof staticHuffmanCodeTable[0];
390 std::vector<CodeEntry> symbols(staticHuffmanCodeTable, staticHuffmanCodeTable + nCodes);
395 if (code1.bitLength == code2.bitLength)
396 return code1.byteValue > code2.byteValue;
397 return code1.bitLength > code2.bitLength;
400 minCodeLength = symbols.back().bitLength;
407 addTable(0, quint32(BitConstants::rootPrefix));
409 for (
const auto &s : symbols) {
410 quint32 tableIndex = 0;
412 Q_ASSERT(tableIndex < prefixTables.size());
414 const auto table = prefixTables[tableIndex];
416 const auto entryIndex = s.huffmanCode << table.prefixLength >> (32 - table.indexLength);
418 PrefixTableEntry entry = tableEntry(table, entryIndex);
420 const auto codedLength = table.prefixLength + table.indexLength;
421 if (codedLength < s.bitLength) {
423 if (!entry.bitLength) {
424 entry.nextTable = addTable(codedLength, std::min<quint32>(quint32(BitConstants::childPrefix),
425 s.bitLength - codedLength));
426 entry.bitLength = s.bitLength;
427 entry.byteValue = s.byteValue;
428 setTableEntry(table, entryIndex, entry);
430 tableIndex = entry.nextTable;
433 entry.byteValue = s.byteValue;
434 entry.bitLength = s.bitLength;
436 entry.nextTable = tableIndex;
437 setTableEntry(table, entryIndex, entry);
445 for (
const auto &table : prefixTables) {
446 const quint32 codedLength = table.prefixLength + table.indexLength;
447 for (quint32 j = 0; j < table.size();) {
448 const PrefixTableEntry &entry = tableEntry(table, j);
449 if (entry.bitLength && entry.bitLength < codedLength) {
450 const quint32 range = 1 << (codedLength - entry.bitLength);
451 for (quint32 k = 1; k < range; ++k)
452 setTableEntry(table, j + k, entry);
465 const quint32 readBits = inputStream.peekBits(inputStream.streamOffset(), 32, &chunk);
467 return !inputStream.hasMoreBits();
469 if (readBits < minCodeLength) {
470 inputStream.skipBits(readBits);
471 return padding_is_valid(chunk, readBits);
474 quint32 tableIndex = 0;
475 const PrefixTable *table = &prefixTables[tableIndex];
476 quint32 entryIndex = chunk >> (32 - table->indexLength);
480 if (entry.nextTable == tableIndex)
483 tableIndex = entry.nextTable;
484 table = &prefixTables[tableIndex];
485 entryIndex = chunk << table->prefixLength >> (32 - table->indexLength);
486 entry = tableEntry(*table, entryIndex);
489 if (entry.bitLength > readBits) {
490 inputStream.skipBits(readBits);
491 return padding_is_valid(chunk, readBits);
494 if (!entry.bitLength || entry.byteValue == 256) {
496 inputStream.skipBits(readBits);
500 outputBuffer.append(entry.byteValue);
501 inputStream.skipBits(entry.bitLength);