Skip to content

Commit e76c24d

Browse files
committed
refactor: Update file and product versions to 1.0.4
1 parent 48d7d68 commit e76c24d

File tree

8 files changed

+244
-491
lines changed

8 files changed

+244
-491
lines changed

.vscode/launch.json

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
55
"version": "0.2.0",
66
"configurations": [
7+
{
8+
"name": "Launch test function",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "test",
12+
"program": "${workspaceFolder}",
13+
"args": [
14+
"-test.run",
15+
"MyTestFunction"
16+
]
17+
},
718
{
819
"name": "Launch Package",
920
"type": "go",

compressor/huffman.go

+146-98
Original file line numberDiff line numberDiff line change
@@ -103,29 +103,34 @@ func buildHuffmanCodes(root *Node) (map[rune]string, error) {
103103
}
104104

105105
// rebuildHuffmanTree reconstructs the Huffman tree from Huffman codes
106-
func rebuildHuffmanTree(codes map[rune]string) (*Node, error) {
107-
var root *Node
106+
func rebuildHuffmanTree(root *Node, codes map[rune]string) error {
108107
for char, code := range codes {
109-
if root == nil {
110-
root = &Node{}
111-
}
112-
current := root
113-
for _, bit := range code {
114-
if bit == '0' {
115-
if current.left == nil {
116-
current.left = &Node{}
117-
}
118-
current = current.left
119-
} else if bit == '1' {
120-
if current.right == nil {
121-
current.right = &Node{}
122-
}
123-
current = current.right
108+
insertNode(root, char, code)
109+
}
110+
return nil
111+
}
112+
113+
// insertNode inserts a node into the Huffman tree based on the given code
114+
func insertNode(root *Node, char rune, code string) {
115+
if root == nil {
116+
root = &Node{}
117+
}
118+
119+
current := root
120+
for _, bit := range code {
121+
if bit == '0' {
122+
if current.left == nil {
123+
current.left = &Node{}
124+
}
125+
current = current.left
126+
} else if bit == '1' {
127+
if current.right == nil {
128+
current.right = &Node{}
124129
}
130+
current = current.right
125131
}
126-
current.char = char
127132
}
128-
return root, nil
133+
current.char = char
129134
}
130135

131136
// Zip compresses files using Huffman coding and returns a compressed file object.
@@ -140,28 +145,9 @@ func Zip(files []utils.File) (utils.File, error) {
140145

141146
// Create raw content buffer
142147
var rawContent bytes.Buffer
143-
for _, file := range files {
144-
// Write filename length and filename
145-
filenameLen := uint32(len(file.Name))
146-
err := binary.Write(&rawContent, binary.BigEndian, filenameLen)
147-
if err != nil {
148-
return utils.File{}, err
149-
}
150-
_, err = rawContent.WriteString(file.Name)
151-
if err != nil {
152-
return utils.File{}, err
153-
}
154-
155-
// Write content length and content
156-
contentLen := uint32(len(file.Content))
157-
err = binary.Write(&rawContent, binary.BigEndian, contentLen)
158-
if err != nil {
159-
return utils.File{}, err
160-
}
161-
_, err = rawContent.Write(file.Content)
162-
if err != nil {
163-
return utils.File{}, err
164-
}
148+
err = createContentBuffer(files, &rawContent)
149+
if err != nil {
150+
return utils.File{}, err
165151
}
166152

167153
// Compress rawContent using Huffman coding
@@ -177,7 +163,10 @@ func Zip(files []utils.File) (utils.File, error) {
177163
if err != nil {
178164
return utils.File{}, err
179165
}
180-
compressedContent := compressData(rawContent.Bytes(), codes)
166+
compressedContent, err := compressData(rawContent.Bytes(), codes)
167+
if err != nil {
168+
return utils.File{}, err
169+
}
181170

182171
// Write compressed content length to buffer
183172
err = binary.Write(&buf, binary.BigEndian, uint32(len(compressedContent)))
@@ -196,25 +185,60 @@ func Zip(files []utils.File) (utils.File, error) {
196185
return utils.File{}, err
197186
}
198187
// Write Huffman codes to buffer
188+
err = writeHuffmanCodesToBuffer(codes, &buf)
189+
if err != nil {
190+
return utils.File{}, err
191+
}
192+
193+
return utils.File{
194+
Name: "compressed.bin",
195+
Content: buf.Bytes(),
196+
}, nil
197+
}
198+
199+
func writeHuffmanCodesToBuffer(codes map[rune]string, buf *bytes.Buffer) error {
199200
for char, code := range codes {
200-
err = binary.Write(&buf, binary.BigEndian, char)
201+
err := binary.Write(buf, binary.BigEndian, char)
201202
if err != nil {
202-
return utils.File{}, err
203+
return err
203204
}
204-
err = binary.Write(&buf, binary.BigEndian, uint32(len(code)))
205+
err = binary.Write(buf, binary.BigEndian, uint32(len(code)))
205206
if err != nil {
206-
return utils.File{}, err
207+
return err
207208
}
208209
_, err = buf.WriteString(code)
209210
if err != nil {
210-
return utils.File{}, err
211+
return err
211212
}
212213
}
214+
return nil
215+
}
213216

214-
return utils.File{
215-
Name: "compressed.bin",
216-
Content: buf.Bytes(),
217-
}, nil
217+
func createContentBuffer(files []utils.File, rawContent *bytes.Buffer) error {
218+
for _, file := range files {
219+
// Write filename length and filename
220+
filenameLen := uint32(len(file.Name))
221+
err := binary.Write(rawContent, binary.BigEndian, filenameLen)
222+
if err != nil {
223+
return err
224+
}
225+
_, err = rawContent.WriteString(file.Name)
226+
if err != nil {
227+
return err
228+
}
229+
230+
// Write content length and content
231+
contentLen := uint32(len(file.Content))
232+
err = binary.Write(rawContent, binary.BigEndian, contentLen)
233+
if err != nil {
234+
return err
235+
}
236+
_, err = rawContent.Write(file.Content)
237+
if err != nil {
238+
return err
239+
}
240+
}
241+
return nil
218242
}
219243

220244
// Unzip decompresses a compressed file using Huffman coding and returns individual files.
@@ -250,110 +274,134 @@ func Unzip(file utils.File) ([]utils.File, error) {
250274
return nil, err
251275
}
252276

253-
// Read Huffman codes
254277
codes := make(map[rune]string)
255-
for i := uint32(0); i < codesLength; i++ {
256-
var char rune
257-
err = binary.Read(buf, binary.BigEndian, &char)
258-
if err != nil {
259-
return nil, err
260-
}
261-
var codeLength uint32
262-
err = binary.Read(buf, binary.BigEndian, &codeLength)
263-
if err != nil {
264-
return nil, err
265-
}
266-
code := make([]byte, codeLength)
267-
_, err = buf.Read(code)
268-
if err != nil {
269-
return nil, err
270-
}
271-
codes[char] = string(code)
272-
}
278+
// Read Huffman codes
279+
readHuffManCodes(&codes, buf, codesLength)
273280

274281
// Rebuild Huffman tree using codes
275-
var root *Node
282+
var root Node
276283
if len(codes) > 0 {
277-
root, err = rebuildHuffmanTree(codes)
284+
err = rebuildHuffmanTree(&root, codes)
278285
if err != nil {
279286
return nil, err
280287
}
281288
}
282289

283-
decompressedContent := decompressData(compressedContent, root)
290+
decompressedContent := decompressData(compressedContent, &root)
284291

285292
// Parse decompressed content to extract files
286293
decompressedContentBuf := bytes.NewBuffer(decompressedContent)
287-
for f := uint32(0); f < numFiles; f++ {
294+
err = parseDecompressedContent(&files, &numFiles, decompressedContentBuf)
295+
296+
if err != nil {
297+
return nil, err
298+
}
299+
300+
return files, nil
301+
}
302+
303+
func parseDecompressedContent(files *[]utils.File, numFiles *uint32, decompressedContentBuf *bytes.Buffer) error {
304+
for f := uint32(0); f < *numFiles; f++ {
288305
// Read filename length
289306
var nameLength uint32
290-
err = binary.Read(decompressedContentBuf, binary.BigEndian, &nameLength)
307+
err := binary.Read(decompressedContentBuf, binary.BigEndian, &nameLength)
291308
if err != nil {
292-
return nil, err
309+
return err
293310
}
294311
// Read filename
295312
name := make([]byte, nameLength)
296313
_, err = decompressedContentBuf.Read(name)
297314
if err != nil {
298-
return nil, err
315+
return err
299316
}
300317
// Read content length
301318
var contentLength uint32
302319
err = binary.Read(decompressedContentBuf, binary.BigEndian, &contentLength)
303320
if err != nil {
304-
return nil, err
321+
return err
305322
}
306323
// Read content
307324
content := make([]byte, contentLength)
308325
_, err = decompressedContentBuf.Read(content)
309326
if err != nil {
310-
return nil, err
327+
return err
311328
}
312-
files = append(files, utils.File{
329+
*files = append(*files, utils.File{
313330
Name: string(name),
314331
Content: content,
315332
})
316333
}
334+
return nil
335+
}
317336

318-
return files, nil
337+
func readHuffManCodes(codes *map[rune]string, buf *bytes.Buffer, codesLength uint32) error {
338+
for i := uint32(0); i < codesLength; i++ {
339+
var char rune
340+
err := binary.Read(buf, binary.BigEndian, &char)
341+
if err != nil {
342+
return err
343+
}
344+
var codeLength uint32
345+
err = binary.Read(buf, binary.BigEndian, &codeLength)
346+
if err != nil {
347+
return err
348+
}
349+
code := make([]byte, codeLength)
350+
_, err = buf.Read(code)
351+
if err != nil {
352+
return err
353+
}
354+
(*codes)[char] = string(code)
355+
}
356+
return nil
319357
}
320358

321359
// compressData compresses data using Huffman codes.
322-
func compressData(data []byte, codes map[rune]string) []byte {
360+
func compressData(data []byte, codes map[rune]string) ([]byte, error) {
323361
var buf bytes.Buffer
324362
var bitBuffer uint64
325363
var bitLength uint
326364
for _, b := range data {
327365
code := codes[rune(b)]
328-
for _, bit := range code {
329-
bitBuffer <<= 1
330-
bitLength++
331-
if bit == '1' {
332-
bitBuffer |= 1
333-
}
334-
if bitLength == 64 {
335-
err := binary.Write(&buf, binary.BigEndian, bitBuffer)
336-
if err != nil {
337-
return nil
338-
}
339-
bitBuffer = 0
340-
bitLength = 0
341-
}
366+
err := compressBits(&code, &buf, &bitBuffer, &bitLength)
367+
if err != nil {
368+
return nil, err
342369
}
343370
}
344371
if bitLength > 0 {
345372
bitBuffer <<= (64 - bitLength)
346373
err := binary.Write(&buf, binary.BigEndian, bitBuffer)
347374
if err != nil {
348-
return nil
375+
return nil, fmt.Errorf("failed to write bit buffer: %v", err)
349376
}
350377
}
351-
return buf.Bytes()
378+
return buf.Bytes(), nil
379+
}
380+
381+
func compressBits(code *string, buf *bytes.Buffer, bitBuffer *uint64, bitLength *uint) error {
382+
for _, bit := range *code {
383+
*bitBuffer <<= 1
384+
*bitLength++
385+
if bit == '1' {
386+
*bitBuffer |= 1
387+
}
388+
if *bitLength == 64 {
389+
err := binary.Write(buf, binary.BigEndian, bitBuffer)
390+
if err != nil {
391+
return fmt.Errorf("failed to write bit buffer: %v", err)
392+
}
393+
*bitBuffer = 0
394+
*bitLength = 0
395+
}
396+
}
397+
return nil
352398
}
353399

354400
// decompressData decompresses data using Huffman codes.
355401
func decompressData(data []byte, root *Node) []byte {
402+
356403
var buf bytes.Buffer
404+
357405
if root == nil {
358406
return buf.Bytes()
359407
}

0 commit comments

Comments
 (0)