Namespaced file_utils

This commit is contained in:
Marc Gilleron 2022-01-09 02:21:49 +00:00
parent e08d0ff448
commit 3101d7f092
6 changed files with 88 additions and 89 deletions

View File

@ -1,21 +1,23 @@
#include "file_utils.h"
#include "../server/voxel_server.h"
const char *to_string(VoxelFileResult res) {
namespace zylann {
const char *to_string(FileResult res) {
switch (res) {
case VOXEL_FILE_OK:
case FILE_OK:
return "OK";
case VOXEL_FILE_CANT_OPEN:
case FILE_CANT_OPEN:
return "Can't open";
case VOXEL_FILE_DOES_NOT_EXIST:
case FILE_DOES_NOT_EXIST:
return "Doesn't exist";
case VOXEL_FILE_UNEXPECTED_EOF:
case FILE_UNEXPECTED_EOF:
return "Unexpected end of file";
case VOXEL_FILE_INVALID_MAGIC:
case FILE_INVALID_MAGIC:
return "Invalid magic";
case VOXEL_FILE_INVALID_VERSION:
case FILE_INVALID_VERSION:
return "Invalid version";
case VOXEL_FILE_INVALID_DATA:
case FILE_INVALID_DATA:
return "Invalid data";
default:
CRASH_NOW();
@ -23,25 +25,25 @@ const char *to_string(VoxelFileResult res) {
}
}
VoxelFileResult check_magic_and_version(
FileResult check_magic_and_version(
FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version) {
uint8_t magic[5] = { '\0' };
int count = f->get_buffer(magic, 4);
if (count != 4) {
return VOXEL_FILE_UNEXPECTED_EOF;
return FILE_UNEXPECTED_EOF;
}
for (int i = 0; i < 4; ++i) {
if (magic[i] != expected_magic[i]) {
return VOXEL_FILE_INVALID_MAGIC;
return FILE_INVALID_MAGIC;
}
}
out_version = f->get_8();
if (out_version != expected_version) {
return VOXEL_FILE_INVALID_VERSION;
return FILE_INVALID_VERSION;
}
return VOXEL_FILE_OK;
return FILE_OK;
}
Error check_directory_created(const String &directory_path) {
@ -67,8 +69,6 @@ Error check_directory_created(const String &directory_path) {
return OK;
}
namespace zylann {
// TODO Write tests
// Makes the file bigger to move the half from the current position further,

View File

@ -5,6 +5,8 @@
#include <core/io/dir_access.h>
#include <core/io/file_access.h>
namespace zylann {
inline Vector3i get_vec3u8(FileAccess *f) {
Vector3i v;
v.x = f->get_8();
@ -33,24 +35,21 @@ inline void store_vec3u32(FileAccess *f, const Vector3i v) {
f->store_32(v.z);
}
enum VoxelFileResult {
VOXEL_FILE_OK = 0,
VOXEL_FILE_CANT_OPEN,
VOXEL_FILE_DOES_NOT_EXIST,
VOXEL_FILE_UNEXPECTED_EOF,
VOXEL_FILE_INVALID_MAGIC,
VOXEL_FILE_INVALID_VERSION,
VOXEL_FILE_INVALID_DATA
enum FileResult {
FILE_OK = 0,
FILE_CANT_OPEN,
FILE_DOES_NOT_EXIST,
FILE_UNEXPECTED_EOF,
FILE_INVALID_MAGIC,
FILE_INVALID_VERSION,
FILE_INVALID_DATA
};
const char *to_string(VoxelFileResult res);
VoxelFileResult check_magic_and_version(
const char *to_string(FileResult res);
FileResult check_magic_and_version(
FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version);
Error check_directory_created(const String &directory_path);
// TODO Wrap other stuff in that
namespace zylann {
void insert_bytes(FileAccess *f, size_t count, size_t temp_chunk_size = 512);
} // namespace zylann

View File

@ -138,8 +138,8 @@ VoxelStreamRegionFiles::EmergeResult VoxelStreamRegionFiles::_emerge_block(
}
if (!_meta_loaded) {
const VoxelFileResult load_res = load_meta();
if (load_res != VOXEL_FILE_OK) {
const FileResult load_res = load_meta();
if (load_res != FILE_OK) {
// No block was ever saved
return EMERGE_OK_FALLBACK;
}
@ -191,8 +191,8 @@ void VoxelStreamRegionFiles::_immerge_block(VoxelBufferInternal &voxel_buffer, V
if (!_meta_loaded) {
// If it's not loaded, always try to load meta file first if it exists already,
// because we could want to save blocks without reading any
VoxelFileResult load_res = load_meta();
if (load_res != VOXEL_FILE_OK && load_res != VOXEL_FILE_CANT_OPEN) {
FileResult load_res = load_meta();
if (load_res != FILE_OK && load_res != FILE_CANT_OPEN) {
// The file is present but there is a problem with it
String meta_path = _directory_path.plus_file(META_FILE_NAME);
ERR_PRINT(String("Could not read {0}: error {1}").format(varray(meta_path, ::to_string(load_res))));
@ -205,8 +205,8 @@ void VoxelStreamRegionFiles::_immerge_block(VoxelBufferInternal &voxel_buffer, V
for (unsigned int i = 0; i < _meta.channel_depths.size(); ++i) {
_meta.channel_depths[i] = voxel_buffer.get_channel_depth(i);
}
VoxelFileResult err = save_meta();
ERR_FAIL_COND(err != VOXEL_FILE_OK);
FileResult err = save_meta();
ERR_FAIL_COND(err != FILE_OK);
}
// Verify format
@ -266,8 +266,8 @@ static bool depth_from_json_variant(Variant &v, VoxelBufferInternal::Depth &d) {
return true;
}
VoxelFileResult VoxelStreamRegionFiles::save_meta() {
ERR_FAIL_COND_V(_directory_path == "", VOXEL_FILE_CANT_OPEN);
FileResult VoxelStreamRegionFiles::save_meta() {
ERR_FAIL_COND_V(_directory_path == "", FILE_CANT_OPEN);
Dictionary d;
d["version"] = _meta.version;
@ -291,7 +291,7 @@ VoxelFileResult VoxelStreamRegionFiles::save_meta() {
Error err = check_directory_created(_directory_path);
if (err != OK) {
ERR_PRINT("Could not save meta");
return VOXEL_FILE_CANT_OPEN;
return FILE_CANT_OPEN;
}
}
@ -302,7 +302,7 @@ VoxelFileResult VoxelStreamRegionFiles::save_meta() {
FileAccessRef f = FileAccess::open(meta_path, FileAccess::WRITE, &err);
if (!f) {
ERR_PRINT(String("Could not save {0}").format(varray(meta_path)));
return VOXEL_FILE_CANT_OPEN;
return FILE_CANT_OPEN;
}
f->store_string(json_string);
@ -310,7 +310,7 @@ VoxelFileResult VoxelStreamRegionFiles::save_meta() {
_meta_saved = true;
_meta_loaded = true;
return VOXEL_FILE_OK;
return FILE_OK;
}
static void migrate_region_meta_data(Dictionary &data) {
@ -334,8 +334,8 @@ static void migrate_region_meta_data(Dictionary &data) {
//}
}
VoxelFileResult VoxelStreamRegionFiles::load_meta() {
ERR_FAIL_COND_V(_directory_path == "", VOXEL_FILE_CANT_OPEN);
FileResult VoxelStreamRegionFiles::load_meta() {
ERR_FAIL_COND_V(_directory_path == "", FILE_CANT_OPEN);
// Ensure you cleanup previous world before loading another
CRASH_COND(_region_cache.size() > 0);
@ -348,7 +348,7 @@ VoxelFileResult VoxelStreamRegionFiles::load_meta() {
VoxelFileLockerRead file_rlock(meta_path);
FileAccessRef f = FileAccess::open(meta_path, FileAccess::READ, &err);
if (!f) {
return VOXEL_FILE_CANT_OPEN;
return FILE_CANT_OPEN;
}
json_string = f->get_as_utf8_string();
}
@ -364,34 +364,33 @@ VoxelFileResult VoxelStreamRegionFiles::load_meta() {
if (json_err != OK) {
ERR_PRINT(
String("Error when parsing {0}: line {1}: {2}").format(varray(meta_path, json_err_line, json_err_msg)));
return VOXEL_FILE_INVALID_DATA;
return FILE_INVALID_DATA;
}
Dictionary d = res;
migrate_region_meta_data(d);
Meta meta;
ERR_FAIL_COND_V(!u8_from_json_variant(d["version"], meta.version), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["block_size_po2"], meta.block_size_po2), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["region_size_po2"], meta.region_size_po2), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["lod_count"], meta.lod_count), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u32_from_json_variant(d["sector_size"], meta.sector_size), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["version"], meta.version), FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["block_size_po2"], meta.block_size_po2), FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["region_size_po2"], meta.region_size_po2), FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u8_from_json_variant(d["lod_count"], meta.lod_count), FILE_INVALID_DATA);
ERR_FAIL_COND_V(!u32_from_json_variant(d["sector_size"], meta.sector_size), FILE_INVALID_DATA);
ERR_FAIL_COND_V(meta.version < 0, VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(meta.version < 0, FILE_INVALID_DATA);
Array channel_depths_data = d["channel_depths"];
ERR_FAIL_COND_V(channel_depths_data.size() != VoxelBuffer::MAX_CHANNELS, VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(channel_depths_data.size() != VoxelBuffer::MAX_CHANNELS, FILE_INVALID_DATA);
for (int i = 0; i < channel_depths_data.size(); ++i) {
ERR_FAIL_COND_V(
!depth_from_json_variant(channel_depths_data[i], meta.channel_depths[i]), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!depth_from_json_variant(channel_depths_data[i], meta.channel_depths[i]), FILE_INVALID_DATA);
}
ERR_FAIL_COND_V(!check_meta(meta), VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(!check_meta(meta), FILE_INVALID_DATA);
_meta = meta;
_meta_loaded = true;
_meta_saved = true;
return VOXEL_FILE_OK;
return FILE_OK;
}
bool VoxelStreamRegionFiles::check_meta(const Meta &meta) {
@ -609,7 +608,7 @@ void VoxelStreamRegionFiles::_convert_files(Meta new_meta) {
int lod;
};
ERR_FAIL_COND(old_stream->load_meta() != VOXEL_FILE_OK);
ERR_FAIL_COND(old_stream->load_meta() != FILE_OK);
std::vector<PositionAndLod> old_region_list;
Meta old_meta = old_stream->_meta;
@ -655,7 +654,7 @@ void VoxelStreamRegionFiles::_convert_files(Meta new_meta) {
}
_meta = new_meta;
ERR_FAIL_COND(save_meta() != VOXEL_FILE_OK);
ERR_FAIL_COND(save_meta() != FILE_OK);
const Vector3i old_block_size = Vector3iUtil::create(1 << old_meta.block_size_po2);
const Vector3i new_block_size = Vector3iUtil::create(1 << _meta.block_size_po2);
@ -854,7 +853,7 @@ void VoxelStreamRegionFiles::convert_files(Dictionary d) {
ERR_FAIL_COND_MSG(!check_meta(meta), "Invalid setting");
if (!_meta_loaded) {
if (load_meta() != VOXEL_FILE_OK) {
if (load_meta() != FILE_OK) {
// New stream, nothing to convert
_meta = meta;

View File

@ -67,8 +67,8 @@ private:
EmergeResult _emerge_block(zylann::voxel::VoxelBufferInternal &out_buffer, Vector3i origin_in_voxels, int lod);
void _immerge_block(zylann::voxel::VoxelBufferInternal &voxel_buffer, Vector3i origin_in_voxels, int lod);
VoxelFileResult save_meta();
VoxelFileResult load_meta();
zylann::FileResult save_meta();
zylann::FileResult load_meta();
Vector3i get_block_position_from_voxels(const Vector3i &origin_in_voxels) const;
Vector3i get_region_position_from_blocks(const Vector3i &block_position) const;
void close_all_regions();

View File

@ -4,7 +4,8 @@
#include <core/io/dir_access.h>
#include <core/io/file_access.h>
using namespace zylann::voxel;
using namespace zylann;
using namespace voxel;
namespace {
const uint8_t FORMAT_VERSION = 1;
@ -34,7 +35,7 @@ VoxelStream::Result VoxelStreamBlockFiles::emerge_block(
}
if (!_meta_loaded) {
if (load_meta() != VOXEL_FILE_OK) {
if (load_meta() != FILE_OK) {
return RESULT_ERROR;
}
}
@ -65,8 +66,8 @@ VoxelStream::Result VoxelStreamBlockFiles::emerge_block(
{
{
uint8_t version;
VoxelFileResult err = check_magic_and_version(f, FORMAT_VERSION, FORMAT_BLOCK_MAGIC, version);
if (err != VOXEL_FILE_OK) {
const FileResult err = check_magic_and_version(f, FORMAT_VERSION, FORMAT_BLOCK_MAGIC, version);
if (err != FILE_OK) {
memdelete(f);
ERR_PRINT(String("Invalid file header: ") + ::to_string(err));
return RESULT_ERROR;
@ -97,8 +98,8 @@ void VoxelStreamBlockFiles::immerge_block(VoxelBufferInternal &buffer, Vector3i
if (!_meta_loaded) {
// If it's not loaded, always try to load meta file first if it exists already,
// because we could want to save blocks without reading any
VoxelFileResult res = load_meta();
if (res != VOXEL_FILE_OK && res != VOXEL_FILE_CANT_OPEN) {
const FileResult res = load_meta();
if (res != FILE_OK && res != FILE_CANT_OPEN) {
// The file is present but there is a problem with it
String meta_path = _directory_path.plus_file(META_FILE_NAME);
ERR_PRINT(String("Could not read {0}: {1}").format(varray(meta_path, ::to_string(res))));
@ -111,8 +112,8 @@ void VoxelStreamBlockFiles::immerge_block(VoxelBufferInternal &buffer, Vector3i
for (unsigned int i = 0; i < _meta.channel_depths.size(); ++i) {
_meta.channel_depths[i] = buffer.get_channel_depth(i);
}
VoxelFileResult res = save_meta();
ERR_FAIL_COND(res != VOXEL_FILE_OK);
const FileResult res = save_meta();
ERR_FAIL_COND(res != FILE_OK);
}
// Check format
@ -177,7 +178,7 @@ int VoxelStreamBlockFiles::get_block_size_po2() const {
return _meta.block_size_po2;
}
VoxelFileResult VoxelStreamBlockFiles::save_meta() {
FileResult VoxelStreamBlockFiles::save_meta() {
CRASH_COND(_directory_path.is_empty());
// Make sure the directory exists
@ -185,7 +186,7 @@ VoxelFileResult VoxelStreamBlockFiles::save_meta() {
Error err = check_directory_created(_directory_path);
if (err != OK) {
ERR_PRINT("Could not save meta");
return VOXEL_FILE_CANT_OPEN;
return FILE_CANT_OPEN;
}
}
@ -195,7 +196,7 @@ VoxelFileResult VoxelStreamBlockFiles::save_meta() {
Error err;
VoxelFileLockerWrite file_wlock(meta_path);
FileAccess *f = FileAccess::open(meta_path, FileAccess::WRITE, &err);
ERR_FAIL_COND_V(f == nullptr, VOXEL_FILE_CANT_OPEN);
ERR_FAIL_COND_V(f == nullptr, FILE_CANT_OPEN);
f->store_buffer((uint8_t *)FORMAT_META_MAGIC, 4);
f->store_8(FORMAT_VERSION);
@ -212,20 +213,20 @@ VoxelFileResult VoxelStreamBlockFiles::save_meta() {
_meta_loaded = true;
_meta_saved = true;
return VOXEL_FILE_OK;
return FILE_OK;
}
VoxelFileResult VoxelStreamBlockFiles::load_or_create_meta() {
VoxelFileResult res = load_meta();
if (res == VOXEL_FILE_DOES_NOT_EXIST) {
VoxelFileResult save_result = save_meta();
ERR_FAIL_COND_V(save_result != VOXEL_FILE_OK, save_result);
return VOXEL_FILE_OK;
FileResult VoxelStreamBlockFiles::load_or_create_meta() {
const FileResult res = load_meta();
if (res == FILE_DOES_NOT_EXIST) {
const FileResult save_result = save_meta();
ERR_FAIL_COND_V(save_result != FILE_OK, save_result);
return FILE_OK;
}
return res;
}
VoxelFileResult VoxelStreamBlockFiles::load_meta() {
FileResult VoxelStreamBlockFiles::load_meta() {
CRASH_COND(_directory_path.is_empty());
String meta_path = _directory_path.plus_file(META_FILE_NAME);
@ -238,12 +239,12 @@ VoxelFileResult VoxelStreamBlockFiles::load_meta() {
// Had to add ERR_FILE_CANT_OPEN because that's what Godot actually returns when the file doesn't exist...
if (!_meta_saved && (open_result == ERR_FILE_NOT_FOUND || open_result == ERR_FILE_CANT_OPEN)) {
// This is a new terrain, save the meta we have and consider it current
return VOXEL_FILE_DOES_NOT_EXIST;
return FILE_DOES_NOT_EXIST;
}
ERR_FAIL_COND_V(!f, VOXEL_FILE_CANT_OPEN);
ERR_FAIL_COND_V(!f, FILE_CANT_OPEN);
VoxelFileResult check_result = check_magic_and_version(f.f, FORMAT_VERSION, FORMAT_META_MAGIC, meta.version);
if (check_result != VOXEL_FILE_OK) {
FileResult check_result = check_magic_and_version(f.f, FORMAT_VERSION, FORMAT_META_MAGIC, meta.version);
if (check_result != FILE_OK) {
return check_result;
}
@ -252,17 +253,17 @@ VoxelFileResult VoxelStreamBlockFiles::load_meta() {
for (unsigned int i = 0; i < meta.channel_depths.size(); ++i) {
uint8_t depth = f->get_8();
ERR_FAIL_COND_V(depth >= VoxelBufferInternal::DEPTH_COUNT, VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(depth >= VoxelBufferInternal::DEPTH_COUNT, FILE_INVALID_DATA);
meta.channel_depths[i] = (VoxelBufferInternal::Depth)depth;
}
ERR_FAIL_COND_V(meta.lod_count < 1 || meta.lod_count > 32, VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(meta.block_size_po2 < 1 || meta.block_size_po2 > 8, VOXEL_FILE_INVALID_DATA);
ERR_FAIL_COND_V(meta.lod_count < 1 || meta.lod_count > 32, FILE_INVALID_DATA);
ERR_FAIL_COND_V(meta.block_size_po2 < 1 || meta.block_size_po2 > 8, FILE_INVALID_DATA);
}
_meta_loaded = true;
_meta = meta;
return VOXEL_FILE_OK;
return FILE_OK;
}
String VoxelStreamBlockFiles::get_block_file_path(const Vector3i &block_pos, unsigned int lod) const {

View File

@ -29,9 +29,9 @@ protected:
static void _bind_methods();
private:
VoxelFileResult save_meta();
VoxelFileResult load_meta();
VoxelFileResult load_or_create_meta();
zylann::FileResult save_meta();
zylann::FileResult load_meta();
zylann::FileResult load_or_create_meta();
String get_block_file_path(const Vector3i &block_pos, unsigned int lod) const;
Vector3i get_block_position(const Vector3i &origin_in_voxels) const;