diff options
Diffstat (limited to 'core')
28 files changed, 626 insertions, 144 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index ee20aea35d..a0412e91ff 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -253,7 +253,7 @@ bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const { } void ProjectSettings::add_hidden_prefix(const String &p_prefix) { - ERR_FAIL_COND_MSG(hidden_prefixes.find(p_prefix) > -1, vformat("Hidden prefix '%s' already exists.", p_prefix)); + ERR_FAIL_COND_MSG(hidden_prefixes.has(p_prefix), vformat("Hidden prefix '%s' already exists.", p_prefix)); hidden_prefixes.push_back(p_prefix); } diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index 3e6b7501c7..f4283e0ea9 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -38,10 +38,10 @@ Array DebuggerMarshalls::ScriptStackDump::serialize() { Array arr; arr.push_back(frames.size() * 3); - for (int i = 0; i < frames.size(); i++) { - arr.push_back(frames[i].file); - arr.push_back(frames[i].line); - arr.push_back(frames[i].func); + for (const ScriptLanguage::StackInfo &frame : frames) { + arr.push_back(frame.file); + arr.push_back(frame.line); + arr.push_back(frame.func); } return arr; } diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index a7655c874a..97a020e4c3 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -137,7 +137,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co script_debugger = memnew(ScriptDebugger); // Tell the OS that we want to handle termination signals. OS::get_singleton()->initialize_debugging(); - } else if (p_uri.find("://") >= 0) { + } else if (p_uri.contains("://")) { const String proto = p_uri.substr(0, p_uri.find("://") + 3); if (!protocols.has(proto)) { return; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 1973663c72..bd30da3047 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -206,8 +206,7 @@ void RemoteDebugger::flush_output() { Vector<String> joined_log_strings; Vector<String> strings; Vector<int> types; - for (int i = 0; i < output_strings.size(); i++) { - const OutputString &output_string = output_strings[i]; + for (const OutputString &output_string : output_strings) { if (output_string.type == MESSAGE_TYPE_ERROR) { if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 81ee09f515..21a9014626 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -45,7 +45,7 @@ bool RemoteDebuggerPeerTCP::has_message() { Array RemoteDebuggerPeerTCP::get_message() { MutexLock lock(mutex); ERR_FAIL_COND_V(!has_message(), Array()); - Array out = in_queue[0]; + Array out = in_queue.front()->get(); in_queue.pop_front(); return out; } @@ -100,7 +100,7 @@ void RemoteDebuggerPeerTCP::_write_out() { break; // Nothing left to send } mutex.lock(); - Variant var = out_queue[0]; + Variant var = out_queue.front()->get(); out_queue.pop_front(); mutex.unlock(); int size = 0; diff --git a/core/doc_data.cpp b/core/doc_data.cpp index 7549ba884e..672a36c35c 100644 --- a/core/doc_data.cpp +++ b/core/doc_data.cpp @@ -152,9 +152,10 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met return_doc_from_retinfo(p_method, p_methodinfo.return_val); - for (int i = 0; i < p_methodinfo.arguments.size(); i++) { + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = p_methodinfo.arguments.begin(); itr != p_methodinfo.arguments.end(); ++itr, ++i) { DocData::ArgumentDoc argument; - argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]); + argument_doc_from_arginfo(argument, *itr); int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); if (default_arg_index >= 0) { Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index d7fba74365..848b6f3886 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -1018,26 +1018,34 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { d2["is_virtual"] = true; // virtual functions have no hash since no MethodBind is involved bool has_return = mi.return_val.type != Variant::NIL || (mi.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT); - Array arguments; - for (int i = (has_return ? -1 : 0); i < mi.arguments.size(); i++) { - PropertyInfo pinfo = i == -1 ? mi.return_val : mi.arguments[i]; + if (has_return) { + PropertyInfo pinfo = mi.return_val; Dictionary d3; - if (i >= 0) { - d3["name"] = pinfo.name; + d3["type"] = get_property_info_type_name(pinfo); + + if (mi.get_argument_meta(-1) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(-1)); } + d2["return_value"] = d3; + } + + Array arguments; + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) { + const PropertyInfo &pinfo = *itr; + Dictionary d3; + + d3["name"] = pinfo.name; + d3["type"] = get_property_info_type_name(pinfo); if (mi.get_argument_meta(i) > 0) { d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(i)); } - if (i == -1) { - d2["return_value"] = d3; - } else { - arguments.push_back(d3); - } + arguments.push_back(d3); } if (arguments.size()) { @@ -1151,10 +1159,11 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { Array arguments; - for (int i = 0; i < F.arguments.size(); i++) { + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = F.arguments.begin(); itr != F.arguments.end(); ++itr, ++i) { Dictionary d3; - d3["name"] = F.arguments[i].name; - d3["type"] = get_property_info_type_name(F.arguments[i]); + d3["name"] = itr->name; + d3["type"] = get_property_info_type_name(*itr); if (F.get_argument_meta(i) > 0) { d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i)); } @@ -1192,7 +1201,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { if (F.name.begins_with("_")) { continue; //hidden property } - if (F.name.find("/") >= 0) { + if (F.name.contains("/")) { // Ignore properties with '/' (slash) in the name. These are only meant for use in the inspector. continue; } diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index b48ea97040..a26bb3e8f3 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -211,14 +211,14 @@ protected: if (p_arg < 0) { return return_value_info.type; } else { - return arguments_info[p_arg].type; + return arguments_info.get(p_arg).type; } } virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { if (p_arg < 0) { return return_value_info; } else { - return arguments_info[p_arg]; + return arguments_info.get(p_arg); } } @@ -232,7 +232,7 @@ public: if (p_arg < 0) { return return_value_metadata; } else { - return arguments_metadata[p_arg]; + return arguments_metadata.get(p_arg); } } #endif @@ -319,8 +319,9 @@ public: return false; } - for (uint32_t i = 0; i < p_method_info->argument_count; i++) { - if (arguments_info[i].type != (Variant::Type)p_method_info->arguments_info[i].type) { + List<PropertyInfo>::ConstIterator itr = arguments_info.begin(); + for (uint32_t i = 0; i < p_method_info->argument_count; ++itr, ++i) { + if (itr->type != (Variant::Type)p_method_info->arguments_info[i].type) { return false; } } diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index bfe592cb4e..6fe6b8df20 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -2875,7 +2875,7 @@ typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNam * * The provided pointer can be immediately freed once the function returns. * - * @param p_data A pointer to an UTF-8 encoded C string (null terminated). + * @param p_data A pointer to a UTF-8 encoded C string (null terminated). */ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *p_data); @@ -2887,7 +2887,7 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char * * * The provided pointer can be immediately freed once the function returns. * - * @param p_data A pointer to an UTF-8 encoded C string. + * @param p_data A pointer to a UTF-8 encoded C string. * @param p_size The number of bytes (not code units). */ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size); diff --git a/core/input/input.cpp b/core/input/input.cpp index 1eabfacd8e..a8409cc06d 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -858,7 +858,7 @@ void Input::warp_mouse(const Vector2 &p_position) { warp_mouse_func(p_position); } -Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { +Point2 Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { // The relative distance reported for the next event after a warp is in the boundaries of the // size of the rect on that axis, but it may be greater, in which case there's no problem as fmod() // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation @@ -868,14 +868,14 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con // detect the warp: if the relative distance is greater than the half of the size of the relevant rect // (checked per each axis), it will be considered as the consequence of a former pointer warp. - const Point2i rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); - const Size2i warp_margin = p_rect.size * 0.5f; - const Point2i rel_warped( + const Point2 rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); + const Size2 warp_margin = p_rect.size * 0.5f; + const Point2 rel_warped( Math::fmod(p_motion->get_relative().x + rel_sign.x * warp_margin.x, p_rect.size.x) - rel_sign.x * warp_margin.x, Math::fmod(p_motion->get_relative().y + rel_sign.y * warp_margin.y, p_rect.size.y) - rel_sign.y * warp_margin.y); - const Point2i pos_local = p_motion->get_global_position() - p_rect.position; - const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); + const Point2 pos_local = p_motion->get_global_position() - p_rect.position; + const Point2 pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); if (pos_warped != pos_local) { warp_mouse(pos_warped + p_rect.position); } diff --git a/core/input/input.h b/core/input/input.h index 93407da2d9..6e7ab43082 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -316,7 +316,7 @@ public: BitField<MouseButtonMask> get_mouse_button_mask() const; void warp_mouse(const Vector2 &p_position); - Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); + Point2 warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); void parse_input_event(const Ref<InputEvent> &p_event); diff --git a/core/io/ip.cpp b/core/io/ip.cpp index ec86104926..f20d65bef9 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -148,8 +148,8 @@ PackedStringArray IP::resolve_hostname_addresses(const String &p_hostname, Type resolver->mutex.unlock(); PackedStringArray result; - for (int i = 0; i < res.size(); ++i) { - result.push_back(String(res[i])); + for (const IPAddress &E : res) { + result.push_back(String(E)); } return result; } @@ -206,9 +206,9 @@ IPAddress IP::get_resolve_item_address(ResolverID p_id) const { List<IPAddress> res = resolver->queue[p_id].response; - for (int i = 0; i < res.size(); ++i) { - if (res[i].is_valid()) { - return res[i]; + for (const IPAddress &E : res) { + if (E.is_valid()) { + return E; } } return IPAddress(); @@ -226,9 +226,9 @@ Array IP::get_resolve_item_addresses(ResolverID p_id) const { List<IPAddress> res = resolver->queue[p_id].response; Array result; - for (int i = 0; i < res.size(); ++i) { - if (res[i].is_valid()) { - result.push_back(String(res[i])); + for (const IPAddress &E : res) { + if (E.is_valid()) { + result.push_back(String(E)); } } return result; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index ce74bb36d6..a93876a2b5 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -202,7 +202,7 @@ IPAddress::IPAddress(const String &p_string) { // Wildcard (not a valid IP) wildcard = true; - } else if (p_string.find(":") >= 0) { + } else if (p_string.contains(":")) { // IPv6 _parse_ipv6(p_string); valid = true; diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index 215c6903a6..75ba784dbd 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -161,7 +161,7 @@ Ref<PacketPeerUDP> UDPServer::take_connection() { return conn; } - Peer peer = pending[0]; + Peer peer = pending.front()->get(); pending.pop_front(); peers.push_back(peer); return peer.peer; diff --git a/core/math/static_raycaster.h b/core/math/static_raycaster.h index c53868e12d..74e4b75163 100644 --- a/core/math/static_raycaster.h +++ b/core/math/static_raycaster.h @@ -49,7 +49,7 @@ protected: static StaticRaycaster *(*create_function)(); public: - // compatible with embree3 rays + // Compatible with embree4 rays. struct __aligned(16) Ray { const static unsigned int INVALID_GEOMETRY_ID = ((unsigned int)-1); // from rtcore_common.h diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 876635529c..6b84dfcee9 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -425,8 +425,8 @@ uint32_t ClassDB::get_api_hash(APIType p_api) { for (const StringName &F : snames) { MethodInfo &mi = t->signal_map[F]; hash = hash_murmur3_one_64(F.hash(), hash); - for (int i = 0; i < mi.arguments.size(); i++) { - hash = hash_murmur3_one_64(mi.arguments[i].type, hash); + for (const PropertyInfo &pi : mi.arguments) { + hash = hash_murmur3_one_64(pi.type, hash); } } } @@ -1856,8 +1856,9 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ if (p_arg_names.size() != mi.arguments.size()) { WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name); } else { - for (int i = 0; i < p_arg_names.size(); i++) { - mi.arguments[i].name = p_arg_names[i]; + List<PropertyInfo>::Iterator itr = mi.arguments.begin(); + for (int i = 0; i < p_arg_names.size(); ++itr, ++i) { + itr->name = p_arg_names[i]; } } } diff --git a/core/object/method_bind.h b/core/object/method_bind.h index e97f4abc6a..2f9a2d1679 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -152,7 +152,7 @@ public: if (p_arg < 0) { return _gen_return_type_info(); } else if (p_arg < method_info.arguments.size()) { - return method_info.arguments[p_arg]; + return method_info.arguments.get(p_arg); } else { return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); } @@ -193,10 +193,11 @@ public: Vector<StringName> names; names.resize(method_info.arguments.size()); #endif - for (int i = 0; i < method_info.arguments.size(); i++) { - at[i + 1] = method_info.arguments[i].type; + int i = 0; + for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) { + at[i + 1] = itr->type; #ifdef DEBUG_METHODS_ENABLED - names.write[i] = method_info.arguments[i].name; + names.write[i] = itr->name; #endif } diff --git a/core/object/object.cpp b/core/object/object.cpp index b6c8a87a22..dfc8e2a29a 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1302,9 +1302,8 @@ TypedArray<Dictionary> Object::_get_signal_connection_list(const StringName &p_s TypedArray<Dictionary> Object::_get_incoming_connections() const { TypedArray<Dictionary> ret; - int connections_amount = connections.size(); - for (int idx_conn = 0; idx_conn < connections_amount; idx_conn++) { - ret.push_back(connections[idx_conn]); + for (const Object::Connection &connection : connections) { + ret.push_back(connection); } return ret; @@ -2308,9 +2307,9 @@ void ObjectDB::setup() { } void ObjectDB::cleanup() { - if (slot_count > 0) { - spin_lock.lock(); + spin_lock.lock(); + if (slot_count > 0) { WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details)."); if (OS::get_singleton()->is_stdout_verbose()) { // Ensure calling the native classes because if a leaked instance has a script @@ -2341,10 +2340,11 @@ void ObjectDB::cleanup() { } print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`)."); } - spin_lock.unlock(); } if (object_slots) { memfree(object_slots); } + + spin_lock.unlock(); } diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index cc6b729ae8..8fd26c3d2c 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -389,7 +389,16 @@ public: EXBIND0RC(bool, can_make_function) EXBIND3R(Error, open_in_external_editor, const Ref<Script> &, int, int) EXBIND0R(bool, overrides_external_editor) - EXBIND0RC(ScriptNameCasing, preferred_file_name_casing) + + GDVIRTUAL0RC(ScriptNameCasing, _preferred_file_name_casing); + + virtual ScriptNameCasing preferred_file_name_casing() const override { + ScriptNameCasing ret; + if (GDVIRTUAL_CALL(_preferred_file_name_casing, ret)) { + return ret; + } + return ScriptNameCasing::SCRIPT_NAME_CASING_SNAKE_CASE; + } GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *) diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 2b62b72a51..3d37e17ef8 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1184,6 +1184,26 @@ int String::get_slice_count(const String &p_splitter) const { return slices; } +int String::get_slice_count(const char *p_splitter) const { + if (is_empty()) { + return 0; + } + if (p_splitter == nullptr || *p_splitter == '\0') { + return 0; + } + + int pos = 0; + int slices = 1; + int splitter_length = strlen(p_splitter); + + while ((pos = find(p_splitter, pos)) >= 0) { + slices++; + pos += splitter_length; + } + + return slices; +} + String String::get_slice(const String &p_splitter, int p_slice) const { if (is_empty() || p_splitter.is_empty()) { return ""; @@ -1224,6 +1244,47 @@ String String::get_slice(const String &p_splitter, int p_slice) const { return ""; //no find! } +String String::get_slice(const char *p_splitter, int p_slice) const { + if (is_empty() || p_splitter == nullptr || *p_splitter == '\0') { + return ""; + } + + int pos = 0; + int prev_pos = 0; + //int slices=1; + if (p_slice < 0) { + return ""; + } + if (find(p_splitter) == -1) { + return *this; + } + + int i = 0; + int splitter_length = strlen(p_splitter); + while (true) { + pos = find(p_splitter, pos); + if (pos == -1) { + pos = length(); //reached end + } + + int from = prev_pos; + //int to=pos; + + if (p_slice == i) { + return substr(from, pos - from); + } + + if (pos == length()) { //reached end and no find + break; + } + pos += splitter_length; + prev_pos = pos; + i++; + } + + return ""; //no find! +} + String String::get_slicec(char32_t p_splitter, int p_slice) const { if (is_empty()) { return String(); @@ -1338,6 +1399,54 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p return ret; } +Vector<String> String::split(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const { + Vector<String> ret; + + if (is_empty()) { + if (p_allow_empty) { + ret.push_back(""); + } + return ret; + } + + int from = 0; + int len = length(); + + while (true) { + int end; + if (p_splitter == nullptr || *p_splitter == '\0') { + end = from + 1; + } else { + end = find(p_splitter, from); + if (end < 0) { + end = len; + } + } + if (p_allow_empty || (end > from)) { + if (p_maxsplit <= 0) { + ret.push_back(substr(from, end - from)); + } else { + // Put rest of the string and leave cycle. + if (p_maxsplit == ret.size()) { + ret.push_back(substr(from, len)); + break; + } + + // Otherwise, push items until positive limit is reached. + ret.push_back(substr(from, end - from)); + } + } + + if (end == len) { + break; + } + + from = end + strlen(p_splitter); + } + + return ret; +} + Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { Vector<String> ret; const int len = length(); @@ -1380,6 +1489,49 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int return ret; } +Vector<String> String::rsplit(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const { + Vector<String> ret; + const int len = length(); + const int splitter_length = strlen(p_splitter); + int remaining_len = len; + + while (true) { + if (remaining_len < splitter_length || (p_maxsplit > 0 && p_maxsplit == ret.size())) { + // no room for another splitter or hit max splits, push what's left and we're done + if (p_allow_empty || remaining_len > 0) { + ret.push_back(substr(0, remaining_len)); + } + break; + } + + int left_edge; + if (p_splitter == nullptr || *p_splitter == '\0') { + left_edge = remaining_len - 1; + if (left_edge == 0) { + left_edge--; // Skip to the < 0 condition. + } + } else { + left_edge = rfind(p_splitter, remaining_len - splitter_length); + } + + if (left_edge < 0) { + // no more splitters, we're done + ret.push_back(substr(0, remaining_len)); + break; + } + + int substr_start = left_edge + splitter_length; + if (p_allow_empty || substr_start < remaining_len) { + ret.push_back(substr(substr_start, remaining_len - substr_start)); + } + + remaining_len = left_edge; + } + + ret.reverse(); + return ret; +} + Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const { Vector<double> ret; int from = 0; @@ -3087,23 +3239,20 @@ int String::find(const String &p_str, int p_from) const { } int String::find(const char *p_str, int p_from) const { - if (p_from < 0) { + if (p_from < 0 || !p_str) { return -1; } + const int src_len = strlen(p_str); + const int len = length(); - if (len == 0) { + if (len == 0 || src_len == 0) { return -1; // won't find anything! } const char32_t *src = get_data(); - int src_len = 0; - while (p_str[src_len] != '\0') { - src_len++; - } - if (src_len == 1) { const char32_t needle = p_str[0]; @@ -3238,6 +3387,46 @@ int String::findn(const String &p_str, int p_from) const { return -1; } +int String::findn(const char *p_str, int p_from) const { + if (p_from < 0) { + return -1; + } + + int src_len = strlen(p_str); + + if (src_len == 0 || length() == 0) { + return -1; // won't find anything! + } + + const char32_t *srcd = get_data(); + + for (int i = p_from; i <= (length() - src_len); i++) { + bool found = true; + for (int j = 0; j < src_len; j++) { + int read_pos = i + j; + + if (read_pos >= length()) { + ERR_PRINT("read_pos>=length()"); + return -1; + } + + char32_t src = _find_lower(srcd[read_pos]); + char32_t dst = _find_lower(p_str[j]); + + if (src != dst) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + int String::rfind(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); @@ -3285,6 +3474,57 @@ int String::rfind(const String &p_str, int p_from) const { return -1; } +int String::rfind(const char *p_str, int p_from) const { + const int source_length = length(); + int substring_length = strlen(p_str); + + if (source_length == 0 || substring_length == 0) { + return -1; // won't find anything! + } + + // establish a limit + int limit = length() - substring_length; + if (limit < 0) { + return -1; + } + + // establish a starting point + int starting_point; + if (p_from < 0) { + starting_point = limit; + } else if (p_from > limit) { + starting_point = limit; + } else { + starting_point = p_from; + } + + const char32_t *source = get_data(); + + for (int i = starting_point; i >= 0; i--) { + bool found = true; + for (int j = 0; j < substring_length; j++) { + int read_pos = i + j; + + if (read_pos >= source_length) { + ERR_PRINT("read_pos>=source_length"); + return -1; + } + + const char32_t key_needle = p_str[j]; + if (source[read_pos] != key_needle) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + int String::rfindn(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); @@ -3335,6 +3575,60 @@ int String::rfindn(const String &p_str, int p_from) const { return -1; } +int String::rfindn(const char *p_str, int p_from) const { + const int source_length = length(); + int substring_length = strlen(p_str); + + if (source_length == 0 || substring_length == 0) { + return -1; // won't find anything! + } + + // establish a limit + int limit = length() - substring_length; + if (limit < 0) { + return -1; + } + + // establish a starting point + int starting_point; + if (p_from < 0) { + starting_point = limit; + } else if (p_from > limit) { + starting_point = limit; + } else { + starting_point = p_from; + } + + const char32_t *source = get_data(); + + for (int i = starting_point; i >= 0; i--) { + bool found = true; + for (int j = 0; j < substring_length; j++) { + int read_pos = i + j; + + if (read_pos >= source_length) { + ERR_PRINT("read_pos>=source_length"); + return -1; + } + + const char32_t key_needle = p_str[j]; + int srcc = _find_lower(source[read_pos]); + int keyc = _find_lower(key_needle); + + if (srcc != keyc) { + found = false; + break; + } + } + + if (found) { + return i; + } + } + + return -1; +} + bool String::ends_with(const String &p_string) const { int l = p_string.length(); if (l > length()) { @@ -3357,6 +3651,31 @@ bool String::ends_with(const String &p_string) const { return true; } +bool String::ends_with(const char *p_string) const { + if (!p_string) { + return false; + } + + int l = strlen(p_string); + if (l > length()) { + return false; + } + + if (l == 0) { + return true; + } + + const char32_t *s = &operator[](length() - l); + + for (int i = 0; i < l; i++) { + if (static_cast<char32_t>(p_string[i]) != s[i]) { + return false; + } + } + + return true; +} + bool String::begins_with(const String &p_string) const { int l = p_string.length(); if (l > length()) { @@ -3380,11 +3699,11 @@ bool String::begins_with(const String &p_string) const { } bool String::begins_with(const char *p_string) const { - int l = length(); if (!p_string) { return false; } + int l = length(); if (l == 0) { return *p_string == 0; } @@ -3456,14 +3775,61 @@ int String::_count(const String &p_string, int p_from, int p_to, bool p_case_ins return c; } +int String::_count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const { + int substring_length = strlen(p_string); + if (substring_length == 0) { + return 0; + } + const int source_length = length(); + + if (source_length < substring_length) { + return 0; + } + String str; + int search_limit = p_to; + if (p_from >= 0 && p_to >= 0) { + if (p_to == 0) { + search_limit = source_length; + } else if (p_from >= p_to) { + return 0; + } + if (p_from == 0 && search_limit == source_length) { + str = String(); + str.copy_from_unchecked(&get_data()[0], source_length); + } else { + str = substr(p_from, search_limit - p_from); + } + } else { + return 0; + } + int c = 0; + int idx = -1; + do { + idx = p_case_insensitive ? str.findn(p_string) : str.find(p_string); + if (idx != -1) { + str = str.substr(idx + substring_length, str.length() - substring_length); + ++c; + } + } while (idx != -1); + return c; +} + int String::count(const String &p_string, int p_from, int p_to) const { return _count(p_string, p_from, p_to, false); } +int String::count(const char *p_string, int p_from, int p_to) const { + return _count(p_string, p_from, p_to, false); +} + int String::countn(const String &p_string, int p_from, int p_to) const { return _count(p_string, p_from, p_to, true); } +int String::countn(const char *p_string, int p_from, int p_to) const { + return _count(p_string, p_from, p_to, true); +} + bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const { int len = length(); if (len == 0) { @@ -3598,7 +3964,7 @@ String String::format(const Variant &values, const String &placeholder) const { Variant v_val = values_arr[i]; String val = v_val; - if (placeholder.find("_") > -1) { + if (placeholder.contains("_")) { new_string = new_string.replace(placeholder.replace("_", i_as_str), val); } else { new_string = new_string.replace_first(placeholder, val); @@ -3673,6 +4039,16 @@ String String::replace_first(const String &p_key, const String &p_with) const { return *this; } +String String::replace_first(const char *p_key, const char *p_with) const { + int pos = find(p_key); + if (pos >= 0) { + int substring_length = strlen(p_key); + return substr(0, pos) + p_with + substr(pos + substring_length, length()); + } + + return *this; +} + String String::replacen(const String &p_key, const String &p_with) const { String new_string; int search_from = 0; @@ -3692,6 +4068,31 @@ String String::replacen(const String &p_key, const String &p_with) const { return new_string; } +String String::replacen(const char *p_key, const char *p_with) const { + String new_string; + int search_from = 0; + int result = 0; + int substring_length = strlen(p_key); + + if (substring_length == 0) { + return *this; // there's nothing to match or substitute + } + + while ((result = findn(p_key, search_from)) >= 0) { + new_string += substr(search_from, result - search_from); + new_string += p_with; + search_from = result + substring_length; + } + + if (search_from == 0) { + return *this; + } + + new_string += substr(search_from, length() - search_from); + + return new_string; +} + String String::repeat(int p_count) const { ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number."); @@ -4420,6 +4821,15 @@ String String::trim_prefix(const String &p_prefix) const { return s; } +String String::trim_prefix(const char *p_prefix) const { + String s = *this; + if (s.begins_with(p_prefix)) { + int prefix_length = strlen(p_prefix); + return s.substr(prefix_length, s.length() - prefix_length); + } + return s; +} + String String::trim_suffix(const String &p_suffix) const { String s = *this; if (s.ends_with(p_suffix)) { @@ -4428,6 +4838,14 @@ String String::trim_suffix(const String &p_suffix) const { return s; } +String String::trim_suffix(const char *p_suffix) const { + String s = *this; + if (s.ends_with(p_suffix)) { + return s.substr(0, s.length() - strlen(p_suffix)); + } + return s; +} + bool String::is_valid_int() const { int len = length(); diff --git a/core/string/ustring.h b/core/string/ustring.h index 693df6dcba..9df2d56e80 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -198,6 +198,7 @@ class String { bool _base_is_subsequence_of(const String &p_string, bool case_insensitive) const; int _count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const; + int _count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const; String _camelcase_to_underscore() const; public: @@ -288,14 +289,18 @@ public: int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed int find_char(const char32_t &p_char, int p_from = 0) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive + int findn(const char *p_str, int p_from = 0) const; ///< return <0 if failed int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed + int rfind(const char *p_str, int p_from = -1) const; ///< return <0 if failed int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive + int rfindn(const char *p_str, int p_from = -1) const; ///< return <0 if failed int findmk(const Vector<String> &p_keys, int p_from = 0, int *r_key = nullptr) const; ///< return <0 if failed bool match(const String &p_wildcard) const; bool matchn(const String &p_wildcard) const; bool begins_with(const String &p_string) const; bool begins_with(const char *p_string) const; bool ends_with(const String &p_string) const; + bool ends_with(const char *p_string) const; bool is_enclosed_in(const String &p_string) const; bool is_subsequence_of(const String &p_string) const; bool is_subsequence_ofn(const String &p_string) const; @@ -304,9 +309,11 @@ public: float similarity(const String &p_string) const; String format(const Variant &values, const String &placeholder = "{_}") const; String replace_first(const String &p_key, const String &p_with) const; + String replace_first(const char *p_key, const char *p_with) const; String replace(const String &p_key, const String &p_with) const; String replace(const char *p_key, const char *p_with) const; String replacen(const String &p_key, const String &p_with) const; + String replacen(const char *p_key, const char *p_with) const; String repeat(int p_count) const; String reverse() const; String insert(int p_at_pos, const String &p_string) const; @@ -314,7 +321,9 @@ public: String pad_decimals(int p_digits) const; String pad_zeros(int p_digits) const; String trim_prefix(const String &p_prefix) const; + String trim_prefix(const char *p_prefix) const; String trim_suffix(const String &p_suffix) const; + String trim_suffix(const char *p_suffix) const; String lpad(int min_length, const String &character = " ") const; String rpad(int min_length, const String &character = " ") const; String sprintf(const Array &values, bool *error) const; @@ -353,11 +362,15 @@ public: String get_with_code_lines() const; int get_slice_count(const String &p_splitter) const; + int get_slice_count(const char *p_splitter) const; String get_slice(const String &p_splitter, int p_slice) const; + String get_slice(const char *p_splitter, int p_slice) const; String get_slicec(char32_t p_splitter, int p_slice) const; Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> split(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> rsplit(const char *p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split_spaces() const; Vector<double> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; @@ -372,7 +385,9 @@ public: String to_lower() const; int count(const String &p_string, int p_from = 0, int p_to = 0) const; + int count(const char *p_string, int p_from = 0, int p_to = 0) const; int countn(const String &p_string, int p_from = 0, int p_to = 0) const; + int countn(const char *p_string, int p_from = 0, int p_to = 0) const; String left(int p_len) const; String right(int p_len) const; @@ -414,6 +429,8 @@ public: _FORCE_INLINE_ bool is_empty() const { return length() == 0; } _FORCE_INLINE_ bool contains(const char *p_str) const { return find(p_str) != -1; } _FORCE_INLINE_ bool contains(const String &p_str) const { return find(p_str) != -1; } + _FORCE_INLINE_ bool containsn(const char *p_str) const { return findn(p_str) != -1; } + _FORCE_INLINE_ bool containsn(const String &p_str) const { return findn(p_str) != -1; } // path functions bool is_absolute_path() const; diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h index c149861467..dbf938a117 100644 --- a/core/templates/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -208,7 +208,7 @@ #define ARG(N) p##N #define PARAM(N) P##N p##N #define TYPE_PARAM(N) typename P##N -#define PARAM_DECL(N) typename GetSimpleTypeT<P##N>::type_t p##N +#define PARAM_DECL(N) GetSimpleTypeT<P##N> p##N #define DECL_CMD(N) \ template <typename T, typename M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \ @@ -302,7 +302,7 @@ class CommandQueueMT { struct CommandBase { bool sync = false; virtual void call() = 0; - virtual ~CommandBase() = default; // Won't be called. + virtual ~CommandBase() = default; }; struct SyncCommand : public CommandBase { @@ -327,7 +327,6 @@ class CommandQueueMT { enum { DEFAULT_COMMAND_MEM_SIZE_KB = 256, - SYNC_SEMAPHORES = 8 }; BinaryMutex mutex; @@ -335,6 +334,7 @@ class CommandQueueMT { ConditionVariable sync_cond_var; uint32_t sync_head = 0; uint32_t sync_tail = 0; + uint32_t sync_awaiters = 0; WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID; uint64_t flush_read_ptr = 0; @@ -349,6 +349,15 @@ class CommandQueueMT { return cmd; } + _FORCE_INLINE_ void _prevent_sync_wraparound() { + bool safe_to_reset = !sync_awaiters; + bool already_sync_to_latest = sync_head == sync_tail; + if (safe_to_reset && already_sync_to_latest) { + sync_head = 0; + sync_tail = 0; + } + } + void _flush() { if (unlikely(flush_read_ptr)) { // Re-entrant call. @@ -365,25 +374,39 @@ class CommandQueueMT { cmd->call(); if (unlikely(cmd->sync)) { sync_head++; + unlock(); // Give an opportunity to awaiters right away. sync_cond_var.notify_all(); + lock(); } + // If the command involved reallocating the buffer, the address may have changed. + cmd = reinterpret_cast<CommandBase *>(&command_mem[flush_read_ptr]); + cmd->~CommandBase(); + flush_read_ptr += size; } WorkerThreadPool::thread_exit_command_queue_mt_flush(); command_mem.clear(); flush_read_ptr = 0; + + _prevent_sync_wraparound(); + unlock(); } _FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) { + sync_awaiters++; uint32_t sync_head_goal = sync_tail; do { sync_cond_var.wait(p_lock); - } while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound. + } while (sync_head < sync_head_goal); + sync_awaiters--; + _prevent_sync_wraparound(); } + void _no_op() {} + public: void lock(); void unlock(); @@ -405,10 +428,15 @@ public: _flush(); } } + void flush_all() { _flush(); } + void sync() { + push_and_sync(this, &CommandQueueMT::_no_op); + } + void wait_and_flush() { ERR_FAIL_COND(pump_task_id == WorkerThreadPool::INVALID_TASK_ID); WorkerThreadPool::get_singleton()->wait_for_task_completion(pump_task_id); @@ -416,7 +444,9 @@ public: } void set_pump_task_id(WorkerThreadPool::TaskID p_task_id) { + lock(); pump_task_id = p_task_id; + unlock(); } CommandQueueMT(); diff --git a/core/templates/list.h b/core/templates/list.h index b4d4beb930..6663f06c30 100644 --- a/core/templates/list.h +++ b/core/templates/list.h @@ -139,54 +139,58 @@ public: typedef T ValueType; - struct Iterator { - _FORCE_INLINE_ T &operator*() const { + struct ConstIterator { + _FORCE_INLINE_ const T &operator*() const { return E->get(); } - _FORCE_INLINE_ T *operator->() const { return &E->get(); } - _FORCE_INLINE_ Iterator &operator++() { + _FORCE_INLINE_ const T *operator->() const { return &E->get(); } + _FORCE_INLINE_ ConstIterator &operator++() { E = E->next(); return *this; } - _FORCE_INLINE_ Iterator &operator--() { + _FORCE_INLINE_ ConstIterator &operator--() { E = E->prev(); return *this; } - _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } - Iterator(Element *p_E) { E = p_E; } - Iterator() {} - Iterator(const Iterator &p_it) { E = p_it.E; } + _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; } + _FORCE_INLINE_ ConstIterator() {} + _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; } private: - Element *E = nullptr; + const Element *E = nullptr; }; - struct ConstIterator { - _FORCE_INLINE_ const T &operator*() const { + struct Iterator { + _FORCE_INLINE_ T &operator*() const { return E->get(); } - _FORCE_INLINE_ const T *operator->() const { return &E->get(); } - _FORCE_INLINE_ ConstIterator &operator++() { + _FORCE_INLINE_ T *operator->() const { return &E->get(); } + _FORCE_INLINE_ Iterator &operator++() { E = E->next(); return *this; } - _FORCE_INLINE_ ConstIterator &operator--() { + _FORCE_INLINE_ Iterator &operator--() { E = E->prev(); return *this; } - _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } + _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } - _FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; } - _FORCE_INLINE_ ConstIterator() {} - _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; } + Iterator(Element *p_E) { E = p_E; } + Iterator() {} + Iterator(const Iterator &p_it) { E = p_it.E; } + + operator ConstIterator() const { + return ConstIterator(E); + } private: - const Element *E = nullptr; + Element *E = nullptr; }; _FORCE_INLINE_ Iterator begin() { @@ -519,7 +523,9 @@ public: } } - T &operator[](int p_index) { + // Random access to elements, use with care, + // do not use for iteration. + T &get(int p_index) { CRASH_BAD_INDEX(p_index, size()); Element *I = front(); @@ -532,7 +538,9 @@ public: return I->get(); } - const T &operator[](int p_index) const { + // Random access to elements, use with care, + // do not use for iteration. + const T &get(int p_index) const { CRASH_BAD_INDEX(p_index, size()); const Element *I = front(); diff --git a/core/templates/local_vector.h b/core/templates/local_vector.h index e0047e0782..c281d70d92 100644 --- a/core/templates/local_vector.h +++ b/core/templates/local_vector.h @@ -264,6 +264,10 @@ public: return -1; } + bool has(const T &p_val) const { + return find(p_val) != -1; + } + template <typename C> void sort_custom() { U len = count; diff --git a/core/templates/simple_type.h b/core/templates/simple_type.h index b2ae0110e2..197115ddb9 100644 --- a/core/templates/simple_type.h +++ b/core/templates/simple_type.h @@ -31,26 +31,9 @@ #ifndef SIMPLE_TYPE_H #define SIMPLE_TYPE_H -/* Batch of specializations to obtain the actual simple type */ +#include <type_traits> template <typename T> -struct GetSimpleTypeT { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T &> { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T const> { - typedef T type_t; -}; - -template <typename T> -struct GetSimpleTypeT<T const &> { - typedef T type_t; -}; +using GetSimpleTypeT = typename std::remove_cv_t<std::remove_reference_t<T>>; #endif // SIMPLE_TYPE_H diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 0fe4518b0f..61b90e2a26 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -362,42 +362,42 @@ void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void template <typename T, typename... P, size_t... Is> void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { - (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename... P, size_t... Is> void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence<Is...>) { - (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename R, typename... P, size_t... Is> void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename T, typename... P, size_t... Is> void call_with_validated_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, IndexSequence<Is...>) { - p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + p_method(p_instance, (VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename R, typename... P, size_t... Is> void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { - VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); + VariantInternalAccessor<GetSimpleTypeT<R>>::set(r_ret, p_method((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...)); } template <typename... P, size_t... Is> void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { - p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); + p_method((VariantInternalAccessor<GetSimpleTypeT<P>>::get(p_args[Is]))...); } template <typename T, typename... P> diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 7012bf698d..9b7777f480 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1648,19 +1648,19 @@ static void _register_variant_builtin_methods() { bind_string_method(filenocasecmp_to, sarray("to"), varray()); bind_string_method(length, sarray(), varray()); bind_string_method(substr, sarray("from", "len"), varray(-1)); - bind_string_method(get_slice, sarray("delimiter", "slice"), varray()); + bind_string_methodv(get_slice, static_cast<String (String::*)(const String &, int) const>(&String::get_slice), sarray("delimiter", "slice"), varray()); bind_string_method(get_slicec, sarray("delimiter", "slice"), varray()); - bind_string_method(get_slice_count, sarray("delimiter"), varray()); + bind_string_methodv(get_slice_count, static_cast<int (String::*)(const String &) const>(&String::get_slice_count), sarray("delimiter"), varray()); bind_string_methodv(find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0)); - bind_string_method(count, sarray("what", "from", "to"), varray(0, 0)); - bind_string_method(countn, sarray("what", "from", "to"), varray(0, 0)); - bind_string_method(findn, sarray("what", "from"), varray(0)); - bind_string_method(rfind, sarray("what", "from"), varray(-1)); - bind_string_method(rfindn, sarray("what", "from"), varray(-1)); + bind_string_methodv(findn, static_cast<int (String::*)(const String &, int) const>(&String::findn), sarray("what", "from"), varray(0)); + bind_string_methodv(count, static_cast<int (String::*)(const String &, int, int) const>(&String::count), sarray("what", "from", "to"), varray(0, 0)); + bind_string_methodv(countn, static_cast<int (String::*)(const String &, int, int) const>(&String::countn), sarray("what", "from", "to"), varray(0, 0)); + bind_string_methodv(rfind, static_cast<int (String::*)(const String &, int) const>(&String::rfind), sarray("what", "from"), varray(-1)); + bind_string_methodv(rfindn, static_cast<int (String::*)(const String &, int) const>(&String::rfindn), sarray("what", "from"), varray(-1)); bind_string_method(match, sarray("expr"), varray()); bind_string_method(matchn, sarray("expr"), varray()); bind_string_methodv(begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray()); - bind_string_method(ends_with, sarray("text"), varray()); + bind_string_methodv(ends_with, static_cast<bool (String::*)(const String &) const>(&String::ends_with), sarray("text"), varray()); bind_string_method(is_subsequence_of, sarray("text"), varray()); bind_string_method(is_subsequence_ofn, sarray("text"), varray()); bind_string_method(bigrams, sarray(), varray()); @@ -1668,7 +1668,7 @@ static void _register_variant_builtin_methods() { bind_string_method(format, sarray("values", "placeholder"), varray("{_}")); bind_string_methodv(replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray()); - bind_string_method(replacen, sarray("what", "forwhat"), varray()); + bind_string_methodv(replacen, static_cast<String (String::*)(const String &, const String &) const>(&String::replacen), sarray("what", "forwhat"), varray()); bind_string_method(repeat, sarray("count"), varray()); bind_string_method(reverse, sarray(), varray()); bind_string_method(insert, sarray("position", "what"), varray()); @@ -1677,8 +1677,8 @@ static void _register_variant_builtin_methods() { bind_string_method(to_camel_case, sarray(), varray()); bind_string_method(to_pascal_case, sarray(), varray()); bind_string_method(to_snake_case, sarray(), varray()); - bind_string_method(split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); - bind_string_method(rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_methodv(split, static_cast<Vector<String> (String::*)(const String &, bool, int) const>(&String::split), sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); + bind_string_methodv(rsplit, static_cast<Vector<String> (String::*)(const String &, bool, int) const>(&String::rsplit), sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0)); bind_string_method(split_floats, sarray("delimiter", "allow_empty"), varray(true)); bind_string_method(join, sarray("parts"), varray()); @@ -1707,6 +1707,7 @@ static void _register_variant_builtin_methods() { bind_string_method(sha256_buffer, sarray(), varray()); bind_string_method(is_empty, sarray(), varray()); bind_string_methodv(contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray()); + bind_string_methodv(containsn, static_cast<bool (String::*)(const String &) const>(&String::containsn), sarray("what"), varray()); bind_string_method(is_absolute_path, sarray(), varray()); bind_string_method(is_relative_path, sarray(), varray()); @@ -1741,8 +1742,8 @@ static void _register_variant_builtin_methods() { bind_string_method(rpad, sarray("min_length", "character"), varray(" ")); bind_string_method(pad_decimals, sarray("digits"), varray()); bind_string_method(pad_zeros, sarray("digits"), varray()); - bind_string_method(trim_prefix, sarray("prefix"), varray()); - bind_string_method(trim_suffix, sarray("suffix"), varray()); + bind_string_methodv(trim_prefix, static_cast<String (String::*)(const String &) const>(&String::trim_prefix), sarray("prefix"), varray()); + bind_string_methodv(trim_suffix, static_cast<String (String::*)(const String &) const>(&String::trim_suffix), sarray("suffix"), varray()); bind_string_method(to_ascii_buffer, sarray(), varray()); bind_string_method(to_utf8_buffer, sarray(), varray()); diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index ec87081f15..c52ab6917b 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -1546,7 +1546,7 @@ struct VariantTypeChanger { template <typename T> struct VariantTypeAdjust { _FORCE_INLINE_ static void adjust(Variant *r_ret) { - VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret); + VariantTypeChanger<GetSimpleTypeT<T>>::change(r_ret); } }; |