Files
mashzip/main.cpp
2024-01-08 02:42:59 +07:00

278 lines
7.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <string>
#include <queue>
#include <unordered_map>
#include <map>
#include <iostream>
#include <set>
#include <bitset>
#include <sstream>
#include "bitstream.h"
#include "huffman_table.h"
using namespace std;
// // A Tree node
// struct Node
// {
// char ch;
// int freq;
// Node *left, *right;
// };
// // Function to allocate a new tree node
// Node* getNode(char ch, int freq, Node* left, Node* right)
// {
// Node* node = new Node();
// node->ch = ch;
// node->freq = freq;
// node->left = left;
// node->right = right;
// return node;
// }
// // Comparison object to be used to order the heap
// struct comp
// {
// bool operator()(Node* l, Node* r)
// {
// // highest priority item has lowest frequency
// return l->freq > r->freq;
// }
// };
// // traverse the Huffman Tree and store Huffman Codes
// // in a map.
// void encode(Node* root, int len,
// map<int, std::set<char> > &huffmanLengths)
// {
// if (root == nullptr)
// return;
// // found a leaf node
// if (!root->left && !root->right) {
// // huffmanCode[root->ch] = str;
// huffmanLengths[len].insert(root->ch);
// }
// encode(root->left, len + 1, huffmanLengths);
// encode(root->right, len + 1, huffmanLengths);
// }
// void initializeTable(const map<int, std::set<char> > &huffmanLengths,
// unordered_map<char, std::pair<int, short> > &table)
// {
// int nextbl = 0;
// short code = 0;
// for (auto lenCodePairIt = huffmanLengths.begin(); lenCodePairIt != huffmanLengths.end(); lenCodePairIt++)
// {
// auto lenCodePair = *lenCodePairIt;
// for (auto it = lenCodePair.second.begin(); it != lenCodePair.second.end(); it++)
// {
// table[*it].first = lenCodePair.first; // save current bit length for code
// table[*it].second = code;
// // code := (code + 1) << ((bit length of the next symbol) (current bit length))
// // code++;
// // if last symbol of length and has symbols with greater length
// if (next(it) == lenCodePair.second.end() && next(lenCodePairIt) != huffmanLengths.end()) {
// nextbl = (*next(lenCodePairIt)).first;
// } else {
// nextbl = lenCodePair.first;
// }
// code = (code + 1) << (nextbl - lenCodePair.first);
// }
// // code <<= 1;
// }
// }
// // traverse the Huffman Tree and decode the encoded string
// void decode(Node* root, int &index, string str)
// {
// if (root == nullptr) {
// return;
// }
// // found a leaf node
// if (!root->left && !root->right)
// {
// cout << root->ch;
// return;
// }
// index++;
// if (str[index] =='0')
// decode(root->left, index, str);
// else
// decode(root->right, index, str);
// }
// // Builds Huffman Tree and decode given input text
// void buildHuffmanTree(basic_istream<char> &is)
// {
// // count frequency of appearance of each character
// // and store it in a map
// unordered_map<char, int> freq;
// char ch;
// while (is.get(ch)) {
// freq[ch]++;
// }
// for (auto freqPair : freq) {
// cout << "Freq " << freqPair.first << " " << freqPair.second << endl;
// }
// // Create a priority queue to store live nodes of
// // Huffman tree;
// priority_queue<Node*, vector<Node*>, comp> pq;
// // Create a leaf node for each character and add it
// // to the priority queue.
// for (auto pair: freq) {
// pq.push(getNode(pair.first, pair.second, nullptr, nullptr));
// }
// // do till there is more than one node in the queue
// while (pq.size() != 1)
// {
// // Remove the two nodes of highest priority
// // (lowest frequency) from the queue
// Node *left = pq.top(); pq.pop();
// Node *right = pq.top(); pq.pop();
// // Create a new internal node with these two nodes
// // as children and with frequency equal to the sum
// // of the two nodes' frequencies. Add the new node
// // to the priority queue.
// int sum = left->freq + right->freq;
// pq.push(getNode('\0', sum, left, right));
// }
// // root stores pointer to root of Huffman Tree
// Node* root = pq.top();
// map<int, std::set<char> > huffmanLengths;
// encode(root, 0, huffmanLengths);
// unordered_map<char, std::pair<int, short> > huffmanCode;
// initializeTable(huffmanLengths, huffmanCode);
// cout << "Huffman Codes are :\n" << '\n';
// for (auto pair: huffmanCode) {
// cout << pair.first << " " << pair.second.first << " " << bitset<16>(pair.second.second) << '\n';
// }
// // cout << "\nOriginal string was :\n" << text << '\n';
// // // print encoded string
// // string str = "";
// // for (char ch: text) {
// // str += huffmanCode[ch];
// // }
// // cout << "\nEncoded string is :\n" << str << '\n';
// // // traverse the Huffman Tree again and this time
// // // decode the encoded string
// // int index = -1;
// // cout << "\nDecoded string is: \n";
// // while (index < (int)str.size() - 2) {
// // decode(root, index, str);
// // }
// }
//// Huffman coding algorithm
int main(int argc, char **argv)
{
// // buildHuffmanTree(cin);
// // 10111010 11110101
// stringstream ss("\xba\xf5");
// ibitstream ibs(ss);
// // 10111010 11110101
// // ^^
// int a = ibs.getbits(2);
// cout << bitset<2>(a) << endl;
// // 10111010 11110101
// // ^^^^
// int b = ibs.getbits(4);
// cout << bitset<4>(b) << endl;
// // 10111010 11110101
// // ^^ ^^^^^^^
// b = ibs.getbits(9);
// cout << bitset<9>(b) << endl;
// // 10111010 11110101
// // ^ + overflow
// try {
// b = ibs.getbits(10);
// cout << b << endl;
// } catch (std::runtime_error &e) {
// cout << "Got runtime error: " << e.what() << endl;
// }
// ostringstream so("bits: ");
// obitstream obs(so);
// obs.writebits(0xf, 3);
// cout << "After 3 bits: " << so.str() << endl;
// // cache here: 00000111
// obs.writebits(0xf5, 7);
// // here: Flush: 10101111
// cout << "After 7 bits: " << so.str() << endl;
// obs.flush();
// // here: Flush: 00000011
// cout << "After flush: " << so.str() << endl;
// obs.writebits(0xbeef, 16);
// cout << "After 0xbeef: " << so.str() << endl;
// obs.flush();
// // here: Flush: 0xEFBE - reversed!
// cout << "After flush: " << so.str() << endl;
string s = "Some long text!!!!\x01\x02\x03\x04";
stringstream ss1(s);
HuffmanTable ht(ss1);
uint8_t *header = ht.to_header();
// for (size_t i = 0; i < 128; i++)
// {
// cout << "Code for " << 2 * i << " and " << 2 * i + 1 << ": " << bitset<8>(header[i]) << endl;
// }
ostringstream test;
test << "MASH"; // magic
for (size_t i = 0; i < 128; i++) {
test << header[i];
}
obitstream some_stream(test);
for (char c : s) {
ht.write_symbol(some_stream, c);
}
some_stream.flush();
std::cout << test.str();
return 0;
}