ソースを参照

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
Pedro J. Estébanez 5 年 前
コミット
f38949a44d
3 ファイル変更55 行追加9 行削除
  1. 24 6
      core/io/file_access_pack.cpp
  2. 24 0
      core/io/file_access_pack.h
  3. 7 3
      core/os/file_access.cpp

+ 24 - 6
core/io/file_access_pack.cpp

@@ -376,8 +376,14 @@ String DirAccessPack::get_drive(int p_drive) {
 	return "";
 }
 
-Error DirAccessPack::change_dir(String p_dir) {
+PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
 	String nd = p_dir.replace("\\", "/");
+
+	// Special handling since simplify_path() will forbid it
+	if (p_dir == "..") {
+		return current->parent;
+	}
+
 	bool absolute = false;
 	if (nd.begins_with("res://")) {
 		nd = nd.replace_first("res://", "");
@@ -417,13 +423,21 @@ Error DirAccessPack::change_dir(String p_dir) {
 			pd = pd->subdirs[p];
 
 		} else {
-			return ERR_INVALID_PARAMETER;
+			return nullptr;
 		}
 	}
 
-	current = pd;
+	return pd;
+}
 
-	return OK;
+Error DirAccessPack::change_dir(String p_dir) {
+	PackedData::PackedDir *pd = _find_dir(p_dir);
+	if (pd) {
+		current = pd;
+		return OK;
+	} else {
+		return ERR_INVALID_PARAMETER;
+	}
 }
 
 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) {
 	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) {
 	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) {

+ 24 - 0
core/io/file_access_pack.h

@@ -113,6 +113,9 @@ public:
 	_FORCE_INLINE_ FileAccess *try_open_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();
 };
@@ -189,6 +192,16 @@ bool PackedData::has_path(const String &p_path) {
 	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 {
 	PackedData::PackedDir *current;
 
@@ -196,6 +209,8 @@ class DirAccessPack : public DirAccess {
 	List<String> list_files;
 	bool cdir = false;
 
+	PackedData::PackedDir *_find_dir(String p_dir);
+
 public:
 	virtual Error list_dir_begin();
 	virtual String get_next();
@@ -225,4 +240,13 @@ public:
 	~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

+ 7 - 3
core/os/file_access.cpp

@@ -51,7 +51,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
 }
 
 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;
 	}
 
@@ -456,7 +456,7 @@ void FileAccess::store_double(double p_dest) {
 }
 
 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;
 	}
 
@@ -469,7 +469,7 @@ uint64_t FileAccess::get_modified_time(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;
 	}
 
@@ -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) {
+	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);
 	ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");