-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileHandler.cpp
More file actions
121 lines (102 loc) · 4.46 KB
/
Copy pathFileHandler.cpp
File metadata and controls
121 lines (102 loc) · 4.46 KB
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
#include "FileHandler.h"
#include <fstream>
#include <stdexcept>
#include <cstdint>
namespace FileHandler {
// ─── Helpers ─────────────────────────────────────────────────────
static void writeU32(std::ofstream& f, uint32_t v) {
f.put((v >> 24) & 0xFF);
f.put((v >> 16) & 0xFF);
f.put((v >> 8) & 0xFF);
f.put((v ) & 0xFF);
}
static uint32_t readU32(std::ifstream& f) {
uint32_t v = 0;
v |= (uint32_t)(unsigned char)f.get() << 24;
v |= (uint32_t)(unsigned char)f.get() << 16;
v |= (uint32_t)(unsigned char)f.get() << 8;
v |= (uint32_t)(unsigned char)f.get();
return v;
}
// ─── Read / write raw files ──────────────────────────────────────
std::string readFile(const std::string& path) {
std::ifstream f(path, std::ios::binary);
if (!f.is_open()) throw std::runtime_error("Cannot open file: " + path);
return std::string((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
}
void writeFile(const std::string& path, const std::string& data) {
std::ofstream f(path, std::ios::binary);
if (!f.is_open()) throw std::runtime_error("Cannot write file: " + path);
f.write(data.data(), (std::streamsize)data.size());
}
// ─── Pack bit string → bytes ─────────────────────────────────────
static std::string packBits(const std::string& bits, uint32_t& paddingBits) {
std::string bytes;
size_t len = bits.size();
paddingBits = (8 - (len % 8)) % 8;
// Pad with zeros at the end
std::string padded = bits + std::string(paddingBits, '0');
bytes.reserve(padded.size() / 8);
for (size_t i = 0; i < padded.size(); i += 8) {
unsigned char byte = 0;
for (int b = 0; b < 8; ++b)
if (padded[i + b] == '1') byte |= (1 << (7 - b));
bytes += (char)byte;
}
return bytes;
}
// ─── Unpack bytes → bit string ────────────────────────────────────
static std::string unpackBits(const std::string& bytes, uint32_t paddingBits) {
std::string bits;
bits.reserve(bytes.size() * 8);
for (unsigned char byte : bytes)
for (int b = 7; b >= 0; --b)
bits += ((byte >> b) & 1) ? '1' : '0';
// Remove padding
if (paddingBits > 0)
bits.resize(bits.size() - paddingBits);
return bits;
}
// ─── Write compressed file ────────────────────────────────────────
void writeCompressed(const std::string& path,
const std::string& treeData,
const std::string& bits,
uint32_t originalSize) {
std::ofstream f(path, std::ios::binary);
if (!f.is_open()) throw std::runtime_error("Cannot write file: " + path);
uint32_t paddingBits = 0;
std::string packed = packBits(bits, paddingBits);
// Magic
f.write("HUFF", 4);
// Tree size + tree
writeU32(f, (uint32_t)treeData.size());
f.write(treeData.data(), (std::streamsize)treeData.size());
// Padding + original size
writeU32(f, paddingBits);
writeU32(f, originalSize);
// Packed data
f.write(packed.data(), (std::streamsize)packed.size());
}
// ─── Read compressed file ─────────────────────────────────────────
void readCompressed(const std::string& path,
std::string& treeData,
std::string& bits,
uint32_t& originalSize) {
std::ifstream f(path, std::ios::binary);
if (!f.is_open()) throw std::runtime_error("Cannot open file: " + path);
// Check magic
char magic[5] = {};
f.read(magic, 4);
if (std::string(magic, 4) != "HUFF")
throw std::runtime_error("Not a valid HUFF compressed file.");
uint32_t treeSize = readU32(f);
treeData.resize(treeSize);
f.read(&treeData[0], (std::streamsize)treeSize);
uint32_t paddingBits = readU32(f);
originalSize = readU32(f);
std::string packed((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
bits = unpackBits(packed, paddingBits);
}
} // namespace FileHandler