//bitstring.cpp
#include "bitstring.h"
BitStringWrite::BitStringWrite(std::ostream &_out_f) : _byte(0), _pos(0), _out_f(_out_f) {}
void BitStringWrite::writeBit(bool bit) {
if (_pos == 8)
flush();
if (bit == 1) {
_byte |= (1 << _pos);
}
_pos++;
}
void BitStringWrite::writeByte(char b){
for(int i = 0; i < 8; i++)
this -> writeBit((b >> i) & 1);
}
void BitStringWrite::flush() {
if (_pos != 0) {
_out_f.write(&_byte, sizeof(char));
_pos = 0;
_byte = 0;
}
}
BitStringRead::BitStringRead(std::istream &_in_f) : _pos(8), _in_f(_in_f) {}
bool BitStringRead::readBit() {
if (_pos == 8) {
_in_f.read(&_byte, sizeof(char));
_pos = 0;
}
return (_byte >> _pos++) & (char)1;
}
char BitStringRead::readByte() {
char sym = (char)0;
for (int i = 0; i < 8; i++){
sym |= ((1 & readBit()) << (i));
}
return sym;
}
BitStringWrite::~BitStringWrite() {
flush();
}
____________________________________________
//archiver.cpp
#include "archiver.h"
#include <fstream>
void Archiver::encodeTree(BitStringWrite& bw, TreeNode* node){
if (node -> isLeaf()) {
bw.writeBit(1);
char symb = node->getChar();
bw.getStream().write(&symb, sizeof(symb));
}
else {
bw.writeBit(0);
encodeTree(bw, node->getLeftTree());
encodeTree(bw, node->getRightTree());
}
}
TreeNode* Archiver::decodeTree(BitStringRead& br, TreeNode* cur){
if (br.readBit()) {
return new TreeNode(br.readByte(), 0, false, NULL, NULL);
}
else {
TreeNode* left = decodeTree(br, cur-> getLeftTree());
TreeNode* right = decodeTree(br, cur-> getRightTree());
decodeTree(br, cur-> getRightTree());
return new TreeNode(0, 0, false, left, right);
}
}
void Archiver::buildCodes(TreeNode* n, std::vector<bool>& cur) {
if (n -> isLeaf()) {
codes[cur] = n->getChar();
return;
}
cur.push_back(0);
buildCodes(n->getLeftTree(), cur);
cur.pop_back();
cur.push_back(1);
buildCodes(n->getRightTree(), cur);
}
void Archiver::compress(std::ifstream &ifs, std::ofstream &ofs, HuffmanTree *tree) {
ifs.seekg(0, ifs.beg);
BitStringRead br(ifs);
BitStringWrite bw(ofs);
tree->buildTable();
encodeTree(bw, tree -> getRoot());
char symb = 0;
while(!ifs.eof()){
ifs.read(&symb, sizeof(symb));
int sz = tree->getTable()[symb].size();
std::vector<bool> out = tree->getTable()[symb];
std::cout << std::endl;
for(int i = 0; i < sz; i++)
bw.writeBit(out[i]);
}
}
void Archiver::decompress(std::ifstream &ifs, std::ofstream &ofs, HuffmanTree *tree) {
ifs.seekg(0, ifs.beg);
BitStringRead br(ifs);
BitStringWrite bw(ofs);
decodeTree(br, tree->getRoot());
std::vector<bool> cur;
/* buildCodes(tree->getRoot(), cur);
while(!ifs.eof()){
std::vector<bool> v;
while(!(getCodes().count(v))) {
bool b = br.readBit();
v.push_back(b);
}
char s = getCodes()[v];
v.clear();
ofs.write(&s, sizeof(s));
}*/
}
_________________________________
//huffman.cpp
#include "huffman.h"
#include "archiver.h"
#include <sstream>
#include <queue>
using namespace std;
HuffmanTree::HuffmanTree(std::map<char, int>& count_map) {
if (count_map.empty()) {
std::stringstream ss;
ss << "Compressor requires a non-empty text.";
throw std::runtime_error{ss.str()};
}
std::priority_queue<TreeNode*, std::vector<TreeNode*>, HuffmanTree::NodeComparator> queue;
for(auto a : count_map)
queue.push(new TreeNode(a.first, a.second, true, NULL, NULL));
while (queue.size() > 1) {
TreeNode* node1 = queue.top(); queue.pop();
TreeNode* node2 = queue.top(); queue.pop();
queue.push(merge(node1, node2));
}
root = queue.top(); queue.pop();
}
std::map<char, vector<bool> > HuffmanTree::buildTable() {
deque< pair<TreeNode *, code_t> > q;
q.push_back(make_pair(this->getRoot(), code_t()));
while (!q.empty()) {
TreeNode *node, *lc, *rc;
code_t code;
node = q.front().first;
code = q.front().second;
q.pop_front();
lc = node->getLeftTree();
rc = node->getRightTree();
if (lc) {
code_t code_cp(code);
q.push_back(make_pair(lc, (code.push_back(0), code)));
q.push_back(make_pair(rc, (code_cp.push_back(1), code_cp)));
}
else {
lookup.insert(make_pair(node->getChar(), code));
cout << "(" << node->getChar() << ", ";
for (unsigned i = 0; i < code.size(); i++) {
cout << code[i];
}
cout << ")" << endl;
}
}
return lookup;
}
void BuildTable(TreeNode *root, std::vector<bool> &code, std::map<std::vector<bool>, char > &table){
if (root->getLeftTree()){
code.push_back(0);
BuildTable(root->getLeftTree(), code, table);
}
if (root->getRightTree()){
code.push_back(1);
BuildTable(root->getRightTree(), code, table);
}
if (root->getChar())
table[code] = root->getChar();
if (code.size())
code.pop_back();
}
void HuffmanTree::recursiveNodeDelete(TreeNode* node) {
if (node == NULL) {
return;
}
recursiveNodeDelete(node->getLeftTree());
recursiveNodeDelete(node->getRightTree());
delete node;
}
HuffmanTree::~HuffmanTree() {
recursiveNodeDelete(root);
}
TreeNode* HuffmanTree::merge(TreeNode* node1, TreeNode* node2) {
TreeNode* new_node = new TreeNode(0, node1->getCount() + node2->getCount(), false, NULL, NULL);
if (node1->getCount() < node2->getCount()) {
new_node->setLeftTree(node1);
new_node->setRightTree(node2);
}
else {
new_node->setLeftTree(node2);
new_node->setRightTree(node1);
}
new_node->setChar(std::max(node1->getChar(), node2->getChar()));
return new_node;
}
______________________________________________
//main.cpp
#include <iostream>
#include <bits/stdc++.h>
#include "huffman.h"
#include "archiver.h"
using namespace std;
std::map<char, int32_t> createFreqTable(const std::string &strfile){
std::ifstream file(strfile);
std::map<char, int32_t> freq;
int next = 0;
while ((next = file.get()) != EOF) {
char uc = static_cast <char> (next);
std::map<char, int32_t>::iterator iter;
iter = freq.find(uc);
if (iter != freq.end())
iter->second += 1;
else
freq[uc] = 1;
}
return freq;
};
int main() {
Archiver ar;
std::map<char, int32_t> m = createFreqTable("test.in");
HuffmanTree t(m);
std::ifstream ifs("test.in");
std::ofstream ofs("test.out");
//t.buildTable(t.getRoot());
ar.compress(ifs, ofs, &t);
/* HuffmanTree nt;
std::ifstream ifs("test.out");
std::ofstream ofs("testo.txt");
vector<bool> v;
ar.decompress(ifs, ofs, &nt);*/
return 0;
}