Improve/fix packed data API

- Enhance directory API
- Fix `FileAccess::exists()` not checking for PackedData being disabled
- Fix moving to the parent directory (`..`)
- Allow absolute paths in existence checks
This commit is contained in:
Pedro J. Estébanez 2020-07-27 12:06:40 +02:00
parent 4fdc3e683a
commit f38949a44d
3 changed files with 55 additions and 9 deletions

View File

@ -376,8 +376,14 @@ String DirAccessPack::get_drive(int p_drive) {
return ""; return "";
} }
Error DirAccessPack::change_dir(String p_dir) { PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
String nd = p_dir.replace("\\", "/"); String nd = p_dir.replace("\\", "/");
// Special handling since simplify_path() will forbid it
if (p_dir == "..") {
return current->parent;
}
bool absolute = false; bool absolute = false;
if (nd.begins_with("res://")) { if (nd.begins_with("res://")) {
nd = nd.replace_first("res://", ""); nd = nd.replace_first("res://", "");
@ -416,14 +422,22 @@ Error DirAccessPack::change_dir(String p_dir) {
} else if (pd->subdirs.has(p)) { } else if (pd->subdirs.has(p)) {
pd = pd->subdirs[p]; pd = pd->subdirs[p];
} else {
return nullptr;
}
}
return pd;
}
Error DirAccessPack::change_dir(String p_dir) {
PackedData::PackedDir *pd = _find_dir(p_dir);
if (pd) {
current = pd;
return OK;
} else { } else {
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
} }
}
current = pd;
return OK;
} }
String DirAccessPack::get_current_dir(bool p_include_drive) { String DirAccessPack::get_current_dir(bool p_include_drive) {
@ -441,13 +455,17 @@ String DirAccessPack::get_current_dir(bool p_include_drive) {
bool DirAccessPack::file_exists(String p_file) { bool DirAccessPack::file_exists(String p_file) {
p_file = fix_path(p_file); p_file = fix_path(p_file);
return current->files.has(p_file); PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir());
if (!pd) {
return false;
}
return pd->files.has(p_file.get_file());
} }
bool DirAccessPack::dir_exists(String p_dir) { bool DirAccessPack::dir_exists(String p_dir) {
p_dir = fix_path(p_dir); p_dir = fix_path(p_dir);
return current->subdirs.has(p_dir); return _find_dir(p_dir) != nullptr;
} }
Error DirAccessPack::make_dir(String p_dir) { Error DirAccessPack::make_dir(String p_dir) {

View File

@ -113,6 +113,9 @@ public:
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path); _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path); _FORCE_INLINE_ bool has_path(const String &p_path);
_FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
_FORCE_INLINE_ bool has_directory(const String &p_path);
PackedData(); PackedData();
~PackedData(); ~PackedData();
}; };
@ -189,6 +192,16 @@ bool PackedData::has_path(const String &p_path) {
return files.has(PathMD5(p_path.md5_buffer())); return files.has(PathMD5(p_path.md5_buffer()));
} }
bool PackedData::has_directory(const String &p_path) {
DirAccess *da = try_open_directory(p_path);
if (da) {
memdelete(da);
return true;
} else {
return false;
}
}
class DirAccessPack : public DirAccess { class DirAccessPack : public DirAccess {
PackedData::PackedDir *current; PackedData::PackedDir *current;
@ -196,6 +209,8 @@ class DirAccessPack : public DirAccess {
List<String> list_files; List<String> list_files;
bool cdir = false; bool cdir = false;
PackedData::PackedDir *_find_dir(String p_dir);
public: public:
virtual Error list_dir_begin(); virtual Error list_dir_begin();
virtual String get_next(); virtual String get_next();
@ -225,4 +240,13 @@ public:
~DirAccessPack() {} ~DirAccessPack() {}
}; };
DirAccess *PackedData::try_open_directory(const String &p_path) {
DirAccess *da = memnew(DirAccessPack());
if (da->change_dir(p_path) != OK) {
memdelete(da);
da = nullptr;
}
return da;
}
#endif // FILE_ACCESS_PACK_H #endif // FILE_ACCESS_PACK_H

View File

@ -51,7 +51,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
} }
bool FileAccess::exists(const String &p_name) { bool FileAccess::exists(const String &p_name) {
if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) { if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
return true; return true;
} }
@ -456,7 +456,7 @@ void FileAccess::store_double(double p_dest) {
} }
uint64_t FileAccess::get_modified_time(const String &p_file) { uint64_t FileAccess::get_modified_time(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0; return 0;
} }
@ -469,7 +469,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
} }
uint32_t FileAccess::get_unix_permissions(const String &p_file) { uint32_t FileAccess::get_unix_permissions(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0; return 0;
} }
@ -482,6 +482,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
} }
Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) { Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return ERR_UNAVAILABLE;
}
FileAccess *fa = create_for_path(p_file); FileAccess *fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");