Commit 5d5390ce5b3dcafbcd6f691b68c742ea8ee7f125

Authored by Imanol-Mikel Barba Sabariego
1 parent 20237a82

Implementing libz handling and native type representations (Closes #3 and #1)

Showing 2 changed files with 118 additions and 2 deletions
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:
@@ -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