Skip to content

Commit

Permalink
Merge branch 'godotengine:master' into issue-#98519
Browse files Browse the repository at this point in the history
  • Loading branch information
alecmeyer authored Dec 4, 2024
2 parents cc9dcda + 47bc374 commit 98f4d2a
Show file tree
Hide file tree
Showing 284 changed files with 3,626 additions and 1,564 deletions.
8 changes: 6 additions & 2 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
cs[slen] = 0;
f->get_buffer((uint8_t *)cs.ptr(), slen);
String key;
key.parse_utf8(cs.ptr());
key.parse_utf8(cs.ptr(), slen);

uint32_t vlen = f->get_32();
Vector<uint8_t> d;
Expand Down Expand Up @@ -1516,7 +1516,11 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/frame_pacing/android/enable_frame_pacing", true);
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/frame_pacing/android/swappy_mode", PROPERTY_HINT_ENUM, "pipeline_forced_on,auto_fps_pipeline_forced_on,auto_fps_auto_pipeline"), 2);

custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
#ifdef DISABLE_DEPRECATED
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Safe:1,Separate");
#else
custom_prop_info["rendering/driver/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/driver/threads/thread_model", PROPERTY_HINT_ENUM, "Unsafe (deprecated),Safe,Separate");
#endif
GLOBAL_DEF("physics/2d/run_on_separate_thread", false);
GLOBAL_DEF("physics/3d/run_on_separate_thread", false);

Expand Down
6 changes: 6 additions & 0 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,11 @@ String OS::get_cache_dir() const {
return ::OS::get_singleton()->get_cache_path();
}

String OS::get_temp_dir() const {
// Exposed as `get_temp_dir()` instead of `get_temp_path()` for consistency with other exposed OS methods.
return ::OS::get_singleton()->get_temp_path();
}

bool OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
return true;
Expand Down Expand Up @@ -705,6 +710,7 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_config_dir"), &OS::get_config_dir);
ClassDB::bind_method(D_METHOD("get_data_dir"), &OS::get_data_dir);
ClassDB::bind_method(D_METHOD("get_cache_dir"), &OS::get_cache_dir);
ClassDB::bind_method(D_METHOD("get_temp_dir"), &OS::get_temp_dir);
ClassDB::bind_method(D_METHOD("get_unique_id"), &OS::get_unique_id);

ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &OS::get_keycode_string);
Expand Down
1 change: 1 addition & 0 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ class OS : public Object {
String get_config_dir() const;
String get_data_dir() const;
String get_cache_dir() const;
String get_temp_dir() const;

Error set_thread_name(const String &p_name);
::Thread::ID get_thread_caller_id() const;
Expand Down
83 changes: 82 additions & 1 deletion core/io/dir_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

#include "core/config/project_settings.h"
#include "core/io/file_access.h"
#include "core/os/memory.h"
#include "core/os/os.h"
#include "core/os/time.h"
#include "core/templates/local_vector.h"

thread_local Error DirAccess::last_dir_open_error = OK;
Expand Down Expand Up @@ -323,6 +323,80 @@ Ref<DirAccess> DirAccess::create(AccessType p_access) {
return da;
}

Ref<DirAccess> DirAccess::create_temp(const String &p_prefix, bool p_keep, Error *r_error) {
const String ERROR_COMMON_PREFIX = "Error while creating temporary directory";

if (!p_prefix.is_valid_filename()) {
*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));
}

Ref<DirAccess> dir_access = DirAccess::open(OS::get_singleton()->get_temp_path());

uint32_t suffix_i = 0;
String path;
while (true) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
datetime += itos(Time::get_singleton()->get_ticks_usec());
String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : "");
path = (p_prefix.is_empty() ? "" : p_prefix + "-") + suffix;
if (!path.is_valid_filename()) {
*r_error = ERR_FILE_BAD_PATH;
return Ref<DirAccess>();
}
if (!DirAccess::exists(path)) {
break;
}
suffix_i += 1;
}

Error err = dir_access->make_dir(path);
if (err != OK) {
*r_error = err;
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" couldn't create directory "%s".)", ERROR_COMMON_PREFIX, path));
}
err = dir_access->change_dir(path);
if (err != OK) {
*r_error = err;
return Ref<DirAccess>();
}

dir_access->_is_temp = true;
dir_access->_temp_keep_after_free = p_keep;
dir_access->_temp_path = dir_access->get_current_dir();

*r_error = OK;
return dir_access;
}

Ref<DirAccess> DirAccess::_create_temp(const String &p_prefix, bool p_keep) {
return create_temp(p_prefix, p_keep, &last_dir_open_error);
}

void DirAccess::_delete_temp() {
if (!_is_temp || _temp_keep_after_free) {
return;
}

if (!DirAccess::exists(_temp_path)) {
return;
}

Error err;
{
Ref<DirAccess> dir_access = DirAccess::open(_temp_path, &err);
if (err != OK) {
return;
}
err = dir_access->erase_contents_recursive();
if (err != OK) {
return;
}
}

DirAccess::remove_absolute(_temp_path);
}

Error DirAccess::get_open_error() {
return last_dir_open_error;
}
Expand Down Expand Up @@ -555,6 +629,7 @@ bool DirAccess::is_case_sensitive(const String &p_path) const {
void DirAccess::_bind_methods() {
ClassDB::bind_static_method("DirAccess", D_METHOD("open", "path"), &DirAccess::_open);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
ClassDB::bind_static_method("DirAccess", D_METHOD("create_temp", "prefix", "keep"), &DirAccess::_create_temp, DEFVAL(""), DEFVAL(false));

ClassDB::bind_method(D_METHOD("list_dir_begin"), &DirAccess::list_dir_begin, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_next"), &DirAccess::_get_next);
Expand Down Expand Up @@ -588,6 +663,8 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("read_link", "path"), &DirAccess::read_link);
ClassDB::bind_method(D_METHOD("create_link", "source", "target"), &DirAccess::create_link);

ClassDB::bind_method(D_METHOD("is_bundle", "path"), &DirAccess::is_bundle);

ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
Expand All @@ -598,3 +675,7 @@ void DirAccess::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");
}

DirAccess::~DirAccess() {
_delete_temp();
}
12 changes: 11 additions & 1 deletion core/io/dir_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ class DirAccess : public RefCounted {
bool include_navigational = false;
bool include_hidden = false;

bool _is_temp = false;
bool _temp_keep_after_free = false;
String _temp_path;
void _delete_temp();

static Ref<DirAccess> _create_temp(const String &p_prefix = "", bool p_keep = false);

protected:
static void _bind_methods();

Expand Down Expand Up @@ -136,6 +143,7 @@ class DirAccess : public RefCounted {
}

static Ref<DirAccess> open(const String &p_path, Error *r_error = nullptr);
static Ref<DirAccess> create_temp(const String &p_prefix = "", bool p_keep = false, Error *r_error = nullptr);

static int _get_drive_count();
static String get_drive_name(int p_idx);
Expand All @@ -160,9 +168,11 @@ class DirAccess : public RefCounted {
bool get_include_hidden() const;

virtual bool is_case_sensitive(const String &p_path) const;
virtual bool is_bundle(const String &p_file) const { return false; }

public:
DirAccess() {}
virtual ~DirAccess() {}
virtual ~DirAccess();
};

#endif // DIR_ACCESS_H
83 changes: 81 additions & 2 deletions core/io/file_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/os/time.h"

FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = {};

Expand Down Expand Up @@ -84,6 +85,79 @@ Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
return ret;
}

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";

if (!p_prefix.is_valid_filename()) {
*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));
}

if (!p_extension.is_valid_filename()) {
*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) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
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);
}

Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
return open_internal(p_path, p_mode_flags);
}
Expand Down Expand Up @@ -491,7 +565,7 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
w[len] = 0;

String s;
s.parse_utf8((const char *)w, -1, p_skip_cr);
s.parse_utf8((const char *)w, len, p_skip_cr);
return s;
}

Expand Down Expand Up @@ -650,7 +724,7 @@ String FileAccess::get_pascal_string() {
cs[sl] = 0;

String ret;
ret.parse_utf8(cs.ptr());
ret.parse_utf8(cs.ptr(), sl);
return ret;
}

Expand Down Expand Up @@ -834,6 +908,7 @@ void FileAccess::_bind_methods() {
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);
ClassDB::bind_static_method("FileAccess", D_METHOD("create_temp", "mode_flags", "prefix", "extension", "keep"), &FileAccess::_create_temp, DEFVAL(""), DEFVAL(""), DEFVAL(false));

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);
Expand Down Expand Up @@ -923,3 +998,7 @@ void FileAccess::_bind_methods() {
BIND_BITFIELD_FLAG(UNIX_SET_GROUP_ID);
BIND_BITFIELD_FLAG(UNIX_RESTRICTED_DELETE);
}

FileAccess::~FileAccess() {
_delete_temp();
}
11 changes: 10 additions & 1 deletion core/io/file_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ class FileAccess : public RefCounted {

static Ref<FileAccess> _open(const String &p_path, ModeFlags p_mode_flags);

bool _is_temp_file = false;
bool _temp_keep_after_use = false;
String _temp_path;
void _delete_temp();

static Ref<FileAccess> _create_temp(int p_mode_flags, const String &p_prefix = "", const String &p_extension = "", bool p_keep = false);

public:
static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; }

Expand Down Expand Up @@ -222,6 +229,7 @@ class FileAccess : public RefCounted {
static Ref<FileAccess> create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static Ref<FileAccess> create_for_path(const String &p_path);
static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static Ref<FileAccess> create_temp(int p_mode_flags, const String &p_prefix = "", const String &p_extension = "", bool p_keep = false, Error *r_error = nullptr);

static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv = Vector<uint8_t>());
static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass);
Expand Down Expand Up @@ -257,8 +265,9 @@ class FileAccess : public RefCounted {
create_func[p_access] = _create_builtin<T>;
}

public:
FileAccess() {}
virtual ~FileAccess() {}
virtual ~FileAccess();
};

VARIANT_ENUM_CAST(FileAccess::CompressionMode);
Expand Down
2 changes: 1 addition & 1 deletion core/io/file_access_pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
cs[sl] = 0;

String path;
path.parse_utf8(cs.ptr());
path.parse_utf8(cs.ptr(), sl);

uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
Expand Down
2 changes: 1 addition & 1 deletion core/io/http_client_tcp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ Error HTTPClientTCP::poll() {
// End of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char *)response_str.ptr());
response.parse_utf8((const char *)response_str.ptr(), response_str.size());
Vector<String> responses = response.split("\n");
body_size = -1;
chunked = false;
Expand Down
Loading

0 comments on commit 98f4d2a

Please sign in to comment.