tibia-rme/source/filehandle.cpp

718 lines
16 KiB
C++
Raw Permalink Normal View History

//////////////////////////////////////////////////////////////////////
// This file is part of Remere's Map Editor
//////////////////////////////////////////////////////////////////////
2020-07-30 11:42:28 -03:00
// Remere's Map Editor is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2016-09-29 19:24:45 -03:00
//
2020-07-30 11:42:28 -03:00
// Remere's Map Editor is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2020-07-30 11:42:28 -03:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
2016-09-29 19:24:45 -03:00
//
// You should have received a copy of the GNU General Public License
2020-07-30 11:42:28 -03:00
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////////
#include "main.h"
#include "filehandle.h"
uint8_t NodeFileWriteHandle::NODE_START = ::NODE_START;
uint8_t NodeFileWriteHandle::NODE_END = ::NODE_END;
uint8_t NodeFileWriteHandle::ESCAPE_CHAR = ::ESCAPE_CHAR;
2023-10-09 19:12:16 -07:00
bool FileHandle::seek(size_t offset, int origin) {
if (file) {
feat: synchronizing commits with the official rme repository (#36) * Show indicators for pickupable and moveable items * Fix: drawing always refreshing ui * Fix crash on invalid friend for wallbrush * Option to remove empty spawns * Draws position indicator, some code cleanup * Teleport copy/paste improvements * Fix flood fill * Add function to get minimap/8bit color * Small code cleanup * Cleanup Position * Code cleanup and small optimizations * Code cleanup * Code cleanup and small optimizations (#406) * Cleanup and cast functions. * Avoid adding a new Unique ID if it already exists * Code cleanup and small optimizations * More changes and cleanup * Changes and cleanup * Some changes * Fix copy position. * Only show uid/aid alert if it really changed * Add actions history panel * Does not draw tooltips on minimap mode * Use constexpr * Replace items fix (#408) * Draw grid small optimization * Small change in selection box and Fix #409 * Fix some xpm * Ingame box improvements, add lights support. * Fix go to previous position (#410) * Fix depot crash (#411) * Fix XPMs * Export minimap as .otmm (otclient format) or .png (#413) * Fix glitch after drawing secondary map * fix * Update about_window.cpp * sonar * fix Minimap and progress bar * fix erro load items.xml * fix * fix doodad brush * fix: slightly more accurate house size estimation * feat: update items.otb and items.xml * fix: bad merge * Revert "feat: update items.otb and items.xml" This reverts commit 40f1edc70f17c423282d546a41541a8fe9b92dcc. --------- Co-authored-by: Nailson <Mignari@users.noreply.github.com> Co-authored-by: wtver <51377408+maattch@users.noreply.github.com> Co-authored-by: Majesty <32709570+majestyotbr@users.noreply.github.com> Co-authored-by: Luan Santos <github@luan.sh>
2023-10-09 23:02:37 -03:00
return fseek(file, static_cast<long>(offset), origin) == 0;
}
return false;
}
2023-10-09 19:12:16 -07:00
size_t FileHandle::tell() {
if (file) {
feat: synchronizing commits with the official rme repository (#36) * Show indicators for pickupable and moveable items * Fix: drawing always refreshing ui * Fix crash on invalid friend for wallbrush * Option to remove empty spawns * Draws position indicator, some code cleanup * Teleport copy/paste improvements * Fix flood fill * Add function to get minimap/8bit color * Small code cleanup * Cleanup Position * Code cleanup and small optimizations * Code cleanup * Code cleanup and small optimizations (#406) * Cleanup and cast functions. * Avoid adding a new Unique ID if it already exists * Code cleanup and small optimizations * More changes and cleanup * Changes and cleanup * Some changes * Fix copy position. * Only show uid/aid alert if it really changed * Add actions history panel * Does not draw tooltips on minimap mode * Use constexpr * Replace items fix (#408) * Draw grid small optimization * Small change in selection box and Fix #409 * Fix some xpm * Ingame box improvements, add lights support. * Fix go to previous position (#410) * Fix depot crash (#411) * Fix XPMs * Export minimap as .otmm (otclient format) or .png (#413) * Fix glitch after drawing secondary map * fix * Update about_window.cpp * sonar * fix Minimap and progress bar * fix erro load items.xml * fix * fix doodad brush * fix: slightly more accurate house size estimation * feat: update items.otb and items.xml * fix: bad merge * Revert "feat: update items.otb and items.xml" This reverts commit 40f1edc70f17c423282d546a41541a8fe9b92dcc. --------- Co-authored-by: Nailson <Mignari@users.noreply.github.com> Co-authored-by: wtver <51377408+maattch@users.noreply.github.com> Co-authored-by: Majesty <32709570+majestyotbr@users.noreply.github.com> Co-authored-by: Luan Santos <github@luan.sh>
2023-10-09 23:02:37 -03:00
return ftell(file);
}
return 0;
}
2023-10-09 19:12:16 -07:00
void FileHandle::close() {
if (file) {
fclose(file);
file = nullptr;
}
}
2023-10-09 19:12:16 -07:00
std::string FileHandle::getErrorMessage() {
switch (error_code) {
case FILE_NO_ERROR:
return "No error";
case FILE_COULD_NOT_OPEN:
return "Could not open file";
case FILE_INVALID_IDENTIFIER:
return "File magic number not recognized";
case FILE_STRING_TOO_LONG:
return "Too long string encountered";
case FILE_READ_ERROR:
return "Failed to read from file";
case FILE_WRITE_ERROR:
return "Failed to write to file";
case FILE_SYNTAX_ERROR:
return "Node file syntax error";
case FILE_PREMATURE_END:
return "File end encountered unexpectedly";
}
if (file == nullptr) {
return "Could not open file (2)";
}
2023-10-09 19:12:16 -07:00
if (ferror(file)) {
return "Internal file error #" + i2s(ferror(file));
}
return "No error";
}
//=============================================================================
// File read handle
2023-10-09 19:12:16 -07:00
FileReadHandle::FileReadHandle(const std::string &name) :
file_size(0) {
#if defined __VISUALC__ && defined _UNICODE
file = _wfopen(string2wstring(name).c_str(), L"rb");
#else
file = fopen(name.c_str(), "rb");
#endif
2023-10-09 19:12:16 -07:00
if (!file || ferror(file)) {
error_code = FILE_COULD_NOT_OPEN;
} else {
fseek(file, 0, SEEK_END);
file_size = ftell(file);
fseek(file, 0, SEEK_SET);
}
}
2023-10-09 19:12:16 -07:00
FileReadHandle::~FileReadHandle() {
2015-12-06 11:42:37 -03:00
////
}
2023-10-09 19:12:16 -07:00
void FileReadHandle::close() {
file_size = 0;
FileHandle::close();
}
2023-10-09 19:12:16 -07:00
bool FileReadHandle::getRAW(uint8_t* ptr, size_t sz) {
size_t o = fread(ptr, 1, sz, file);
2023-10-09 19:12:16 -07:00
if (o != sz) {
error_code = FILE_READ_ERROR;
return false;
}
return true;
}
2023-10-09 19:12:16 -07:00
bool FileReadHandle::getRAW(std::string &str, size_t sz) {
str.resize(sz);
size_t o = fread(const_cast<char*>(str.data()), 1, sz, file);
2023-10-09 19:12:16 -07:00
if (o != sz) {
error_code = FILE_READ_ERROR;
return false;
}
return true;
}
2023-10-09 19:12:16 -07:00
bool FileReadHandle::getString(std::string &str) {
uint16_t sz;
2023-10-09 19:12:16 -07:00
if (!getU16(sz)) {
error_code = FILE_READ_ERROR;
return false;
}
return getRAW(str, sz);
}
2023-10-09 19:12:16 -07:00
bool FileReadHandle::getLongString(std::string &str) {
uint32_t sz;
2023-10-09 19:12:16 -07:00
if (!getU32(sz)) {
error_code = FILE_READ_ERROR;
return false;
}
return getRAW(str, sz);
}
//=============================================================================
// Node file read handle
NodeFileReadHandle::NodeFileReadHandle() :
last_was_start(false),
cache(nullptr),
cache_size(32768),
cache_length(0),
local_read_index(0),
2023-10-09 19:12:16 -07:00
root_node(nullptr) {
2015-12-06 11:42:37 -03:00
////
}
2023-10-09 19:12:16 -07:00
NodeFileReadHandle::~NodeFileReadHandle() {
while (!unused.empty()) {
free(unused.top());
unused.pop();
}
}
2023-10-09 19:12:16 -07:00
BinaryNode* NodeFileReadHandle::getNode(BinaryNode* parent) {
void* mem;
2023-10-09 19:12:16 -07:00
if (unused.empty()) {
mem = malloc(sizeof(BinaryNode));
} else {
mem = unused.top();
unused.pop();
}
2023-10-09 19:12:16 -07:00
return new (mem) BinaryNode(this, parent);
}
2023-10-09 19:12:16 -07:00
void NodeFileReadHandle::freeNode(BinaryNode* node) {
if (node) {
node->~BinaryNode();
unused.push(node);
}
}
//=============================================================================
// Memory based node file read handle
2023-10-09 19:12:16 -07:00
MemoryNodeFileReadHandle::MemoryNodeFileReadHandle(const uint8_t* data, size_t size) {
assign(data, size);
}
2023-10-09 19:12:16 -07:00
void MemoryNodeFileReadHandle::assign(const uint8_t* data, size_t size) {
freeNode(root_node);
root_node = nullptr;
// Highly volatile, but we know we're not gonna modify
cache = const_cast<uint8_t*>(data);
cache_size = cache_length = size;
local_read_index = 0;
}
2023-10-09 19:12:16 -07:00
MemoryNodeFileReadHandle::~MemoryNodeFileReadHandle() {
freeNode(root_node);
}
2023-10-09 19:12:16 -07:00
void MemoryNodeFileReadHandle::close() {
assign(nullptr, 0);
}
2023-10-09 19:12:16 -07:00
bool MemoryNodeFileReadHandle::renewCache() {
return false;
}
2023-10-09 19:12:16 -07:00
BinaryNode* MemoryNodeFileReadHandle::getRootNode() {
assert(root_node == nullptr); // You should never do this twice
local_read_index++; // Skip first NODE_START
last_was_start = true;
root_node = getNode(nullptr);
root_node->load();
return root_node;
}
//=============================================================================
// File based node file read handle
2023-10-09 19:12:16 -07:00
DiskNodeFileReadHandle::DiskNodeFileReadHandle(const std::string &name, const std::vector<std::string> &acceptable_identifiers) :
file_size(0) {
#if defined __VISUALC__ && defined _UNICODE
file = _wfopen(string2wstring(name).c_str(), L"rb");
#else
file = fopen(name.c_str(), "rb");
#endif
2023-10-09 19:12:16 -07:00
if (!file || ferror(file)) {
error_code = FILE_COULD_NOT_OPEN;
} else {
char ver[4];
2023-10-09 19:12:16 -07:00
if (fread(ver, 1, 4, file) != 4) {
fclose(file);
error_code = FILE_SYNTAX_ERROR;
return;
}
2016-09-29 19:24:45 -03:00
// 0x00 00 00 00 is accepted as a wildcard version
2023-10-09 19:12:16 -07:00
if (ver[0] != 0 || ver[1] != 0 || ver[2] != 0 || ver[3] != 0) {
bool accepted = false;
2023-10-09 19:12:16 -07:00
for (std::vector<std::string>::const_iterator id_iter = acceptable_identifiers.begin(); id_iter != acceptable_identifiers.end(); ++id_iter) {
if (memcmp(ver, id_iter->c_str(), 4) == 0) {
accepted = true;
break;
}
}
2023-10-09 19:12:16 -07:00
if (!accepted) {
fclose(file);
error_code = FILE_SYNTAX_ERROR;
return;
}
}
fseek(file, 0, SEEK_END);
file_size = ftell(file);
fseek(file, 4, SEEK_SET);
}
}
2023-10-09 19:12:16 -07:00
DiskNodeFileReadHandle::~DiskNodeFileReadHandle() {
close();
}
2023-10-09 19:12:16 -07:00
void DiskNodeFileReadHandle::close() {
freeNode(root_node);
file_size = 0;
FileHandle::close();
free(cache);
}
2023-10-09 19:12:16 -07:00
bool DiskNodeFileReadHandle::renewCache() {
if (!cache) {
cache = (uint8_t*)malloc(cache_size);
}
cache_length = fread(cache, 1, cache_size, file);
2023-10-09 19:12:16 -07:00
if (cache_length == 0 || ferror(file)) {
return false;
}
local_read_index = 0;
return true;
}
2023-10-09 19:12:16 -07:00
BinaryNode* DiskNodeFileReadHandle::getRootNode() {
assert(root_node == nullptr); // You should never do this twice
uint8_t first;
size_t numRead = fread(&first, 1, 1, file);
if (numRead != 1) {
error_code = FILE_READ_ERROR;
return nullptr;
}
if (first == NODE_START) {
root_node = getNode(nullptr);
root_node->load();
return root_node;
} else {
error_code = FILE_SYNTAX_ERROR;
return nullptr;
}
}
//=============================================================================
// Binary file node
BinaryNode::BinaryNode(NodeFileReadHandle* file, BinaryNode* parent) :
read_offset(0),
file(file),
parent(parent),
2023-10-09 19:12:16 -07:00
child(nullptr) {
2015-12-06 11:42:37 -03:00
////
}
2023-10-09 19:12:16 -07:00
BinaryNode::~BinaryNode() {
file->freeNode(child);
}
2023-10-09 19:12:16 -07:00
BinaryNode* BinaryNode::getChild() {
ASSERT(file);
ASSERT(child == nullptr);
2023-10-09 19:12:16 -07:00
if (file->last_was_start) {
child = file->getNode(this);
child->load();
return child;
}
2015-12-06 11:42:37 -03:00
return nullptr;
}
2023-10-09 19:12:16 -07:00
bool BinaryNode::getRAW(uint8_t* ptr, size_t sz) {
if (read_offset + sz > data.size()) {
read_offset = data.size();
return false;
}
memcpy(ptr, data.data() + read_offset, sz);
read_offset += sz;
return true;
}
2023-10-09 19:12:16 -07:00
bool BinaryNode::getRAW(std::string &str, size_t sz) {
if (read_offset + sz > data.size()) {
read_offset = data.size();
return false;
}
str.assign(data.data() + read_offset, sz);
read_offset += sz;
return true;
}
2023-10-09 19:12:16 -07:00
bool BinaryNode::getString(std::string &str) {
uint16_t len;
2023-10-09 19:12:16 -07:00
if (!getU16(len)) {
return false;
}
return getRAW(str, len);
}
2023-10-09 19:12:16 -07:00
bool BinaryNode::getLongString(std::string &str) {
uint32_t len;
2023-10-09 19:12:16 -07:00
if (!getU32(len)) {
return false;
}
return getRAW(str, len);
}
2023-10-09 19:12:16 -07:00
BinaryNode* BinaryNode::advance() {
// Advance this to the next position
ASSERT(file);
2023-10-09 19:12:16 -07:00
if (file->error_code != FILE_NO_ERROR) {
return nullptr;
2023-10-09 19:12:16 -07:00
}
2023-10-09 19:12:16 -07:00
if (child == nullptr) {
getChild();
}
// We need to move the cursor to the next node, since we're still iterating our child node!
2023-10-09 19:12:16 -07:00
while (child) {
// both functions modify ourselves and sets child to nullptr, so loop will be aborted
// possibly change to assignment ?
child->getChild();
child->advance();
}
2023-10-09 19:12:16 -07:00
if (file->last_was_start) {
return nullptr;
} else {
// Last was end (0xff)
// Read next byte to decide if there is another node following this
2023-10-09 19:12:16 -07:00
uint8_t*&cache = file->cache;
size_t &cache_length = file->cache_length;
size_t &local_read_index = file->local_read_index;
2016-09-29 19:24:45 -03:00
2023-10-09 19:12:16 -07:00
if (local_read_index >= cache_length) {
if (!file->renewCache()) {
// Failed to renew, exit
parent->child = nullptr;
file->freeNode(this);
return nullptr;
}
}
2016-09-29 19:24:45 -03:00
uint8_t op = cache[local_read_index];
++local_read_index;
2023-10-09 19:12:16 -07:00
if (op == NODE_START) {
// Another node follows this.
// Load this node as the next one
read_offset = 0;
data.clear();
load();
return this;
2023-10-09 19:12:16 -07:00
} else if (op == NODE_END) {
// End of this child-tree
parent->child = nullptr;
file->last_was_start = false;
file->freeNode(this);
return nullptr;
} else {
file->error_code = FILE_SYNTAX_ERROR;
return nullptr;
}
}
}
2023-10-09 19:12:16 -07:00
void BinaryNode::load() {
ASSERT(file);
// Read until next node starts
2023-10-09 19:12:16 -07:00
uint8_t*&cache = file->cache;
size_t &cache_length = file->cache_length;
size_t &local_read_index = file->local_read_index;
while (true) {
if (local_read_index >= cache_length) {
if (!file->renewCache()) {
// Failed to renew, exit
file->error_code = FILE_PREMATURE_END;
return;
}
}
2016-09-29 19:24:45 -03:00
uint8_t op = cache[local_read_index];
++local_read_index;
2023-10-09 19:12:16 -07:00
switch (op) {
case NODE_START: {
file->last_was_start = true;
return;
2015-12-06 11:42:37 -03:00
}
case NODE_END: {
file->last_was_start = false;
return;
2015-12-06 11:42:37 -03:00
}
2015-12-06 11:42:37 -03:00
case ESCAPE_CHAR: {
2023-10-09 19:12:16 -07:00
if (local_read_index >= cache_length) {
if (!file->renewCache()) {
// Failed to renew, exit
file->error_code = FILE_PREMATURE_END;
return;
}
}
2016-09-29 19:24:45 -03:00
op = cache[local_read_index];
++local_read_index;
2015-12-06 11:42:37 -03:00
break;
}
default:
break;
}
2023-10-09 19:12:16 -07:00
// std::cout << "Appending..." << std::endl;
data.append(1, op);
}
}
//=============================================================================
// node file binary write handle
2023-10-09 19:12:16 -07:00
FileWriteHandle::FileWriteHandle(const std::string &name) {
#if defined __VISUALC__ && defined _UNICODE
file = _wfopen(string2wstring(name).c_str(), L"wb");
#else
file = fopen(name.c_str(), "wb");
#endif
2023-10-09 19:12:16 -07:00
if (file == nullptr || ferror(file)) {
error_code = FILE_COULD_NOT_OPEN;
}
}
2023-10-09 19:12:16 -07:00
FileWriteHandle::~FileWriteHandle() {
2015-12-06 11:42:37 -03:00
////
}
2023-10-09 19:12:16 -07:00
bool FileWriteHandle::addString(const std::string &str) {
if (str.size() > 0xFFFF) {
error_code = FILE_STRING_TOO_LONG;
return false;
}
addU16(uint16_t(str.size()));
addRAW(str);
return true;
}
2023-10-09 19:12:16 -07:00
bool FileWriteHandle::addString(const char* str) {
size_t len = strlen(str);
2023-10-09 19:12:16 -07:00
if (len > 0xFFFF) {
error_code = FILE_STRING_TOO_LONG;
return false;
}
addU16(uint16_t(len));
fwrite(str, 1, len, file);
return true;
}
2023-10-09 19:12:16 -07:00
bool FileWriteHandle::addLongString(const std::string &str) {
addU32(uint32_t(str.size()));
addRAW(str);
return true;
}
2023-10-09 19:12:16 -07:00
bool FileWriteHandle::addRAW(const std::string &str) {
fwrite(str.c_str(), 1, str.size(), file);
return ferror(file) == 0;
}
2023-10-09 19:12:16 -07:00
bool FileWriteHandle::addRAW(const uint8_t* ptr, size_t sz) {
fwrite(ptr, 1, sz, file);
return ferror(file) == 0;
}
2023-10-09 19:12:16 -07:00
void FileWriteHandle::flush() {
if (file) {
feat: synchronizing commits with the official rme repository (#36) * Show indicators for pickupable and moveable items * Fix: drawing always refreshing ui * Fix crash on invalid friend for wallbrush * Option to remove empty spawns * Draws position indicator, some code cleanup * Teleport copy/paste improvements * Fix flood fill * Add function to get minimap/8bit color * Small code cleanup * Cleanup Position * Code cleanup and small optimizations * Code cleanup * Code cleanup and small optimizations (#406) * Cleanup and cast functions. * Avoid adding a new Unique ID if it already exists * Code cleanup and small optimizations * More changes and cleanup * Changes and cleanup * Some changes * Fix copy position. * Only show uid/aid alert if it really changed * Add actions history panel * Does not draw tooltips on minimap mode * Use constexpr * Replace items fix (#408) * Draw grid small optimization * Small change in selection box and Fix #409 * Fix some xpm * Ingame box improvements, add lights support. * Fix go to previous position (#410) * Fix depot crash (#411) * Fix XPMs * Export minimap as .otmm (otclient format) or .png (#413) * Fix glitch after drawing secondary map * fix * Update about_window.cpp * sonar * fix Minimap and progress bar * fix erro load items.xml * fix * fix doodad brush * fix: slightly more accurate house size estimation * feat: update items.otb and items.xml * fix: bad merge * Revert "feat: update items.otb and items.xml" This reverts commit 40f1edc70f17c423282d546a41541a8fe9b92dcc. --------- Co-authored-by: Nailson <Mignari@users.noreply.github.com> Co-authored-by: wtver <51377408+maattch@users.noreply.github.com> Co-authored-by: Majesty <32709570+majestyotbr@users.noreply.github.com> Co-authored-by: Luan Santos <github@luan.sh>
2023-10-09 23:02:37 -03:00
fflush(file);
}
}
//=============================================================================
// Disk based node file write handle
2023-10-09 19:12:16 -07:00
DiskNodeFileWriteHandle::DiskNodeFileWriteHandle(const std::string &name, const std::string &identifier) {
#if defined __VISUALC__ && defined _UNICODE
file = _wfopen(string2wstring(name).c_str(), L"wb");
#else
file = fopen(name.c_str(), "wb");
#endif
2023-10-09 19:12:16 -07:00
if (!file || ferror(file)) {
error_code = FILE_COULD_NOT_OPEN;
return;
}
2023-10-09 19:12:16 -07:00
if (identifier.length() != 4) {
error_code = FILE_INVALID_IDENTIFIER;
return;
}
fwrite(identifier.c_str(), 1, 4, file);
2023-10-09 19:12:16 -07:00
if (!cache) {
cache = (uint8_t*)malloc(cache_size + 1);
}
local_write_index = 0;
}
2023-10-09 19:12:16 -07:00
DiskNodeFileWriteHandle::~DiskNodeFileWriteHandle() {
close();
}
2023-10-09 19:12:16 -07:00
void DiskNodeFileWriteHandle::close() {
if (file) {
renewCache();
fclose(file);
file = nullptr;
error_code = FILE_NO_ERROR;
}
}
2023-10-09 19:12:16 -07:00
void DiskNodeFileWriteHandle::renewCache() {
if (cache) {
fwrite(cache, local_write_index, 1, file);
2023-10-09 19:12:16 -07:00
if (ferror(file) != 0) {
error_code = FILE_WRITE_ERROR;
}
} else {
2023-10-09 19:12:16 -07:00
cache = (uint8_t*)malloc(cache_size + 1);
}
local_write_index = 0;
}
//=============================================================================
// Memory based node file write handle
2023-10-09 19:12:16 -07:00
MemoryNodeFileWriteHandle::MemoryNodeFileWriteHandle() {
if (!cache) {
cache = (uint8_t*)malloc(cache_size + 1);
}
local_write_index = 0;
}
2023-10-09 19:12:16 -07:00
MemoryNodeFileWriteHandle::~MemoryNodeFileWriteHandle() {
close();
}
2023-10-09 19:12:16 -07:00
void MemoryNodeFileWriteHandle::reset() {
memset(cache, 0xAA, cache_size);
local_write_index = 0;
}
2023-10-09 19:12:16 -07:00
void MemoryNodeFileWriteHandle::close() {
free(cache);
cache = nullptr;
}
2023-10-09 19:12:16 -07:00
uint8_t* MemoryNodeFileWriteHandle::getMemory() {
return cache;
}
2023-10-09 19:12:16 -07:00
size_t MemoryNodeFileWriteHandle::getSize() {
return local_write_index;
}
2023-10-09 19:12:16 -07:00
void MemoryNodeFileWriteHandle::renewCache() {
if (cache) {
cache_size = cache_size * 2;
cache = (uint8_t*)realloc(cache, cache_size);
2023-10-09 19:12:16 -07:00
if (!cache) {
exit(1);
}
} else {
2023-10-09 19:12:16 -07:00
cache = (uint8_t*)malloc(cache_size + 1);
}
}
//=============================================================================
// Node file write handle
NodeFileWriteHandle::NodeFileWriteHandle() :
cache(nullptr),
cache_size(0x7FFF),
2023-10-09 19:12:16 -07:00
local_write_index(0) {
2015-12-06 11:42:37 -03:00
////
}
2023-10-09 19:12:16 -07:00
NodeFileWriteHandle::~NodeFileWriteHandle() {
2014-03-02 22:08:22 +01:00
free(cache);
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addNode(uint8_t nodetype) {
cache[local_write_index++] = NODE_START;
2023-10-09 19:12:16 -07:00
if (local_write_index >= cache_size) {
renewCache();
}
cache[local_write_index++] = nodetype;
2023-10-09 19:12:16 -07:00
if (local_write_index >= cache_size) {
renewCache();
}
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::endNode() {
cache[local_write_index++] = NODE_END;
2023-10-09 19:12:16 -07:00
if (local_write_index >= cache_size) {
renewCache();
}
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addU8(uint8_t u8) {
writeBytes(&u8, sizeof(u8));
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addByte(uint8_t u8) {
writeBytes(&u8, sizeof(u8));
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addU16(uint16_t u16) {
writeBytes(reinterpret_cast<uint8_t*>(&u16), sizeof(u16));
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addU32(uint32_t u32) {
writeBytes(reinterpret_cast<uint8_t*>(&u32), sizeof(u32));
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addU64(uint64_t u64) {
writeBytes(reinterpret_cast<uint8_t*>(&u64), sizeof(u64));
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addString(const std::string &str) {
if (str.size() > 0xFFFF) {
error_code = FILE_STRING_TOO_LONG;
return false;
}
addU16(uint16_t(str.size()));
addRAW((const uint8_t*)str.c_str(), str.size());
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addLongString(const std::string &str) {
addU32(uint32_t(str.size()));
addRAW((const uint8_t*)str.c_str(), str.size());
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addRAW(std::string &str) {
writeBytes(reinterpret_cast<uint8_t*>(const_cast<char*>(str.data())), str.size());
return error_code == FILE_NO_ERROR;
}
2023-10-09 19:12:16 -07:00
bool NodeFileWriteHandle::addRAW(const uint8_t* ptr, size_t sz) {
writeBytes(ptr, sz);
return error_code == FILE_NO_ERROR;
}