Commit af20c8c87ba9b1c80ba02190393be183cf454719
1 parent
3f906bc9
Moved decompression function outside and changed it to work with buffers. Added compression function
Showing
3 changed files
with
161 additions
and
55 deletions
compression.c
0 → 100644
1 | +#include "compression.h" | |
2 | + | |
3 | +ssize_t inflateGzip(void* compData, size_t compDataLen, void** unCompData) { | |
4 | + unsigned int increase = compDataLen/2; | |
5 | + unsigned int uncompLength = compDataLen; // Later to be increased | |
6 | + | |
7 | + char* uncomp = (char*)calloc(uncompLength, sizeof(char)); | |
8 | + | |
9 | + z_stream strm; | |
10 | + strm.next_in = (Bytef*) compData; | |
11 | + strm.avail_in = compDataLen; | |
12 | + strm.total_out = 0; | |
13 | + strm.zalloc = Z_NULL; | |
14 | + strm.zfree = Z_NULL; | |
15 | + | |
16 | + if (inflateInit2(&strm, (16+MAX_WBITS)) != Z_OK) { | |
17 | + fprintf(stderr, "Unable to initialize zlib zstream for decompression\n"); | |
18 | + free(uncomp); | |
19 | + return -1; | |
20 | + } | |
21 | + | |
22 | + int err = Z_OK; | |
23 | + do { | |
24 | + // If our output buffer is too small | |
25 | + if(strm.total_out >= uncompLength ) { | |
26 | + // Increase size of output buffer | |
27 | + void* newptr = realloc(uncomp,uncompLength + increase); | |
28 | + if(newptr == NULL) { | |
29 | + fprintf(stderr,"Unable to request memory realloc\n"); | |
30 | + inflateEnd(&strm); | |
31 | + free(uncomp); | |
32 | + return -2; | |
33 | + } | |
34 | + uncomp = newptr; | |
35 | + uncompLength += increase; | |
36 | + } | |
37 | + | |
38 | + strm.next_out = (Bytef *) (uncomp + strm.total_out); | |
39 | + strm.avail_out = uncompLength - strm.total_out; | |
40 | + | |
41 | + // Inflate another chunk. | |
42 | + err = inflate (&strm, Z_SYNC_FLUSH); | |
43 | + if(err != Z_OK && err != Z_STREAM_END) { | |
44 | + fprintf(stderr, "zlib error: %d.\n", err); | |
45 | + inflateEnd(&strm); | |
46 | + free(uncomp); | |
47 | + return -3; | |
48 | + } | |
49 | + } while(err != Z_STREAM_END); | |
50 | + uncompLength = strm.total_out; | |
51 | + | |
52 | + if(inflateEnd(&strm) != Z_OK) { | |
53 | + fprintf(stderr,"Error while deallocating libz zstream\n"); | |
54 | + free(uncomp); | |
55 | + return -4; | |
56 | + } | |
57 | + | |
58 | + *unCompData = uncomp; | |
59 | + return uncompLength; | |
60 | +} | |
61 | + | |
62 | +ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData) { | |
63 | + unsigned int compLength = unCompDataLen; | |
64 | + unsigned int increase = compLength/4; | |
65 | + char* comp = (char*)calloc(compLength, sizeof(char)); | |
66 | + | |
67 | + z_stream strm; | |
68 | + strm.next_in = (Bytef*) unCompData; | |
69 | + strm.avail_in = unCompDataLen; | |
70 | + strm.total_out = 0; | |
71 | + strm.zalloc = Z_NULL; | |
72 | + strm.zfree = Z_NULL; | |
73 | + | |
74 | + if(deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16+MAX_WBITS),8 , Z_DEFAULT_STRATEGY) != Z_OK) { | |
75 | + fprintf(stderr, "Unable to initialize zlib zstream for compression\n"); | |
76 | + free(comp); | |
77 | + return -1; | |
78 | + } | |
79 | + | |
80 | + int err = Z_OK; | |
81 | + do { | |
82 | + // If our output buffer is too small | |
83 | + if (strm.total_out >= compLength) { | |
84 | + // Increase size of output buffer | |
85 | + void* newptr = realloc(comp, compLength + increase); | |
86 | + if(newptr == NULL) { | |
87 | + fprintf(stderr,"Unable to request memory realloc\n"); | |
88 | + deflateEnd(&strm); | |
89 | + free(comp); | |
90 | + return -2; | |
91 | + } | |
92 | + comp = newptr; | |
93 | + compLength += increase; | |
94 | + } | |
95 | + | |
96 | + strm.next_out = (Bytef*) (comp + strm.total_out); | |
97 | + strm.avail_out = compLength - strm.total_out; | |
98 | + | |
99 | + // deflate another chunk | |
100 | + err = deflate(&strm, Z_FINISH); | |
101 | + if(err != Z_OK && err != Z_STREAM_END) { | |
102 | + fprintf(stderr, "Error while deflating buffer\n"); | |
103 | + deflateEnd(&strm); | |
104 | + free(comp); | |
105 | + return -3; | |
106 | + } | |
107 | + } while(err != Z_STREAM_END); | |
108 | + compLength = strm.total_out; | |
109 | + | |
110 | + if(deflateEnd(&strm) != Z_OK) { | |
111 | + fprintf(stderr,"Error while deallocating libz zstream\n"); | |
112 | + free(comp); | |
113 | + return -4; | |
114 | + } | |
115 | + | |
116 | + // Set OS Flag to 0x00: "FAT filesystem (MS-DOS, OS/2, NT/Win32)" | |
117 | + comp[OS_FLAG_OFFSET] = 0x00; | |
118 | + | |
119 | + *compData = comp; | |
120 | + return compLength; | |
121 | +} | |
0 | 122 | \ No newline at end of file | ... | ... |
compression.h
0 → 100644
1 | +#ifndef _COMPRESSION_H | |
2 | +#define _COMPRESSION_H | |
3 | + | |
4 | +#include <stdlib.h> | |
5 | +#include <zlib.h> | |
6 | +#include <stdio.h> | |
7 | + | |
8 | +#define OS_FLAG_OFFSET 0x9 | |
9 | + | |
10 | +ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData); | |
11 | +ssize_t inflateGzip(void* compData, size_t compDataLen, void** unCompData); | |
12 | + | |
13 | +#endif | |
0 | 14 | \ No newline at end of file | ... | ... |
nbt.c
1 | 1 | #include "nbt.h" |
2 | +#include "compression.h" | |
3 | +#include "chunk.h" | |
2 | 4 | |
3 | 5 | ssize_t loadDB(const char* filename, void** data); |
4 | 6 | void destroyTag(Tag* t); |
... | ... | @@ -26,67 +28,31 @@ ssize_t loadDB(const char* filename, void** data) { |
26 | 28 | } |
27 | 29 | fstat(fd, &sb); |
28 | 30 | |
29 | - uint16_t header = 0; | |
30 | - if(pread(fd,&header,sizeof(uint16_t),0) == -1) { | |
31 | - perror("Unable to read header"); | |
32 | - close(fd); | |
33 | - return -3; | |
34 | - } | |
35 | - | |
36 | 31 | void* filedata; |
37 | 32 | ssize_t filesize = sb.st_size; |
38 | 33 | |
39 | - if(header == GZIP_MAGIC) { | |
40 | - close(fd); | |
41 | - filedata = calloc(GZIP_BUFFER,sizeof(char)); | |
42 | - gzFile file = gzopen(filename,"r"); | |
43 | - if(!file) { | |
44 | - perror("Failed to gzopen() file"); | |
45 | - free(filedata); | |
46 | - return -4; | |
47 | - } | |
48 | - int err; | |
49 | - int nRead; | |
50 | - size_t totalBytes = 0; | |
51 | - while((nRead = gzread(file, filedata+totalBytes, GZIP_BUFFER)) != 0) { | |
52 | - totalBytes += nRead; | |
53 | - if(!(totalBytes % GZIP_BUFFER)) { | |
54 | - void* newptr = realloc(filedata,totalBytes + GZIP_BUFFER); | |
55 | - if(newptr == NULL) { | |
56 | - perror("Unable to realloc for decompression"); | |
57 | - gzclose(file); | |
58 | - free(filedata); | |
59 | - return -6; | |
60 | - } | |
61 | - filedata = newptr; | |
62 | - } | |
63 | - } | |
64 | - if(!gzeof(file)) { | |
65 | - const char * errorStr; | |
66 | - errorStr = gzerror(file, &err); | |
67 | - fprintf(stderr, "libz error: %s.\n", errorStr); | |
68 | - gzclose(file); | |
69 | - free(filedata); | |
70 | - return -5; | |
71 | - } | |
72 | - filesize = totalBytes; | |
73 | - gzclose (file); | |
74 | - } else { | |
75 | - filedata = malloc(filesize); | |
76 | - ssize_t nRead = 0; | |
77 | - size_t totalRead = 0; | |
78 | - | |
79 | - while((nRead = read(fd,filedata+totalRead,filesize-totalRead))) { | |
80 | - if(nRead == -1) { | |
81 | - if(errno == EINTR) { | |
82 | - continue; | |
83 | - } | |
84 | - perror("Error reading file"); | |
85 | - return -7; | |
34 | + filedata = malloc(filesize); | |
35 | + ssize_t nRead = 0; | |
36 | + size_t totalRead = 0; | |
37 | + | |
38 | + while((nRead = read(fd,filedata+totalRead,filesize-totalRead))) { | |
39 | + if(nRead == -1) { | |
40 | + if(errno == EINTR) { | |
41 | + continue; | |
86 | 42 | } |
87 | - totalRead += nRead; | |
43 | + perror("Error reading file"); | |
44 | + return -7; | |
88 | 45 | } |
46 | + totalRead += nRead; | |
89 | 47 | } |
48 | + | |
49 | + if(*(uint16_t*)filedata == GZIP_MAGIC) { | |
50 | + void* decompressedFileData; | |
51 | + filesize = inflateGzip(filedata,filesize,&decompressedFileData); | |
52 | + free(filedata); | |
53 | + filedata = decompressedFileData; | |
54 | + } | |
55 | + | |
90 | 56 | *data = filedata; |
91 | 57 | return filesize; |
92 | 58 | } |
... | ... | @@ -190,6 +156,12 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { |
190 | 156 | pos += parseTag(pos,&list[numTags]); |
191 | 157 | } while(list[numTags++].type != TAG_END); |
192 | 158 | |
159 | + void* newptr = reallocarray(list, numTags, sizeof(Tag)); | |
160 | + if(!newptr) { | |
161 | + fprintf(stderr,"Unable to request memory realloc\n"); | |
162 | + } | |
163 | + list = newptr; | |
164 | + | |
193 | 165 | tc->list = list; |
194 | 166 | tc->numTags = numTags-1; |
195 | 167 | return pos - addr; | ... | ... |