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 | \ No newline at end of file | 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 | \ No newline at end of file | 14 | \ No newline at end of file |
nbt.c
1 | #include "nbt.h" | 1 | #include "nbt.h" |
2 | +#include "compression.h" | ||
3 | +#include "chunk.h" | ||
2 | 4 | ||
3 | ssize_t loadDB(const char* filename, void** data); | 5 | ssize_t loadDB(const char* filename, void** data); |
4 | void destroyTag(Tag* t); | 6 | void destroyTag(Tag* t); |
@@ -26,67 +28,31 @@ ssize_t loadDB(const char* filename, void** data) { | @@ -26,67 +28,31 @@ ssize_t loadDB(const char* filename, void** data) { | ||
26 | } | 28 | } |
27 | fstat(fd, &sb); | 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 | void* filedata; | 31 | void* filedata; |
37 | ssize_t filesize = sb.st_size; | 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 | *data = filedata; | 56 | *data = filedata; |
91 | return filesize; | 57 | return filesize; |
92 | } | 58 | } |
@@ -190,6 +156,12 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { | @@ -190,6 +156,12 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { | ||
190 | pos += parseTag(pos,&list[numTags]); | 156 | pos += parseTag(pos,&list[numTags]); |
191 | } while(list[numTags++].type != TAG_END); | 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 | tc->list = list; | 165 | tc->list = list; |
194 | tc->numTags = numTags-1; | 166 | tc->numTags = numTags-1; |
195 | return pos - addr; | 167 | return pos - addr; |