#include "HuffmanEncoder.h" #include "RawTree.h" #include "HuffmanFixedCodes.h" #include #include #include #include void HuffmanEncoder::dumpNode(RawNode* node, unsigned depth) const { if (!node) { return; } auto data = node->getData(); std::string prefix(depth, '_'); if (node->isLeaf()) { //std::cout << prefix << "Leaf with value: " << data.first << " and sum " << data.second << std::endl; } else { //std::cout << prefix << "Intermediate with sum " << data.second << std::endl; //std::cout << prefix << "Doing Left.." << std::endl; dumpNode(node->getLeftChild(), depth+1); //std::cout << prefix << "Doing Right.." << std::endl; dumpNode(node->getRightChild(), depth+1); //std::cout << prefix << "*****" << std::endl; } } void HuffmanEncoder::dumpTree(const RawTree& tree) const { dumpNode(tree.getRootNode(), 0); } void HuffmanEncoder::encode(const std::vector& counts) { auto cmp = [](RawNode* left, RawNode* right) { return left->getData().second > right->getData().second; }; std::priority_queue*, std::vector* >, decltype(cmp)> q(cmp); unsigned offset{0}; for (auto count : counts) { if (count > 0) { q.push(new RawNode({offset, count})); } offset++; } while(q.size() > 1) { auto node0 = q.top(); q.pop(); auto node1 = q.top(); q.pop(); const auto sum = node0->getData().second + node1->getData().second; auto new_node = new RawNode(CountPair{0, sum}); new_node->addChild(node0); new_node->addChild(node1); q.push(new_node); } auto root = q.top(); q.pop(); RawTree tree; tree.addRootNode(root); //using TableEntry = std::tuple<> //dumpTree(tree); //std::cout << "********" << std::endl; } void HuffmanEncoder::encode(const std::unordered_map& counts) { std::vector just_counts; for (const auto& data: counts) { mSymbolMapping.push_back(data.first); just_counts.push_back(data.second); } encode(just_counts); } void HuffmanEncoder::setUseFixedCode(bool useFixed) { mUseFixedCode = useFixed; } uint32_t HuffmanEncoder::getLengthValue(unsigned length) { return 0; } std::optional HuffmanEncoder::getLiteralValue(unsigned char value) const { return mLiteralLengthTable.getCodeForSymbol(value); } std::optional HuffmanEncoder::getLengthValue(unsigned length) const { return mLiteralLengthTable.getCodeForSymbol(length); } std::optional HuffmanEncoder::getDistanceValue(unsigned distance) const { return mDistanceTable.getCodeForSymbol(distance); } std::optional HuffmanEncoder::getEndOfStreamValue() const { return mLiteralLengthTable.getCodeForSymbol(256); } void HuffmanEncoder::initializeTrees(const std::vector& hits) { initializeLiteralLengthTable(hits); } void HuffmanEncoder::initializeLiteralLengthTable(const std::vector& hits) { if(mUseFixedCode) { mLiteralLengthTable.setInputLengthSequence(HuffmanFixedCodes::getDeflateFixedHuffmanCodes(), false); mLiteralLengthTable.buildPrefixCodes(); return; } std::vector counts(285, 0); counts[256] = 1; for (const auto& hit : hits) { const auto& [length, distance, next_char] = hit; if (length > 0 ) { const auto& [code, extra_bits, num_extra_bits] = HuffmanFixedCodes::getCodeForLength(length); counts[code]++; } else { counts[next_char]++; } } for(unsigned idx=0; idx0) { //std::cout << "Count for " << idx << " is " << counts[idx] << std::endl; } } encode(counts); }