bool FileLoader::openFile(const char* filename, bool write, bool caching /*= false*/) { if(write) { m_file = fopen(filename, "wb"); if(m_file) { uint32_t version = 0; writeData(&version, sizeof(version), false); return true; } else{ m_lastError = ERROR_CAN_NOT_CREATE; return false; } } else { m_file = fopen(filename, "rb"); if(m_file){ uint32_t version; fread(&version, sizeof(version), 1, m_file); if(version > 0){ fclose(m_file); m_file = NULL; m_lastError = ERROR_INVALID_FILE_VERSION; return false; } else{ if(caching){ m_use_cache = true; fseek(m_file, 0, SEEK_END); int file_size = ftell(m_file); m_cache_size = std::min(32768, std::max(file_size/20, 8192)) & ~0x1FFF; } //parse nodes if(safeSeek(4)){ delete m_root; m_root = new NodeStruct(); m_root->start = 4; int byte; if(safeSeek(4) && readByte(byte) && byte == NODE_START){ bool ret = parseNode(m_root); return ret; } else{ return false; } } else{ m_lastError = ERROR_INVALID_FORMAT; return false; } } } else{ m_lastError = ERROR_CAN_NOT_OPEN; return false; } } }
bool FileLoader::openFile(const char* filename, const char* accept_identifier) { m_file = fopen(filename, "rb"); if (!m_file) { m_lastError = ERROR_CAN_NOT_OPEN; return false; } char identifier[4]; if (fread(identifier, 1, 4, m_file) < 4) { fclose(m_file); m_file = nullptr; m_lastError = ERROR_EOF; return false; } // The first four bytes must either match the accept identifier or be 0x00000000 (wildcard) if (memcmp(identifier, accept_identifier, 4) != 0 && memcmp(identifier, "\0\0\0\0", 4) != 0) { fclose(m_file); m_file = nullptr; m_lastError = ERROR_INVALID_FILE_VERSION; return false; } fseek(m_file, 0, SEEK_END); int32_t file_size = ftell(m_file); m_cache_size = std::min<uint32_t>(32768, std::max<uint32_t>(file_size / 20, 8192)) & ~0x1FFF; if (!safeSeek(4)) { m_lastError = ERROR_INVALID_FORMAT; return false; } delete m_root; m_root = new NodeStruct(); m_root->start = 4; int32_t byte; if (safeSeek(4) && readByte(byte) && byte == NODE_START) { return parseNode(m_root); } return false; }
bool FileLoader::parseNode(NODE node) { int32_t byte; int32_t pos; NODE currentNode = node; while(1) { //read node type if(readByte(byte)) { currentNode->type = byte; bool setPropsSize = false; while(1) { //search child and next node if(readByte(byte)) { if(byte == NODE_START) { //child node start if(safeTell(pos)) { NODE childNode = new NodeStruct(); childNode->start = pos; setPropsSize = true; currentNode->propsSize = pos - currentNode->start - 2; currentNode->child = childNode; if(!parseNode(childNode)) return false; } else return false; } else if(byte == NODE_END) { //current node end if(!setPropsSize) { if(safeTell(pos)) currentNode->propsSize = pos - currentNode->start - 2; else return false; } if(readByte(byte)) { if(byte == NODE_START) { //starts next node if(safeTell(pos)) { NODE nextNode = new NodeStruct(); nextNode->start = pos; currentNode->next = nextNode; currentNode = nextNode; break; } else return false; } else if(byte == NODE_END) { //up 1 level and move 1 position back if(safeTell(pos) && safeSeek(pos)) return true; else return false; } else { //wrong format m_lastError = ERROR_INVALID_FORMAT; return false; } } else { //end of file? return true; } } else if(byte == ESCAPE_CHAR) { if(!readByte(byte)) return false; } } else return false; } } else return false; } }
bool FileLoader::parseNode(NODE node) { int32_t byte, pos; NODE currentNode = node; while (readByte(byte)) { currentNode->type = byte; bool setPropsSize = false; while (true) { if (!readByte(byte)) { return false; } bool skipNode = false; switch (byte) { case NODE_START: { //child node start if (!safeTell(pos)) { return false; } NODE childNode = new NodeStruct(); childNode->start = pos; currentNode->propsSize = pos - currentNode->start - 2; currentNode->child = childNode; setPropsSize = true; if (!parseNode(childNode)) { return false; } break; } case NODE_END: { //current node end if (!setPropsSize) { if (!safeTell(pos)) { return false; } currentNode->propsSize = pos - currentNode->start - 2; } if (!readByte(byte)) { return true; } switch (byte) { case NODE_START: { //starts next node if (!safeTell(pos)) { return false; } skipNode = true; NODE nextNode = new NodeStruct(); nextNode->start = pos; currentNode->next = nextNode; currentNode = nextNode; break; } case NODE_END: return safeTell(pos) && safeSeek(pos); default: m_lastError = ERROR_INVALID_FORMAT; return false; } break; } case ESCAPE_CHAR: { if (!readByte(byte)) { return false; } break; } default: break; } if (skipNode) { break; } } } return false; }
bool FileLoader::openFile(const char* filename, const char* accept_identifier, bool write, bool caching /*= false*/) { if(write) { m_file = fopen(filename, "wb"); if(!m_file) { m_lastError = ERROR_CAN_NOT_CREATE; return false; } uint32_t version = 0; writeData(&version, sizeof(version), false); return true; } m_file = fopen(filename, "rb"); if(!m_file) { m_lastError = ERROR_CAN_NOT_OPEN; return false; } char identifier[4]; if(fread(identifier, 1, 4, m_file) < 4) { fclose(m_file); m_file = NULL; m_lastError = ERROR_EOF; return false; } // The first four bytes must either match the accept identifier or be 0x00000000 (wildcard) if(memcmp(identifier, accept_identifier, 4) != 0 && memcmp(identifier, "\0\0\0\0", 4) != 0) { fclose(m_file); m_file = NULL; m_lastError = ERROR_INVALID_FILE_VERSION; return false; } if(caching) { m_use_cache = true; fseek(m_file, 0, SEEK_END); int32_t file_size = ftell(m_file); m_cache_size = std::min(32768, std::max(file_size/20, 8192)) & ~0x1FFF; } if(!safeSeek(4)) { m_lastError = ERROR_INVALID_FORMAT; return false; } delete m_root; m_root = new NodeStruct(); m_root->start = 4; int32_t byte; if(safeSeek(4) && readByte(byte) && byte == NODE_START) return parseNode(m_root); return false; }