-
Notifications
You must be signed in to change notification settings - Fork 0
/
huffman.hpp
135 lines (100 loc) · 3.27 KB
/
huffman.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#ifndef HUFFMAN_H
#define HUFFMAN_H
#include <stdint.h>
#include <vector>
#include <fstream>
#include <filesystem>
#include <limits>
#include <bitset>
#include "node.hpp"
#include "huf_exception.hpp"
#define TOKEN_MAX 0x100 // 1byte
#define TOKEN_BITS 8
#define TYPE_REGULAR_FILE 0
#define TYPE_DIRECTORY 1
namespace Huffman
{
struct TokenCount
{
unsigned char token;
unsigned count;
bool operator<(const TokenCount& other) const
{
return count < other.count;
}
bool operator>(const TokenCount& other) const
{
return count > other.count;
}
bool operator==(const TokenCount& other) const
{
return count == other.count;
}
bool operator<=(const TokenCount& other) const
{
return count <= other.count;
}
bool operator>=(const TokenCount& other) const
{
return count >= other.count;
}
bool operator!=(const TokenCount& other) const
{
return count != other.count;
}
};
#pragma pack(push, 1)
using token_t = uint8_t;
struct HufHeader
{
uint16_t padding_bits : 3;
uint16_t records_size : 13;
size_t data_size;
};
struct Header
{
uint16_t type : 1;
uint16_t name_size : 15; // name is std::filesystem::path::value_type
size_t data_size;
};
using NameType = std::filesystem::path::value_type;
using FileHeader = Header;
using DirectoryHeader = Header;
struct TokenRecord
{
token_t level;
token_t token;
};
#pragma pack(pop)
using HufNode = PODNode<TokenCount, 2>;
//using Code = std::vector<bool>;
struct Code
{
std::bitset<TOKEN_MAX> code;
size_t size;
};
// preprocessing for encoding------------------------------
std::vector<size_t> MakeTokenTable(std::istream& is);
HufNode* MakePrefixTree(const std::vector<size_t>& token_table);
std::vector<Code> MakeCodeTable(const HufNode* tree);
uint16_t BuildTokenRecords(const HufNode* tree, TokenRecord token_records[]);
// encoding process----------------------------------------
// return last bit position + 1
int ConvertToHufCode(std::istream& src, std::ostream& dst, const std::vector<Code>& code_table);
void Encode(std::istream& src, std::ostream& dst, const std::vector<Code>& code_table, const HufNode* tree);
void Encoding(std::istream& src, std::ostream& dst);
void EncodeFile(const std::filesystem::path& file_path, std::ostream& dst);
void EncodeDirectory(const std::filesystem::path& dir_path, std::ostream& dst);
void Compress(const std::filesystem::path& src_path, std::ostream& dst);
// decoding process----------------------------------------
HufNode* DecodeTokenRecords(const TokenRecord token_records[], uint16_t records_size);
void ConvertToToken(std::istream& src, std::ostream& dst, const HufNode* tree, int padding_bits, size_t max_len = std::numeric_limits<size_t>::max());
void Decode(std::istream& src, std::ostream& dst);
void Decoding(std::istream& src, std::ostream& dst);
void DecodeFile(std::istream& src, const std::filesystem::path& prefix);
void DecodeDirectory(std::istream& src, const std::filesystem::path& prefix, size_t num_of_file);
void Decompress(std::istream& src, const std::filesystem::path& prefix);
// Æнº¸¦ ¾ò°í ½Í´Ù¸é ÀÌ°Í?!
std::filesystem::path DecompressRetFilename(std::istream& src, const std::filesystem::path& prefix);
}
#endif // HUFFMAN_H