| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  file_access.cpp                                                       */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "file_access.h"
 | 
					
						
							| 
									
										
										
										
											2024-11-07 12:32:02 +02:00
										 |  |  | #include "file_access.compat.inc"
 | 
					
						
							| 
									
										
										
										
											2017-04-28 18:29:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2019-07-11 15:21:47 +02:00
										 |  |  | #include "core/crypto/crypto_core.h"
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | #include "core/io/file_access_compressed.h"
 | 
					
						
							|  |  |  | #include "core/io/file_access_encrypted.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include "core/io/file_access_pack.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "core/io/marshalls.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/os/os.h"
 | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | #include "core/os/time.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | Ref<FileAccess> FileAccess::create(AccessType p_access) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr); | 
					
						
							| 
									
										
										
										
											2023-10-19 14:35:10 +03:00
										 |  |  | 	ERR_FAIL_NULL_V(create_func[p_access], nullptr); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> ret = create_func[p_access](); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ret->_set_access_type(p_access); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool FileAccess::exists(const String &p_name) { | 
					
						
							| 
									
										
										
										
											2020-07-27 12:06:40 +02:00
										 |  |  | 	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 20:11:10 -04:00
										 |  |  | 	// Using file_exists because it's faster than trying to open the file.
 | 
					
						
							|  |  |  | 	Ref<FileAccess> ret = create_for_path(p_name); | 
					
						
							|  |  |  | 	return ret->file_exists(p_name); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileAccess::_set_access_type(AccessType p_access) { | 
					
						
							|  |  |  | 	_access_type = p_access; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | Ref<FileAccess> FileAccess::create_for_path(const String &p_path) { | 
					
						
							|  |  |  | 	Ref<FileAccess> ret; | 
					
						
							| 
									
										
										
										
											2024-11-15 16:14:38 +01:00
										 |  |  | 	if (p_path.begins_with("res://") || p_path.begins_with("uid://")) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ret = create(ACCESS_RESOURCES); | 
					
						
							|  |  |  | 	} else if (p_path.begins_with("user://")) { | 
					
						
							|  |  |  | 		ret = create(ACCESS_USERDATA); | 
					
						
							| 
									
										
										
										
											2023-10-19 14:35:10 +03:00
										 |  |  | 	} else if (p_path.begins_with("pipe://")) { | 
					
						
							|  |  |  | 		ret = create(ACCESS_PIPE); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		ret = create(ACCESS_FILESYSTEM); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) { | 
					
						
							|  |  |  | 	const String ERROR_COMMON_PREFIX = "Error while creating temporary file"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 20:00:55 -03:00
										 |  |  | 	if (!p_prefix.is_empty() && !p_prefix.is_valid_filename()) { | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | 		*r_error = ERR_FILE_BAD_PATH; | 
					
						
							|  |  |  | 		ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 20:00:55 -03:00
										 |  |  | 	if (!p_extension.is_empty() && !p_extension.is_valid_filename()) { | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | 		*r_error = ERR_FILE_BAD_PATH; | 
					
						
							|  |  |  | 		ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const String TEMP_DIR = OS::get_singleton()->get_temp_path(); | 
					
						
							|  |  |  | 	String extension = p_extension.trim_prefix("."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint32_t suffix_i = 0; | 
					
						
							|  |  |  | 	String path; | 
					
						
							|  |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2024-05-28 12:55:07 +02:00
										 |  |  | 		String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:"); | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | 		datetime += itos(Time::get_singleton()->get_ticks_usec()); | 
					
						
							|  |  |  | 		String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : ""); | 
					
						
							|  |  |  | 		path = TEMP_DIR.path_join((p_prefix.is_empty() ? "" : p_prefix + "-") + suffix + (extension.is_empty() ? "" : "." + extension)); | 
					
						
							|  |  |  | 		if (!DirAccess::exists(path)) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		suffix_i += 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Error err; | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// Create file first with WRITE mode.
 | 
					
						
							|  |  |  | 		// Otherwise, it would fail to open with a READ mode.
 | 
					
						
							|  |  |  | 		Ref<FileAccess> ret = FileAccess::open(path, FileAccess::ModeFlags::WRITE, &err); | 
					
						
							|  |  |  | 		if (err != OK) { | 
					
						
							|  |  |  | 			*r_error = err; | 
					
						
							|  |  |  | 			ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: could not create "%s".)", ERROR_COMMON_PREFIX, path)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ret->flush(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Open then the temp file with the correct mode flag.
 | 
					
						
							|  |  |  | 	Ref<FileAccess> ret = FileAccess::open(path, p_mode_flags, &err); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		*r_error = err; | 
					
						
							|  |  |  | 		ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: could not open "%s".)", ERROR_COMMON_PREFIX, path)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ret.is_valid()) { | 
					
						
							|  |  |  | 		ret->_is_temp_file = true; | 
					
						
							|  |  |  | 		ret->_temp_keep_after_use = p_keep; | 
					
						
							|  |  |  | 		ret->_temp_path = ret->get_path_absolute(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*r_error = OK; | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<FileAccess> FileAccess::_create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep) { | 
					
						
							|  |  |  | 	return create_temp(p_mode_flags, p_prefix, p_extension, p_keep, &last_file_open_error); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileAccess::_delete_temp() { | 
					
						
							|  |  |  | 	if (!_is_temp_file || _temp_keep_after_use) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!FileAccess::exists(_temp_path)) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DirAccess::remove_absolute(_temp_path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Error FileAccess::reopen(const String &p_path, int p_mode_flags) { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	return open_internal(p_path, p_mode_flags); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	//try packed data first
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> ret; | 
					
						
							| 
									
										
										
										
											2025-02-20 11:08:16 +02:00
										 |  |  | 	if (!(p_mode_flags & WRITE) && !(p_mode_flags & SKIP_PACK) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ret = PackedData::get_singleton()->try_open_path(p_path); | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 		if (ret.is_valid()) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (r_error) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				*r_error = OK; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return ret; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ret = create_for_path(p_path); | 
					
						
							| 
									
										
										
										
											2025-02-20 11:08:16 +02:00
										 |  |  | 	Error err = ret->open_internal(p_path, p_mode_flags & ~SKIP_PACK); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (r_error) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		*r_error = err; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (err != OK) { | 
					
						
							| 
									
										
										
										
											2022-04-12 10:12:40 +03:00
										 |  |  | 		ret.unref(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | Ref<FileAccess> FileAccess::_open(const String &p_path, ModeFlags p_mode_flags) { | 
					
						
							|  |  |  | 	Error err = OK; | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = open(p_path, p_mode_flags, &err); | 
					
						
							|  |  |  | 	last_file_open_error = err; | 
					
						
							|  |  |  | 	if (err) { | 
					
						
							|  |  |  | 		return Ref<FileAccess>(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 12:32:02 +02:00
										 |  |  | Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv) { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	Ref<FileAccess> fa = _open(p_path, p_mode_flags); | 
					
						
							|  |  |  | 	if (fa.is_null()) { | 
					
						
							|  |  |  | 		return fa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccessEncrypted> fae; | 
					
						
							|  |  |  | 	fae.instantiate(); | 
					
						
							| 
									
										
										
										
											2024-11-07 12:32:02 +02:00
										 |  |  | 	Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ, true, p_iv); | 
					
						
							| 
									
										
										
										
											2023-02-21 16:58:55 +02:00
										 |  |  | 	last_file_open_error = err; | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	if (err) { | 
					
						
							|  |  |  | 		return Ref<FileAccess>(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fae; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<FileAccess> FileAccess::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) { | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = _open(p_path, p_mode_flags); | 
					
						
							|  |  |  | 	if (fa.is_null()) { | 
					
						
							|  |  |  | 		return fa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccessEncrypted> fae; | 
					
						
							|  |  |  | 	fae.instantiate(); | 
					
						
							|  |  |  | 	Error err = fae->open_and_parse_password(fa, p_pass, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ); | 
					
						
							| 
									
										
										
										
											2023-02-21 16:58:55 +02:00
										 |  |  | 	last_file_open_error = err; | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	if (err) { | 
					
						
							|  |  |  | 		return Ref<FileAccess>(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fae; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<FileAccess> FileAccess::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) { | 
					
						
							|  |  |  | 	Ref<FileAccessCompressed> fac; | 
					
						
							|  |  |  | 	fac.instantiate(); | 
					
						
							|  |  |  | 	fac->configure("GCPF", (Compression::Mode)p_compress_mode); | 
					
						
							|  |  |  | 	Error err = fac->open_internal(p_path, p_mode_flags); | 
					
						
							| 
									
										
										
										
											2023-02-21 16:58:55 +02:00
										 |  |  | 	last_file_open_error = err; | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	if (err) { | 
					
						
							|  |  |  | 		return Ref<FileAccess>(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fac; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error FileAccess::get_open_error() { | 
					
						
							|  |  |  | 	return last_file_open_error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) { | 
					
						
							|  |  |  | 	return create_func[p_access]; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 20:06:03 +02:00
										 |  |  | FileAccess::AccessType FileAccess::get_access_type() const { | 
					
						
							|  |  |  | 	return _access_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | String FileAccess::fix_path(const String &p_path) const { | 
					
						
							| 
									
										
										
										
											2024-11-15 16:14:38 +01:00
										 |  |  | 	// Helper used by file accesses that use a single filesystem.
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-28 12:15:00 +02:00
										 |  |  | 	String r_path = p_path.replace_char('\\', '/'); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (_access_type) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case ACCESS_RESOURCES: { | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | 			if (ProjectSettings::get_singleton()) { | 
					
						
							| 
									
										
										
										
											2024-11-15 16:14:38 +01:00
										 |  |  | 				if (r_path.begins_with("uid://")) { | 
					
						
							| 
									
										
										
										
											2025-06-11 12:43:32 +02:00
										 |  |  | 					ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(r_path); | 
					
						
							|  |  |  | 					if (ResourceUID::get_singleton()->has_id(uid)) { | 
					
						
							|  |  |  | 						r_path = ResourceUID::get_singleton()->get_id_path(uid); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						r_path.clear(); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2024-11-15 16:14:38 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				if (r_path.begins_with("res://")) { | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | 					String resource_path = ProjectSettings::get_singleton()->get_resource_path(); | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 					if (!resource_path.is_empty()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						return r_path.replace("res:/", resource_path); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					return r_path.replace("res://", ""); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case ACCESS_USERDATA: { | 
					
						
							|  |  |  | 			if (r_path.begins_with("user://")) { | 
					
						
							| 
									
										
										
										
											2017-11-17 15:25:22 +01:00
										 |  |  | 				String data_dir = OS::get_singleton()->get_user_data_dir(); | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 				if (!data_dir.is_empty()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					return r_path.replace("user:/", data_dir); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return r_path.replace("user://", ""); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2023-10-19 14:35:10 +03:00
										 |  |  | 		case ACCESS_PIPE: { | 
					
						
							|  |  |  | 			return r_path; | 
					
						
							|  |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case ACCESS_FILESYSTEM: { | 
					
						
							|  |  |  | 			return r_path; | 
					
						
							|  |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2020-05-10 13:00:47 +02:00
										 |  |  | 		case ACCESS_MAX: | 
					
						
							|  |  |  | 			break; // Can't happen, but silences warning
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return r_path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* these are all implemented for ease of porting, then can later be optimized */ | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | uint8_t FileAccess::get_8() const { | 
					
						
							|  |  |  | 	uint8_t data = 0; | 
					
						
							|  |  |  | 	get_buffer(&data, sizeof(uint8_t)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	return data; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | uint16_t FileAccess::get_16() const { | 
					
						
							|  |  |  | 	uint16_t data = 0; | 
					
						
							|  |  |  | 	get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t)); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		data = BSWAP16(data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		data = BSWAP16(data); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	return data; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | uint32_t FileAccess::get_32() const { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	uint32_t data = 0; | 
					
						
							|  |  |  | 	get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t)); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		data = BSWAP32(data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		data = BSWAP32(data); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	return data; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | uint64_t FileAccess::get_64() const { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	uint64_t data = 0; | 
					
						
							|  |  |  | 	get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t)); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		data = BSWAP64(data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		data = BSWAP64(data); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	return data; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-01 23:41:13 -03:00
										 |  |  | float FileAccess::get_half() const { | 
					
						
							|  |  |  | 	return Math::half_to_float(get_16()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | float FileAccess::get_float() const { | 
					
						
							|  |  |  | 	MarshallFloat m; | 
					
						
							|  |  |  | 	m.i = get_32(); | 
					
						
							|  |  |  | 	return m.f; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | real_t FileAccess::get_real() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (real_is_double) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return get_double(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return get_float(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | Variant FileAccess::get_var(bool p_allow_objects) const { | 
					
						
							|  |  |  | 	uint32_t len = get_32(); | 
					
						
							| 
									
										
										
										
											2022-11-28 11:00:48 +02:00
										 |  |  | 	Vector<uint8_t> buff = get_buffer(len); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const uint8_t *r = buff.ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Variant v; | 
					
						
							|  |  |  | 	Error err = decode_variant(v, &r[0], len, nullptr, p_allow_objects); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to encode Variant."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | double FileAccess::get_double() const { | 
					
						
							|  |  |  | 	MarshallDouble m; | 
					
						
							|  |  |  | 	m.l = get_64(); | 
					
						
							|  |  |  | 	return m.d; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-28 21:46:48 -03:00
										 |  |  | String FileAccess::get_token() const { | 
					
						
							|  |  |  | 	CharString token; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 02:17:09 +01:00
										 |  |  | 	uint8_t c = get_8(); | 
					
						
							| 
									
										
										
										
											2017-05-28 21:46:48 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (!eof_reached()) { | 
					
						
							|  |  |  | 		if (c <= ' ') { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (token.length()) { | 
					
						
							| 
									
										
										
										
											2017-05-28 21:46:48 -03:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-05-28 21:46:48 -03:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2024-12-14 02:17:09 +01:00
										 |  |  | 			token += char(c); | 
					
						
							| 
									
										
										
										
											2017-05-28 21:46:48 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		c = get_8(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return String::utf8(token.get_data()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | class CharBuffer { | 
					
						
							|  |  |  | 	Vector<char> vector; | 
					
						
							|  |  |  | 	char stack_buffer[256]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 17:38:46 +01:00
										 |  |  | 	char *buffer = nullptr; | 
					
						
							| 
									
										
										
										
											2025-05-19 09:53:53 -07:00
										 |  |  | 	int64_t capacity = 0; | 
					
						
							|  |  |  | 	int64_t written = 0; | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bool grow() { | 
					
						
							| 
									
										
										
										
											2025-05-19 09:53:53 -07:00
										 |  |  | 		if (vector.resize(next_power_of_2((uint64_t)1 + (uint64_t)written)) != OK) { | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (buffer == stack_buffer) { // first chunk?
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-19 09:53:53 -07:00
										 |  |  | 			for (int64_t i = 0; i < written; i++) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 				vector.write[i] = stack_buffer[i]; | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buffer = vector.ptrw(); | 
					
						
							|  |  |  | 		capacity = vector.size(); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(written >= capacity, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	_FORCE_INLINE_ CharBuffer() : | 
					
						
							|  |  |  | 			buffer(stack_buffer), | 
					
						
							| 
									
										
										
										
											2025-02-04 17:35:39 +01:00
										 |  |  | 			capacity(std::size(stack_buffer)) { | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ void push_back(char c) { | 
					
						
							|  |  |  | 		if (written >= capacity) { | 
					
						
							|  |  |  | 			ERR_FAIL_COND(!grow()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buffer[written++] = c; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ const char *get_data() const { | 
					
						
							|  |  |  | 		return buffer; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | String FileAccess::get_line() const { | 
					
						
							| 
									
										
										
										
											2017-12-13 20:38:21 +01:00
										 |  |  | 	CharBuffer line; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 02:17:09 +01:00
										 |  |  | 	uint8_t c = get_8(); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (!eof_reached()) { | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | 		if (c == '\r' || c == '\n' || c == '\0' || get_error() != OK) { | 
					
						
							|  |  |  | 			if (c == '\r') { | 
					
						
							|  |  |  | 				// Check for Windows-style EOL.
 | 
					
						
							|  |  |  | 				const uint64_t prev_pos = get_position() - 1; | 
					
						
							|  |  |  | 				if (unlikely(get_8() != '\n')) { | 
					
						
							|  |  |  | 					// HACK: We can't simply check the next value in a vacuum, so we risk triggering
 | 
					
						
							|  |  |  | 					//  an EOL false-positive in the unlikely event that this `\r` was the final
 | 
					
						
							|  |  |  | 					//  value of the file. Unilaterally work around by re-reading the *previous*
 | 
					
						
							|  |  |  | 					//  byte (the starting `\r`) to ensure `get_error()` returns `OK`.
 | 
					
						
							|  |  |  | 					const_cast<FileAccess *>(this)->seek(prev_pos); | 
					
						
							|  |  |  | 					get_8(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			line.push_back(0); | 
					
						
							|  |  |  | 			return String::utf8(line.get_data()); | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2024-12-14 02:17:09 +01:00
										 |  |  | 			line.push_back(char(c)); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		c = get_8(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	line.push_back(0); | 
					
						
							|  |  |  | 	return String::utf8(line.get_data()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-13 12:53:24 +01:00
										 |  |  | Vector<String> FileAccess::get_csv_line(const String &p_delim) const { | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(p_delim.length() != 1, Vector<String>(), "Only single character delimiters are supported to parse CSV lines."); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(p_delim[0] == '"', Vector<String>(), "The double quotation mark character (\") is not supported as a delimiter for CSV lines."); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 	String line; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// CSV can support entries with line breaks as long as they are enclosed
 | 
					
						
							|  |  |  | 	// in double quotes. So our "line" might be more than a single line in the
 | 
					
						
							|  |  |  | 	// text file.
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int qc = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (eof_reached()) { | 
					
						
							| 
									
										
										
										
											2018-12-16 07:09:33 +03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 		line += get_line() + "\n"; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		qc = 0; | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 		for (int i = 0; i < line.length(); i++) { | 
					
						
							|  |  |  | 			if (line[i] == '"') { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				qc++; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} while (qc % 2); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 	// Remove the extraneous newline we've added above.
 | 
					
						
							|  |  |  | 	line = line.substr(0, line.length() - 1); | 
					
						
							| 
									
										
										
										
											2016-04-16 15:12:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Vector<String> strings; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bool in_quote = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	String current; | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 	for (int i = 0; i < line.length(); i++) { | 
					
						
							|  |  |  | 		char32_t c = line[i]; | 
					
						
							|  |  |  | 		// A delimiter ends the current entry, unless it's in a quoted string.
 | 
					
						
							| 
									
										
										
										
											2018-11-13 12:53:24 +01:00
										 |  |  | 		if (!in_quote && c == p_delim[0]) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			strings.push_back(current); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			current = String(); | 
					
						
							|  |  |  | 		} else if (c == '"') { | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 			// Doubled quotes are escapes for intentional quotes in the string.
 | 
					
						
							|  |  |  | 			if (line[i + 1] == '"' && in_quote) { | 
					
						
							|  |  |  | 				current += '"'; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				i++; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				in_quote = !in_quote; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-08-04 11:20:36 +02:00
										 |  |  | 			current += c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-19 19:50:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (in_quote) { | 
					
						
							|  |  |  | 		WARN_PRINT(vformat("Reached end of file before closing '\"' in CSV file '%s'.", get_path())); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	strings.push_back(current); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return strings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | String FileAccess::get_as_text() const { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	uint64_t original_pos = get_position(); | 
					
						
							|  |  |  | 	const_cast<FileAccess *>(this)->seek(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | 	String text = get_as_utf8_string(); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	const_cast<FileAccess *>(this)->seek(original_pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-28 11:00:48 +02:00
										 |  |  | Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	Vector<uint8_t> data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0."); | 
					
						
							|  |  |  | 	if (p_length == 0) { | 
					
						
							|  |  |  | 		return data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Error err = data.resize(p_length); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length)); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	uint8_t *w = data.ptrw(); | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 	int64_t len = get_buffer(w, p_length); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (len < p_length) { | 
					
						
							|  |  |  | 		data.resize(len); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | String FileAccess::get_as_utf8_string() const { | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 	Vector<uint8_t> sourcef; | 
					
						
							| 
									
										
										
										
											2021-05-25 07:58:49 +01:00
										 |  |  | 	uint64_t len = get_length(); | 
					
						
							| 
									
										
										
										
											2019-03-03 16:50:41 -03:00
										 |  |  | 	sourcef.resize(len + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 18:06:54 -03:00
										 |  |  | 	uint8_t *w = sourcef.ptrw(); | 
					
						
							| 
									
										
										
										
											2019-03-26 18:51:13 +01:00
										 |  |  | 	uint64_t r = get_buffer(w, len); | 
					
						
							| 
									
										
										
										
											2019-03-03 16:50:41 -03:00
										 |  |  | 	ERR_FAIL_COND_V(r != len, String()); | 
					
						
							|  |  |  | 	w[len] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String s; | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | 	s.append_utf8((const char *)w, len); | 
					
						
							| 
									
										
										
										
											2019-03-03 16:50:41 -03:00
										 |  |  | 	return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_8(uint8_t p_dest) { | 
					
						
							|  |  |  | 	return store_buffer(&p_dest, sizeof(uint8_t)); | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_16(uint16_t p_dest) { | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		p_dest = BSWAP16(p_dest); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		p_dest = BSWAP16(p_dest); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_32(uint32_t p_dest) { | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		p_dest = BSWAP32(p_dest); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		p_dest = BSWAP32(p_dest); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_64(uint64_t p_dest) { | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #ifdef BIG_ENDIAN_ENABLED
 | 
					
						
							|  |  |  | 	if (!big_endian) { | 
					
						
							|  |  |  | 		p_dest = BSWAP64(p_dest); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-05-20 14:58:03 +02:00
										 |  |  | 	if (big_endian) { | 
					
						
							| 
									
										
										
										
											2024-05-20 18:07:27 +02:00
										 |  |  | 		p_dest = BSWAP64(p_dest); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-04-09 09:58:29 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_real(real_t p_real) { | 
					
						
							| 
									
										
										
										
											2022-09-29 09:18:07 +03:00
										 |  |  | 	if constexpr (sizeof(real_t) == 4) { | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 		return store_float(p_real); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 		return store_double(p_real); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_half(float p_dest) { | 
					
						
							|  |  |  | 	return store_16(Math::make_half_float(p_dest)); | 
					
						
							| 
									
										
										
										
											2024-10-01 23:41:13 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_float(float p_dest) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	MarshallFloat m; | 
					
						
							|  |  |  | 	m.f = p_dest; | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_32(m.i); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_double(double p_dest) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	MarshallDouble m; | 
					
						
							|  |  |  | 	m.d = p_dest; | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_64(m.l); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | uint64_t FileAccess::get_modified_time(const String &p_file) { | 
					
						
							| 
									
										
										
										
											2020-07-27 12:06:40 +02:00
										 |  |  | 	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) { | 
					
						
							| 
									
										
										
										
											2018-01-23 19:49:50 +02:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-23 19:49:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 10:47:58 +03:00
										 |  |  | 	return fa->_get_modified_time(p_file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint64_t FileAccess::get_access_time(const String &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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fa->_get_access_time(p_file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int64_t FileAccess::get_size(const String &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 PackedData::get_singleton()->get_size(p_file); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), -1, "Cannot create FileAccess for path '" + p_file + "'."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fa->_get_size(p_file); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const String &p_file) { | 
					
						
							| 
									
										
										
										
											2020-07-27 12:06:40 +02:00
										 |  |  | 	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) { | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 	return fa->_get_unix_permissions(p_file); | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | Error FileAccess::set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) { | 
					
						
							| 
									
										
										
										
											2020-07-27 12:06:40 +02:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2019-04-07 15:46:52 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Error err = fa->_set_unix_permissions(p_file, p_permissions); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | bool FileAccess::get_hidden_attribute(const String &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 false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return fa->_get_hidden_attribute(p_file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error FileAccess::set_hidden_attribute(const String &p_file, bool p_hidden) { | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Error err = fa->_set_hidden_attribute(p_file, p_hidden); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool FileAccess::get_read_only_attribute(const String &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 false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return fa->_get_read_only_attribute(p_file); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error FileAccess::set_read_only_attribute(const String &p_file, bool p_ro) { | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<FileAccess> fa = create_for_path(p_file); | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, vformat("Cannot create FileAccess for path '%s'.", p_file)); | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Error err = fa->_set_read_only_attribute(p_file, p_ro); | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_string(const String &p_string) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_string.length() == 0) { | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	CharString cs = p_string.utf8(); | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_buffer((uint8_t *)&cs[0], cs.length()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-03-13 22:57:24 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_pascal_string(const String &p_string) { | 
					
						
							| 
									
										
										
										
											2014-03-13 22:57:24 -03:00
										 |  |  | 	CharString cs = p_string.utf8(); | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_32(cs.length()) && store_buffer((uint8_t *)&cs[0], cs.length()); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-03-13 22:57:24 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | String FileAccess::get_pascal_string() { | 
					
						
							|  |  |  | 	uint32_t sl = get_32(); | 
					
						
							|  |  |  | 	CharString cs; | 
					
						
							| 
									
										
										
										
											2025-05-28 20:33:21 +02:00
										 |  |  | 	cs.resize_uninitialized(sl + 1); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	get_buffer((uint8_t *)cs.ptr(), sl); | 
					
						
							|  |  |  | 	cs[sl] = 0; | 
					
						
							| 
									
										
										
										
											2014-03-13 22:57:24 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-30 19:56:38 +02:00
										 |  |  | 	return String::utf8(cs.ptr(), sl); | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-03-13 22:57:24 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_line(const String &p_line) { | 
					
						
							|  |  |  | 	return store_string(p_line) && store_8('\n'); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(p_delim.length() != 1, false); | 
					
						
							| 
									
										
										
										
											2018-11-13 12:53:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String line = ""; | 
					
						
							|  |  |  | 	int size = p_values.size(); | 
					
						
							|  |  |  | 	for (int i = 0; i < size; ++i) { | 
					
						
							|  |  |  | 		String value = p_values[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-05 17:56:08 +01:00
										 |  |  | 		if (value.contains_char('"') || value.contains(p_delim) || value.contains_char('\n')) { | 
					
						
							| 
									
										
										
										
											2018-11-13 12:53:24 +01:00
										 |  |  | 			value = "\"" + value.replace("\"", "\"\"") + "\""; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (i < size - 1) { | 
					
						
							|  |  |  | 			value += p_delim; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		line += value; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_line(line); | 
					
						
							| 
									
										
										
										
											2018-11-13 12:53:24 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	uint64_t len = p_buffer.size(); | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	if (len == 0) { | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	const uint8_t *r = p_buffer.ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	return store_buffer(r, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!p_src && p_length > 0, false); | 
					
						
							|  |  |  | 	for (uint64_t i = 0; i < p_length; i++) { | 
					
						
							|  |  |  | 		if (unlikely(!store_8(p_src[i]))) { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | bool FileAccess::store_var(const Variant &p_var, bool p_full_objects) { | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	int len; | 
					
						
							|  |  |  | 	Error err = encode_variant(p_var, nullptr, len, p_full_objects); | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(err != OK, false, "Error when trying to encode Variant."); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Vector<uint8_t> buff; | 
					
						
							|  |  |  | 	buff.resize(len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint8_t *w = buff.ptrw(); | 
					
						
							|  |  |  | 	err = encode_variant(p_var, &w[0], len, p_full_objects); | 
					
						
							| 
									
										
										
										
											2023-06-15 21:21:43 +03:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(err != OK, false, "Error when trying to encode Variant."); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 02:17:09 +01:00
										 |  |  | 	return store_32(uint32_t(len)) && store_buffer(buff); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 15:04:01 +02:00
										 |  |  | Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) { | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error); | 
					
						
							|  |  |  | 	if (f.is_null()) { | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | 		if (r_error) { // if error requested, do not throw error
 | 
					
						
							|  |  |  | 			return Vector<uint8_t>(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 		ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path))); | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Vector<uint8_t> data; | 
					
						
							| 
									
										
										
										
											2021-05-25 07:58:49 +01:00
										 |  |  | 	data.resize(f->get_length()); | 
					
						
							| 
									
										
										
										
											2017-11-25 00:07:54 -03:00
										 |  |  | 	f->get_buffer(data.ptrw(), data.size()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { | 
					
						
							|  |  |  | 	Error err; | 
					
						
							| 
									
										
										
										
											2022-11-21 15:04:01 +02:00
										 |  |  | 	Vector<uint8_t> array = get_file_as_bytes(p_path, &err); | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | 	if (r_error) { | 
					
						
							|  |  |  | 		*r_error = err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		if (r_error) { | 
					
						
							|  |  |  | 			return String(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 		ERR_FAIL_V_MSG(String(), vformat("Can't get file as string from path '%s'.", String(p_path))); | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String ret; | 
					
						
							| 
									
										
										
										
											2025-03-24 12:25:48 +01:00
										 |  |  | 	ret.append_utf8((const char *)array.ptr(), array.size()); | 
					
						
							| 
									
										
										
										
											2019-04-08 19:18:03 -03:00
										 |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | String FileAccess::get_md5(const String &p_file) { | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> f = FileAccess::open(p_file, READ); | 
					
						
							|  |  |  | 	if (f.is_null()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return String(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	CryptoCore::MD5Context ctx; | 
					
						
							|  |  |  | 	ctx.start(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	unsigned char step[32768]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2019-03-26 18:51:13 +01:00
										 |  |  | 		uint64_t br = f->get_buffer(step, 32768); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (br > 0) { | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 			ctx.update(step, br); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (br < 4096) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	unsigned char hash[16]; | 
					
						
							|  |  |  | 	ctx.finish(hash); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	return String::md5(hash); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | String FileAccess::get_multiple_md5(const Vector<String> &p_file) { | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	CryptoCore::MD5Context ctx; | 
					
						
							|  |  |  | 	ctx.start(); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < p_file.size(); i++) { | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 		Ref<FileAccess> f = FileAccess::open(p_file[i], READ); | 
					
						
							|  |  |  | 		ERR_CONTINUE(f.is_null()); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		unsigned char step[32768]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (true) { | 
					
						
							| 
									
										
										
										
											2019-03-26 18:51:13 +01:00
										 |  |  | 			uint64_t br = f->get_buffer(step, 32768); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 			if (br > 0) { | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 				ctx.update(step, br); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (br < 4096) { | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	unsigned char hash[16]; | 
					
						
							|  |  |  | 	ctx.finish(hash); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	return String::md5(hash); | 
					
						
							| 
									
										
										
										
											2017-12-27 15:21:18 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | String FileAccess::get_sha256(const String &p_file) { | 
					
						
							| 
									
										
										
										
											2022-03-23 11:08:58 +02:00
										 |  |  | 	Ref<FileAccess> f = FileAccess::open(p_file, READ); | 
					
						
							|  |  |  | 	if (f.is_null()) { | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 		return String(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	CryptoCore::SHA256Context ctx; | 
					
						
							|  |  |  | 	ctx.start(); | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	unsigned char step[32768]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2019-03-26 18:51:13 +01:00
										 |  |  | 		uint64_t br = f->get_buffer(step, 32768); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (br > 0) { | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 			ctx.update(step, br); | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (br < 4096) { | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned char hash[32]; | 
					
						
							| 
									
										
										
										
											2019-07-02 03:06:52 +02:00
										 |  |  | 	ctx.finish(hash); | 
					
						
							| 
									
										
										
										
											2016-06-17 10:55:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return String::hex_encode_buffer(hash, 32); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void FileAccess::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open); | 
					
						
							| 
									
										
										
										
											2024-11-07 12:32:02 +02:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key", "iv"), &FileAccess::open_encrypted, DEFVAL(Vector<uint8_t>())); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &FileAccess::open_encrypted_pass); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0)); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error); | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("create_temp", "mode_flags", "prefix", "extension", "keep"), &FileAccess::_create_temp, DEFVAL(""), DEFVAL(""), DEFVAL(false)); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-21 15:04:01 +02:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_bytes", "path"), &FileAccess::_get_file_as_bytes); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_file_as_string", "path"), &FileAccess::_get_file_as_string); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 22:09:34 +03:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("resize", "length"), &FileAccess::resize); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("flush"), &FileAccess::flush); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_path"), &FileAccess::get_path); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_path_absolute"), &FileAccess::get_path_absolute); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_open"), &FileAccess::is_open); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("seek", "position"), &FileAccess::seek); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("seek_end", "position"), &FileAccess::seek_end, DEFVAL(0)); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_position"), &FileAccess::get_position); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_length"), &FileAccess::get_length); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("eof_reached"), &FileAccess::eof_reached); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_8"), &FileAccess::get_8); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_16"), &FileAccess::get_16); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_32"), &FileAccess::get_32); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_64"), &FileAccess::get_64); | 
					
						
							| 
									
										
										
										
											2024-10-01 23:41:13 -03:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_half"), &FileAccess::get_half); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real); | 
					
						
							| 
									
										
										
										
											2025-03-29 12:56:52 -05:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(",")); | 
					
						
							| 
									
										
										
										
											2025-09-24 13:55:45 -05:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_as_text"), &FileAccess::get_as_text); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_big_endian", "big_endian"), &FileAccess::set_big_endian); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_error"), &FileAccess::get_error); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &FileAccess::get_var, DEFVAL(false)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_8", "value"), &FileAccess::store_8); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_16", "value"), &FileAccess::store_16); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_32", "value"), &FileAccess::store_32); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_64", "value"), &FileAccess::store_64); | 
					
						
							| 
									
										
										
										
											2024-10-01 23:41:13 -03:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("store_half", "value"), &FileAccess::store_half); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real); | 
					
						
							| 
									
										
										
										
											2025-03-29 12:56:52 -05:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool (FileAccess::*)(const Vector<uint8_t> &))&FileAccess::store_buffer); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(",")); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var, DEFVAL(false)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_pascal_string"), &FileAccess::get_pascal_string); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-16 15:25:32 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("close"), &FileAccess::close); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time); | 
					
						
							| 
									
										
										
										
											2023-10-17 10:47:58 +03:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_access_time", "file"), &FileAccess::get_access_time); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_size", "file"), &FileAccess::get_size); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_unix_permissions", "file"), &FileAccess::get_unix_permissions); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("set_unix_permissions", "file", "permissions"), &FileAccess::set_unix_permissions); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_hidden_attribute", "file"), &FileAccess::get_hidden_attribute); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("set_hidden_attribute", "file", "hidden"), &FileAccess::set_hidden_attribute); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("set_read_only_attribute", "file", "ro"), &FileAccess::set_read_only_attribute); | 
					
						
							|  |  |  | 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_read_only_attribute", "file"), &FileAccess::get_read_only_attribute); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(READ); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(WRITE); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(READ_WRITE); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(WRITE_READ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(COMPRESSION_FASTLZ); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(COMPRESSION_DEFLATE); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(COMPRESSION_ZSTD); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(COMPRESSION_GZIP); | 
					
						
							| 
									
										
										
										
											2023-03-29 09:31:25 +03:00
										 |  |  | 	BIND_ENUM_CONSTANT(COMPRESSION_BROTLI); | 
					
						
							| 
									
										
										
										
											2023-08-08 09:53:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_READ_OWNER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_WRITE_OWNER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_EXECUTE_OWNER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_READ_GROUP); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_WRITE_GROUP); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_EXECUTE_GROUP); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_READ_OTHER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_WRITE_OTHER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_EXECUTE_OTHER); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_SET_USER_ID); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_SET_GROUP_ID); | 
					
						
							|  |  |  | 	BIND_BITFIELD_FLAG(UNIX_RESTRICTED_DELETE); | 
					
						
							| 
									
										
										
										
											2022-09-05 13:01:31 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-10-21 15:02:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | FileAccess::~FileAccess() { | 
					
						
							|  |  |  | 	_delete_temp(); | 
					
						
							|  |  |  | } |