diff options
Diffstat (limited to 'core/os')
-rw-r--r-- | core/os/keyboard.cpp | 4 | ||||
-rw-r--r-- | core/os/keyboard.h | 2 | ||||
-rw-r--r-- | core/os/main_loop.h | 1 | ||||
-rw-r--r-- | core/os/memory.h | 14 | ||||
-rw-r--r-- | core/os/os.cpp | 75 | ||||
-rw-r--r-- | core/os/os.h | 18 | ||||
-rw-r--r-- | core/os/pool_allocator.cpp | 4 | ||||
-rw-r--r-- | core/os/pool_allocator.h | 26 | ||||
-rw-r--r-- | core/os/thread.cpp | 1 | ||||
-rw-r--r-- | core/os/thread.h | 1 | ||||
-rw-r--r-- | core/os/time.cpp | 162 | ||||
-rw-r--r-- | core/os/time.h | 9 |
12 files changed, 186 insertions, 131 deletions
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 3a03c0a10b..24907d34c8 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -41,8 +41,8 @@ static const _KeyCodeText _keycodes[] = { /* clang-format off */ {Key::ESCAPE ,"Escape"}, {Key::TAB ,"Tab"}, - {Key::BACKTAB ,"BackTab"}, - {Key::BACKSPACE ,"BackSpace"}, + {Key::BACKTAB ,"Backtab"}, + {Key::BACKSPACE ,"Backspace"}, {Key::ENTER ,"Enter"}, {Key::KP_ENTER ,"Kp Enter"}, {Key::INSERT ,"Insert"}, diff --git a/core/os/keyboard.h b/core/os/keyboard.h index a21d81b2e7..3176a8a210 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -294,7 +294,7 @@ enum class Key { enum class KeyModifierMask { CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers. - MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers. + MODIFIER_MASK = (0x7F << 24), ///< Apply this mask to isolate modifiers. SHIFT = (1 << 25), ALT = (1 << 26), META = (1 << 27), diff --git a/core/os/main_loop.h b/core/os/main_loop.h index a6a32f0138..2bb1ea2ef4 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -38,7 +38,6 @@ class MainLoop : public Object { GDCLASS(MainLoop, Object); - OBJ_CATEGORY("Main Loop"); Ref<Script> initialize_script; diff --git a/core/os/memory.h b/core/os/memory.h index 27eaad5010..42ba9634e2 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -186,9 +186,9 @@ void memdelete_arr(T *p_class) { struct _GlobalNil { int color = 1; - _GlobalNil *right; - _GlobalNil *left; - _GlobalNil *parent; + _GlobalNil *right = nullptr; + _GlobalNil *left = nullptr; + _GlobalNil *parent = nullptr; _GlobalNil(); }; @@ -197,4 +197,12 @@ struct _GlobalNilClass { static _GlobalNil _nil; }; +template <class T> +class DefaultTypedAllocator { +public: + template <class... Args> + _FORCE_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); } + _FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); } +}; + #endif // MEMORY_H diff --git a/core/os/os.cpp b/core/os/os.cpp index 9837b6e0aa..327f1c95f2 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -80,7 +80,9 @@ void OS::print_error(const char *p_function, const char *p_file, int p_line, con return; } - _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type); + if (_logger) { + _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type); + } } void OS::print(const char *p_format, ...) { @@ -91,7 +93,9 @@ void OS::print(const char *p_format, ...) { va_list argp; va_start(argp, p_format); - _logger->logv(p_format, argp, false); + if (_logger) { + _logger->logv(p_format, argp, false); + } va_end(argp); } @@ -104,7 +108,9 @@ void OS::printerr(const char *p_format, ...) { va_list argp; va_start(argp, p_format); - _logger->logv(p_format, argp, true); + if (_logger) { + _logger->logv(p_format, argp, true); + } va_end(argp); } @@ -173,7 +179,7 @@ void OS::dump_memory_to_file(const char *p_file) { //Memory::dump_static_mem_to_file(p_file); } -static FileAccess *_OSPRF = nullptr; +static Ref<FileAccess> _OSPRF; static void _OS_printres(Object *p_obj) { Resource *res = Object::cast_to<Resource>(p_obj); @@ -182,7 +188,7 @@ static void _OS_printres(Object *p_obj) { } String str = vformat("%s - %s - %s", res->to_string(), res->get_name(), res->get_path()); - if (_OSPRF) { + if (_OSPRF.is_valid()) { _OSPRF->store_line(str); } else { print_line(str); @@ -190,24 +196,19 @@ static void _OS_printres(Object *p_obj) { } void OS::print_all_resources(String p_to_file) { - ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF); + ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF.is_valid()); if (!p_to_file.is_empty()) { Error err; _OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err); if (err != OK) { - _OSPRF = nullptr; + _OSPRF.unref(); ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + "."); } } ObjectDB::debug_objects(_OS_printres); - if (!p_to_file.is_empty()) { - if (_OSPRF) { - memdelete(_OSPRF); - } - _OSPRF = nullptr; - } + _OSPRF.unref(); } void OS::print_resources_in_use(bool p_short) { @@ -236,6 +237,11 @@ String OS::get_locale_language() const { return get_locale().left(3).replace("_", ""); } +// Embedded PCK offset. +uint64_t OS::get_embedded_pck_offset() const { + return 0; +} + // Helper function to ensure that a dir name/path will be valid on the OS String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const { Vector<String> invalid_chars = String(": * ? \" < > |").split(" "); @@ -328,17 +334,13 @@ void OS::yield() { void OS::ensure_user_data_dir() { String dd = get_user_data_dir(); - DirAccess *da = DirAccess::open(dd); - if (da) { - memdelete(da); + if (DirAccess::exists(dd)) { return; } - da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = da->make_dir_recursive(dd); ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + "."); - - memdelete(da); } String OS::get_model_name() const { @@ -411,19 +413,29 @@ bool OS::has_feature(const String &p_feature) { if (sizeof(void *) == 4 && p_feature == "32") { return true; } -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) if (p_feature == "x86_64") { return true; } -#elif (defined(__i386) || defined(__i386__)) +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + if (p_feature == "x86_32") { + return true; + } +#endif if (p_feature == "x86") { return true; } -#elif defined(__aarch64__) +#elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) +#if defined(__aarch64__) || defined(_M_ARM64) if (p_feature == "arm64") { return true; } -#elif defined(__arm__) +#elif defined(__arm__) || defined(_M_ARM) + if (p_feature == "arm32") { + return true; + } +#endif #if defined(__ARM_ARCH_7A__) if (p_feature == "armv7a" || p_feature == "armv7") { return true; @@ -455,6 +467,19 @@ bool OS::has_feature(const String &p_feature) { if (p_feature == "ppc") { return true; } +#elif defined(__wasm__) +#if defined(__wasm64__) + if (p_feature == "wasm64") { + return true; + } +#elif defined(__wasm32__) + if (p_feature == "wasm32") { + return true; + } +#endif + if (p_feature == "wasm") { + return true; + } #endif if (_check_internal_feature_support(p_feature)) { @@ -554,6 +579,8 @@ OS::OS() { } OS::~OS() { - memdelete(_logger); + if (_logger) { + memdelete(_logger); + } singleton = nullptr; } diff --git a/core/os/os.h b/core/os/os.h index 808d704b3d..157b8ab992 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -54,14 +54,11 @@ class OS { bool _single_window = false; String _local_clipboard; int _exit_code = EXIT_FAILURE; // unexpected exit is marked as failure - int _orientation; bool _allow_hidpi = false; bool _allow_layered = false; bool _stdout_enabled = true; bool _stderr_enabled = true; - char *last_error; - CompositeLogger *_logger = nullptr; bool restart_on_exit = false; @@ -70,7 +67,7 @@ class OS { // for the user interface we keep a record of the current display driver // so we can retrieve the rendering drivers available int _display_driver_id = -1; - String _current_rendering_driver_name = ""; + String _current_rendering_driver_name; protected: void _set_logger(CompositeLogger *p_logger); @@ -85,11 +82,6 @@ public: RENDER_SEPARATE_THREAD }; - enum RenderMainThreadMode { - RENDER_MAIN_THREAD_ONLY, - RENDER_ANY_THREAD, - }; - protected: friend class Main; // Needed by tests to setup command-line args. @@ -97,7 +89,6 @@ protected: HasServerFeatureCallback has_server_feature_callback = nullptr; RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE; - RenderMainThreadMode _render_main_thread_mode = RENDER_ANY_THREAD; // Functions used by Main to initialize/deinitialize the OS. void add_logger(Logger *p_logger); @@ -140,7 +131,7 @@ public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; } + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) { return ERR_UNAVAILABLE; } virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; } virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; } @@ -155,6 +146,7 @@ public: virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); }; virtual Error kill(const ProcessID &p_pid) = 0; virtual int get_process_id() const; + virtual bool is_process_running(const ProcessID &p_pid) const = 0; virtual void vibrate_handheld(int p_duration_ms = 500); virtual Error shell_open(String p_uri); @@ -260,12 +252,12 @@ public: virtual uint64_t get_free_static_memory() const; RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; } - RenderMainThreadMode get_render_main_thread_mode() const { return _render_main_thread_mode; } - void set_render_main_thread_mode(RenderMainThreadMode p_thread_mode) { _render_main_thread_mode = p_thread_mode; } virtual String get_locale() const; String get_locale_language() const; + virtual uint64_t get_embedded_pck_offset() const; + String get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator = false) const; virtual String get_godot_dir_name() const; diff --git a/core/os/pool_allocator.cpp b/core/os/pool_allocator.cpp index 190617f967..f622e2c7c5 100644 --- a/core/os/pool_allocator.cpp +++ b/core/os/pool_allocator.cpp @@ -149,7 +149,7 @@ void PoolAllocator::compact_up(int p_from) { } } -bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, Entry *p_entry) { +bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, const Entry *p_entry) { EntryArrayPos entry_pos = entry_max; for (int i = 0; i < entry_count; i++) { @@ -424,7 +424,7 @@ bool PoolAllocator::is_locked(ID p_mem) const { } mt_lock(); - const Entry *e = ((PoolAllocator *)(this))->get_entry(p_mem); + const Entry *e = const_cast<PoolAllocator *>(this)->get_entry(p_mem); if (!e) { mt_unlock(); ERR_PRINT("!e"); diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h index 11a252bc54..a7a8523aa4 100644 --- a/core/os/pool_allocator.h +++ b/core/os/pool_allocator.h @@ -75,22 +75,22 @@ private: typedef int EntryArrayPos; typedef int EntryIndicesPos; - Entry *entry_array; - int *entry_indices; - int entry_max; - int entry_count; + Entry *entry_array = nullptr; + int *entry_indices = nullptr; + int entry_max = 0; + int entry_count = 0; - uint8_t *pool; - void *mem_ptr; - int pool_size; + uint8_t *pool = nullptr; + void *mem_ptr = nullptr; + int pool_size = 0; - int free_mem; - int free_mem_peak; + int free_mem = 0; + int free_mem_peak = 0; - unsigned int check_count; - int align; + unsigned int check_count = 0; + int align = 1; - bool needs_locking; + bool needs_locking = false; inline int entry_end(const Entry &p_entry) const { return p_entry.pos + aligned(p_entry.len); @@ -108,7 +108,7 @@ private: void compact_up(int p_from = 0); bool get_free_entry(EntryArrayPos *p_pos); bool find_hole(EntryArrayPos *p_pos, int p_for_size); - bool find_entry_index(EntryIndicesPos *p_map_pos, Entry *p_entry); + bool find_entry_index(EntryIndicesPos *p_map_pos, const Entry *p_entry); Entry *get_entry(ID p_mem); const Entry *get_entry(ID p_mem) const; diff --git a/core/os/thread.cpp b/core/os/thread.cpp index f80e8f4bb3..c8072b7280 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "platform_config.h" #ifndef PLATFORM_THREAD_OVERRIDE // See details in thread.h #include "thread.h" diff --git a/core/os/thread.h b/core/os/thread.h index f4e46059ad..3382dd81f9 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "platform_config.h" // Define PLATFORM_THREAD_OVERRIDE in your platform's `platform_config.h` // to use a custom Thread implementation defined in `platform/[your_platform]/platform_thread.h` // Overriding the platform implementation is required in some proprietary platforms diff --git a/core/os/time.cpp b/core/os/time.cpp index 5eae94279a..a30e2a906b 100644 --- a/core/os/time.cpp +++ b/core/os/time.cpp @@ -95,16 +95,21 @@ VARIANT_ENUM_CAST(Time::Weekday); day = day_number_copy + 1; \ } -#define VALIDATE_YMDHMS \ - ERR_FAIL_COND_V_MSG(month == 0, 0, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \ - ERR_FAIL_COND_V_MSG(month > 12, 0, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \ - ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + "."); \ - ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + "."); \ - ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \ - /* Do this check after month is tested as valid. */ \ - ERR_FAIL_COND_V_MSG(day == 0, 0, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \ - uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \ - ERR_FAIL_COND_V_MSG(day > days_in_this_month, 0, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + "."); +#define VALIDATE_YMDHMS(ret) \ + ERR_FAIL_COND_V_MSG(month == 0, ret, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \ + ERR_FAIL_COND_V_MSG(month < 0, ret, "Invalid month value of: " + itos(month) + "."); \ + ERR_FAIL_COND_V_MSG(month > 12, ret, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \ + ERR_FAIL_COND_V_MSG(hour > 23, ret, "Invalid hour value of: " + itos(hour) + "."); \ + ERR_FAIL_COND_V_MSG(hour < 0, ret, "Invalid hour value of: " + itos(hour) + "."); \ + ERR_FAIL_COND_V_MSG(minute > 59, ret, "Invalid minute value of: " + itos(minute) + "."); \ + ERR_FAIL_COND_V_MSG(minute < 0, ret, "Invalid minute value of: " + itos(minute) + "."); \ + ERR_FAIL_COND_V_MSG(second > 59, ret, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \ + ERR_FAIL_COND_V_MSG(second < 0, ret, "Invalid second value of: " + itos(second) + "."); \ + ERR_FAIL_COND_V_MSG(day == 0, ret, "Invalid day value of: " + itos(day) + ", days are 1-indexed and cannot be 0."); \ + ERR_FAIL_COND_V_MSG(day < 0, ret, "Invalid day value of: " + itos(day) + "."); \ + /* Do this check after month is tested as valid. */ \ + uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \ + ERR_FAIL_COND_V_MSG(day > days_in_this_month, ret, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + "."); #define YMD_TO_DAY_NUMBER \ /* The day number since Unix epoch (0-index). Days before 1970 are negative. */ \ @@ -124,61 +129,65 @@ VARIANT_ENUM_CAST(Time::Weekday); } \ } -#define PARSE_ISO8601_STRING \ - int64_t year = UNIX_EPOCH_YEAR_AD; \ - Month month = MONTH_JANUARY; \ - uint8_t day = 1; \ - uint8_t hour = 0; \ - uint8_t minute = 0; \ - uint8_t second = 0; \ - { \ - bool has_date = false, has_time = false; \ - String date, time; \ - if (p_datetime.find_char('T') > 0) { \ - has_date = has_time = true; \ - PackedStringArray array = p_datetime.split("T"); \ - date = array[0]; \ - time = array[1]; \ - } else if (p_datetime.find_char(' ') > 0) { \ - has_date = has_time = true; \ - PackedStringArray array = p_datetime.split(" "); \ - date = array[0]; \ - time = array[1]; \ - } else if (p_datetime.find_char('-', 1) > 0) { \ - has_date = true; \ - date = p_datetime; \ - } else if (p_datetime.find_char(':') > 0) { \ - has_time = true; \ - time = p_datetime; \ - } \ - /* Set the variables from the contents of the string. */ \ - if (has_date) { \ - PackedInt32Array array = date.split_ints("-", false); \ - year = array[0]; \ - month = (Month)array[1]; \ - day = array[2]; \ - /* Handle negative years. */ \ - if (p_datetime.find_char('-') == 0) { \ - year *= -1; \ - } \ - } \ - if (has_time) { \ - PackedInt32Array array = time.split_ints(":", false); \ - hour = array[0]; \ - minute = array[1]; \ - second = array[2]; \ - } \ +#define PARSE_ISO8601_STRING(ret) \ + int64_t year = UNIX_EPOCH_YEAR_AD; \ + Month month = MONTH_JANUARY; \ + int day = 1; \ + int hour = 0; \ + int minute = 0; \ + int second = 0; \ + { \ + bool has_date = false, has_time = false; \ + String date, time; \ + if (p_datetime.find_char('T') > 0) { \ + has_date = has_time = true; \ + PackedStringArray array = p_datetime.split("T"); \ + ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \ + date = array[0]; \ + time = array[1]; \ + } else if (p_datetime.find_char(' ') > 0) { \ + has_date = has_time = true; \ + PackedStringArray array = p_datetime.split(" "); \ + ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \ + date = array[0]; \ + time = array[1]; \ + } else if (p_datetime.find_char('-', 1) > 0) { \ + has_date = true; \ + date = p_datetime; \ + } else if (p_datetime.find_char(':') > 0) { \ + has_time = true; \ + time = p_datetime; \ + } \ + /* Set the variables from the contents of the string. */ \ + if (has_date) { \ + PackedInt32Array array = date.split_ints("-", false); \ + ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 date string."); \ + year = array[0]; \ + month = (Month)array[1]; \ + day = array[2]; \ + /* Handle negative years. */ \ + if (p_datetime.find_char('-') == 0) { \ + year *= -1; \ + } \ + } \ + if (has_time) { \ + PackedInt32Array array = time.split_ints(":", false); \ + ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 time string."); \ + hour = array[0]; \ + minute = array[1]; \ + second = array[2]; \ + } \ } #define EXTRACT_FROM_DICTIONARY \ /* Get all time values from the dictionary. If it doesn't exist, set the */ \ /* values to the default values for Unix epoch (1970-01-01 00:00:00). */ \ int64_t year = p_datetime.has(YEAR_KEY) ? int64_t(p_datetime[YEAR_KEY]) : UNIX_EPOCH_YEAR_AD; \ - Month month = Month((p_datetime.has(MONTH_KEY)) ? uint8_t(p_datetime[MONTH_KEY]) : 1); \ - uint8_t day = p_datetime.has(DAY_KEY) ? uint8_t(p_datetime[DAY_KEY]) : 1; \ - uint8_t hour = p_datetime.has(HOUR_KEY) ? uint8_t(p_datetime[HOUR_KEY]) : 0; \ - uint8_t minute = p_datetime.has(MINUTE_KEY) ? uint8_t(p_datetime[MINUTE_KEY]) : 0; \ - uint8_t second = p_datetime.has(SECOND_KEY) ? uint8_t(p_datetime[SECOND_KEY]) : 0; + Month month = Month((p_datetime.has(MONTH_KEY)) ? int(p_datetime[MONTH_KEY]) : 1); \ + int day = p_datetime.has(DAY_KEY) ? int(p_datetime[DAY_KEY]) : 1; \ + int hour = p_datetime.has(HOUR_KEY) ? int(p_datetime[HOUR_KEY]) : 0; \ + int minute = p_datetime.has(MINUTE_KEY) ? int(p_datetime[MINUTE_KEY]) : 0; \ + int second = p_datetime.has(SECOND_KEY) ? int(p_datetime[SECOND_KEY]) : 0; Time *Time::singleton = nullptr; @@ -252,8 +261,8 @@ String Time::get_time_string_from_unix_time(int64_t p_unix_time_val) const { return vformat("%02d:%02d:%02d", hour, minute, second); } -Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday) const { - PARSE_ISO8601_STRING +Dictionary Time::get_datetime_dict_from_datetime_string(String p_datetime, bool p_weekday) const { + PARSE_ISO8601_STRING(Dictionary()) Dictionary dict; dict[YEAR_KEY] = year; dict[MONTH_KEY] = (uint8_t)month; @@ -270,9 +279,10 @@ Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday return dict; } -String Time::get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space) const { +String Time::get_datetime_string_from_datetime_dict(const Dictionary p_datetime, bool p_use_space) const { ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), "", "Invalid datetime Dictionary: Dictionary is empty."); EXTRACT_FROM_DICTIONARY + VALIDATE_YMDHMS("") // vformat only supports up to 6 arguments, so we need to split this up into 2 parts. String timestamp = vformat("%04d-%02d-%02d", year, (uint8_t)month, day); if (p_use_space) { @@ -283,21 +293,36 @@ String Time::get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_spa return timestamp; } -int64_t Time::get_unix_time_from_datetime_dict(Dictionary p_datetime) const { +int64_t Time::get_unix_time_from_datetime_dict(const Dictionary p_datetime) const { ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty"); EXTRACT_FROM_DICTIONARY - VALIDATE_YMDHMS + VALIDATE_YMDHMS(0) YMD_TO_DAY_NUMBER return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second; } int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const { - PARSE_ISO8601_STRING - VALIDATE_YMDHMS + PARSE_ISO8601_STRING(-1) + VALIDATE_YMDHMS(0) YMD_TO_DAY_NUMBER return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second; } +String Time::get_offset_string_from_offset_minutes(int64_t p_offset_minutes) const { + String sign; + if (p_offset_minutes < 0) { + sign = "-"; + p_offset_minutes = -p_offset_minutes; + } else { + sign = "+"; + } + // These two lines can be optimized to one instruction on x86 and others. + // Note that % is acceptable here only because we ensure it's positive. + int64_t offset_hours = p_offset_minutes / 60; + int64_t offset_minutes = p_offset_minutes % 60; + return vformat("%s%02d:%02d", sign, offset_hours, offset_minutes); +} + Dictionary Time::get_datetime_dict_from_system(bool p_utc) const { OS::Date date = OS::get_singleton()->get_date(p_utc); OS::Time time = OS::get_singleton()->get_time(p_utc); @@ -385,10 +410,11 @@ void Time::_bind_methods() { ClassDB::bind_method(D_METHOD("get_datetime_string_from_unix_time", "unix_time_val", "use_space"), &Time::get_datetime_string_from_unix_time, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_date_string_from_unix_time", "unix_time_val"), &Time::get_date_string_from_unix_time); ClassDB::bind_method(D_METHOD("get_time_string_from_unix_time", "unix_time_val"), &Time::get_time_string_from_unix_time); - ClassDB::bind_method(D_METHOD("get_datetime_dict_from_string", "datetime", "weekday"), &Time::get_datetime_dict_from_string); - ClassDB::bind_method(D_METHOD("get_datetime_string_from_dict", "datetime", "use_space"), &Time::get_datetime_string_from_dict); + ClassDB::bind_method(D_METHOD("get_datetime_dict_from_datetime_string", "datetime", "weekday"), &Time::get_datetime_dict_from_datetime_string); + ClassDB::bind_method(D_METHOD("get_datetime_string_from_datetime_dict", "datetime", "use_space"), &Time::get_datetime_string_from_datetime_dict); ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_dict", "datetime"), &Time::get_unix_time_from_datetime_dict); ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_string", "datetime"), &Time::get_unix_time_from_datetime_string); + ClassDB::bind_method(D_METHOD("get_offset_string_from_offset_minutes", "offset_minutes"), &Time::get_offset_string_from_offset_minutes); ClassDB::bind_method(D_METHOD("get_datetime_dict_from_system", "utc"), &Time::get_datetime_dict_from_system, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_date_dict_from_system", "utc"), &Time::get_date_dict_from_system, DEFVAL(false)); diff --git a/core/os/time.h b/core/os/time.h index 3f00ba1478..4b4ce3526a 100644 --- a/core/os/time.h +++ b/core/os/time.h @@ -51,7 +51,7 @@ class Time : public Object { public: static Time *get_singleton(); - enum Month : uint8_t { + enum Month { /// Start at 1 to follow Windows SYSTEMTIME structure /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx MONTH_JANUARY = 1, @@ -85,10 +85,11 @@ public: String get_datetime_string_from_unix_time(int64_t p_unix_time_val, bool p_use_space = false) const; String get_date_string_from_unix_time(int64_t p_unix_time_val) const; String get_time_string_from_unix_time(int64_t p_unix_time_val) const; - Dictionary get_datetime_dict_from_string(String p_datetime, bool p_weekday = true) const; - String get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space = false) const; - int64_t get_unix_time_from_datetime_dict(Dictionary p_datetime) const; + Dictionary get_datetime_dict_from_datetime_string(String p_datetime, bool p_weekday = true) const; + String get_datetime_string_from_datetime_dict(const Dictionary p_datetime, bool p_use_space = false) const; + int64_t get_unix_time_from_datetime_dict(const Dictionary p_datetime) const; int64_t get_unix_time_from_datetime_string(String p_datetime) const; + String get_offset_string_from_offset_minutes(int64_t p_offset_minutes) const; // Methods that get information from OS. Dictionary get_datetime_dict_from_system(bool p_utc = false) const; |