#include "Base.h" #include "GPBDecoder.h" namespace gameplay { GPBDecoder::GPBDecoder(void) : _file(NULL), _outFile(NULL) { } GPBDecoder::~GPBDecoder(void) { } void GPBDecoder::readBinary(const std::string& filepath) { // open files _file = fopen(filepath.c_str(), "rb"); std::string outfilePath = filepath; outfilePath += ".xml"; _outFile = fopen(outfilePath.c_str(), "w"); // read and write files assert(validateHeading()); fprintf(_outFile, "\n"); readRefs(); fprintf(_outFile, "\n"); // close files fclose(_outFile); _outFile = NULL; fclose(_file); _file = NULL; } bool GPBDecoder::validateHeading() { const size_t HEADING_SIZE = 9; const char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' }; char heading[HEADING_SIZE]; for (size_t i = 0; i < HEADING_SIZE; ++i) { if (heading[i] != identifier[i]) { return false; } } // read version unsigned char version[2]; fread(version, sizeof(unsigned char), 2, _file); // don't care about version return true; } void GPBDecoder::readRefs() { fprintf(_outFile, "\n"); // read number of refs unsigned int refCount = 0; assert(read(&refCount)); for (size_t i = 0; i < refCount; ++i) { readRef(); } fprintf(_outFile, "\n"); } void GPBDecoder::readRef() { std::string xref = readString(_file); unsigned int type = 0, offset = 0; assert(read(&type)); assert(read(&offset)); fprintf(_outFile, "\n"); fprintfElement(_outFile, "xref", xref); fprintfElement(_outFile, "type", type); fprintfElement(_outFile, "offset", offset); fprintf(_outFile, "\n"); } bool GPBDecoder::read(unsigned int* ptr) { return fread(ptr, sizeof(unsigned int), 1, _file) == 1; } std::string GPBDecoder::readString(FILE* fp) { unsigned int length; if (fread(&length, 4, 1, fp) != 1) { return std::string(); } char* str = new char[length + 1]; if (length > 0) { if (fread(str, 1, length, fp) != length) { delete[] str; return std::string(); } } str[length] = '\0'; std::string result(str); delete[] str; return result; } }