Commit 5d5390ce5b3dcafbcd6f691b68c742ea8ee7f125
1 parent
20237a82
Showing
2 changed files
with
118 additions
and
2 deletions
nbt.c
1 | #include "nbt.h" | 1 | #include "nbt.h" |
2 | 2 | ||
3 | +ssize_t loadDB(const char* filename, void** data); | ||
3 | void destroyTag(Tag* t); | 4 | void destroyTag(Tag* t); |
4 | void destroyTagList(TagList* l); | 5 | void destroyTagList(TagList* l); |
5 | void destroyTagCompound(TagCompound* tc); | 6 | void destroyTagCompound(TagCompound* tc); |
7 | +size_t getTypeSize(uint8_t type); | ||
8 | +unsigned int parseList(void* addr, TagList* tl, uint8_t type); | ||
9 | +unsigned int parseCompound(void* addr, TagCompound* tc); | ||
6 | unsigned int parsePayload(void* addr,Tag* t); | 10 | unsigned int parsePayload(void* addr,Tag* t); |
11 | +unsigned int parseTag(void* addr, Tag* t); | ||
12 | + | ||
13 | +ssize_t loadDB(const char* filename, void** data) { | ||
14 | + if(access(filename,R_OK) == -1) { | ||
15 | + perror("Can't access file"); | ||
16 | + return -1; | ||
17 | + } | ||
18 | + | ||
19 | + struct stat sb; | ||
20 | + unsigned int pos = 0; | ||
21 | + | ||
22 | + int fd = open(filename,O_RDONLY); | ||
23 | + if(fd == -1) { | ||
24 | + perror("Can't open file"); | ||
25 | + return -2; | ||
26 | + } | ||
27 | + fstat(fd, &sb); | ||
28 | + | ||
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; | ||
37 | + ssize_t filesize = sb.st_size; | ||
38 | + | ||
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; | ||
86 | + } | ||
87 | + totalRead += nRead; | ||
88 | + } | ||
89 | + } | ||
90 | + *data = filedata; | ||
91 | + return filesize; | ||
92 | +} | ||
7 | 93 | ||
8 | void destroyTag(Tag* t) { | 94 | void destroyTag(Tag* t) { |
9 | if(t->nameLength) { | 95 | if(t->nameLength) { |
@@ -112,15 +198,33 @@ unsigned int parsePayload(void* addr,Tag* t) { | @@ -112,15 +198,33 @@ unsigned int parsePayload(void* addr,Tag* t) { | ||
112 | t->payloadLength = getTypeSize(t->type); // initially, then particularly for lists/compounds/strings | 198 | t->payloadLength = getTypeSize(t->type); // initially, then particularly for lists/compounds/strings |
113 | TagCompound* tc; | 199 | TagCompound* tc; |
114 | TagList *tl; | 200 | TagList *tl; |
201 | + uint16_t u16 = 0; | ||
202 | + uint32_t u32 = 0; | ||
203 | + uint64_t u64 = 0; | ||
115 | switch(t->type) { | 204 | switch(t->type) { |
116 | case TAG_BYTE: | 205 | case TAG_BYTE: |
206 | + t->payload = calloc(1,t->payloadLength); | ||
207 | + memcpy(t->payload,pos,t->payloadLength); | ||
208 | + pos += t->payloadLength; | ||
209 | + break; | ||
117 | case TAG_SHORT: | 210 | case TAG_SHORT: |
211 | + u16 = __bswap_16(*(uint16_t*)pos); | ||
212 | + t->payload = calloc(1,t->payloadLength); | ||
213 | + memcpy(t->payload,&u16,t->payloadLength); | ||
214 | + pos += t->payloadLength; | ||
215 | + break; | ||
118 | case TAG_INT: | 216 | case TAG_INT: |
119 | - case TAG_LONG: | ||
120 | case TAG_FLOAT: | 217 | case TAG_FLOAT: |
218 | + u32 = __bswap_32(*(uint32_t*)pos); | ||
219 | + t->payload = calloc(1,t->payloadLength); | ||
220 | + memcpy(t->payload,&u32,t->payloadLength); | ||
221 | + pos += t->payloadLength; | ||
222 | + break; | ||
223 | + case TAG_LONG: | ||
121 | case TAG_DOUBLE: | 224 | case TAG_DOUBLE: |
225 | + u64 = __bswap_64(*(uint64_t*)pos); | ||
122 | t->payload = calloc(1,t->payloadLength); | 226 | t->payload = calloc(1,t->payloadLength); |
123 | - memcpy(t->payload,pos,t->payloadLength); | 227 | + memcpy(t->payload,&u64,t->payloadLength); |
124 | pos += t->payloadLength; | 228 | pos += t->payloadLength; |
125 | break; | 229 | break; |
126 | case TAG_STRING: | 230 | case TAG_STRING: |
nbt.h
@@ -7,11 +7,22 @@ | @@ -7,11 +7,22 @@ | ||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <malloc.h> | 8 | #include <malloc.h> |
9 | #include <string.h> | 9 | #include <string.h> |
10 | +#include <unistd.h> | ||
11 | +#include <fcntl.h> | ||
12 | +#include <sys/stat.h> | ||
13 | +#include <errno.h> | ||
14 | +#include <zlib.h> | ||
10 | 15 | ||
11 | #ifndef REALLOC_SIZE | 16 | #ifndef REALLOC_SIZE |
12 | #define REALLOC_SIZE 10 | 17 | #define REALLOC_SIZE 10 |
13 | #endif | 18 | #endif |
14 | 19 | ||
20 | +#ifndef GZIP_BUFFER | ||
21 | +#define GZIP_BUFFER 4096 | ||
22 | +#endif | ||
23 | + | ||
24 | +#define GZIP_MAGIC 0x8B1F | ||
25 | + | ||
15 | typedef struct Tag { | 26 | typedef struct Tag { |
16 | uint8_t type; | 27 | uint8_t type; |
17 | char* name; | 28 | char* name; |
@@ -46,6 +57,7 @@ enum TAG { | @@ -46,6 +57,7 @@ enum TAG { | ||
46 | TAG_INTARRAY | 57 | TAG_INTARRAY |
47 | }; | 58 | }; |
48 | 59 | ||
60 | +ssize_t loadDB(const char* filename, void** data); | ||
49 | void destroyTag(Tag* t); | 61 | void destroyTag(Tag* t); |
50 | unsigned int parseTag(void* addr, Tag* t); | 62 | unsigned int parseTag(void* addr, Tag* t); |
51 | 63 |