summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/project_settings.cpp2
-rw-r--r--core/debugger/debugger_marshalls.cpp8
-rw-r--r--core/debugger/engine_debugger.cpp2
-rw-r--r--core/debugger/remote_debugger.cpp3
-rw-r--r--core/debugger/remote_debugger_peer.cpp4
-rw-r--r--core/doc_data.cpp5
-rw-r--r--core/extension/extension_api_dump.cpp37
-rw-r--r--core/extension/gdextension.cpp11
-rw-r--r--core/extension/gdextension_interface.h4
-rw-r--r--core/input/input.cpp12
-rw-r--r--core/input/input.h2
-rw-r--r--core/io/ip.cpp16
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/io/udp_server.cpp2
-rw-r--r--core/math/static_raycaster.h2
-rw-r--r--core/object/class_db.cpp9
-rw-r--r--core/object/method_bind.h9
-rw-r--r--core/object/object.cpp12
-rw-r--r--core/object/script_language_extension.h11
-rw-r--r--core/string/ustring.cpp436
-rw-r--r--core/string/ustring.h17
-rw-r--r--core/templates/command_queue_mt.h38
-rw-r--r--core/templates/list.h56
-rw-r--r--core/templates/local_vector.h4
-rw-r--r--core/templates/simple_type.h21
-rw-r--r--core/variant/binder_common.h16
-rw-r--r--core/variant/variant_call.cpp27
-rw-r--r--core/variant/variant_internal.h2
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);
}
};