Allow indexing of String values in scripting languages
This commit is contained in:
parent
424ddcba37
commit
262d9397fb
3 changed files with 165 additions and 0 deletions
|
@ -661,6 +661,91 @@ struct VariantIndexedSetGet_Array {
|
|||
static uint64_t get_indexed_size(const Variant *base) { return 0; }
|
||||
};
|
||||
|
||||
struct VariantIndexedSetGet_String {
|
||||
static void get(const Variant *base, int64_t index, Variant *value, bool *oob) {
|
||||
int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
|
||||
if (index < 0) {
|
||||
index += length;
|
||||
}
|
||||
if (index < 0 || index >= length) {
|
||||
*oob = true;
|
||||
return;
|
||||
}
|
||||
char32_t result = (*VariantGetInternalPtr<String>::get_ptr(base))[index];
|
||||
*value = String(&result, 1);
|
||||
*oob = false;
|
||||
}
|
||||
static void ptr_get(const void *base, int64_t index, void *member) {
|
||||
/* avoid ptrconvert for performance*/
|
||||
const String &v = *reinterpret_cast<const String *>(base);
|
||||
if (index < 0) {
|
||||
index += v.length();
|
||||
}
|
||||
OOB_TEST(index, v.length());
|
||||
char32_t c = v[index];
|
||||
PtrToArg<String>::encode(String(&c, 1), member);
|
||||
}
|
||||
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
|
||||
if (value->get_type() != Variant::STRING) {
|
||||
*oob = false;
|
||||
*valid = false;
|
||||
return;
|
||||
}
|
||||
int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
|
||||
if (index < 0) {
|
||||
index += length;
|
||||
}
|
||||
if (index < 0 || index >= length) {
|
||||
*oob = true;
|
||||
*valid = false;
|
||||
return;
|
||||
}
|
||||
String *b = VariantGetInternalPtr<String>::get_ptr(base);
|
||||
const String *v = VariantInternal::get_string(value);
|
||||
if (v->length() == 0) {
|
||||
b->remove(index);
|
||||
} else {
|
||||
b->set(index, v->get(0));
|
||||
}
|
||||
*oob = false;
|
||||
*valid = true;
|
||||
}
|
||||
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
|
||||
int64_t length = VariantGetInternalPtr<String>::get_ptr(base)->length();
|
||||
if (index < 0) {
|
||||
index += length;
|
||||
}
|
||||
if (index < 0 || index >= length) {
|
||||
*oob = true;
|
||||
return;
|
||||
}
|
||||
String *b = VariantGetInternalPtr<String>::get_ptr(base);
|
||||
const String *v = VariantInternal::get_string(value);
|
||||
if (v->length() == 0) {
|
||||
b->remove(index);
|
||||
} else {
|
||||
b->set(index, v->get(0));
|
||||
}
|
||||
*oob = false;
|
||||
}
|
||||
static void ptr_set(void *base, int64_t index, const void *member) {
|
||||
/* avoid ptrconvert for performance*/
|
||||
String &v = *reinterpret_cast<String *>(base);
|
||||
if (index < 0) {
|
||||
index += v.length();
|
||||
}
|
||||
OOB_TEST(index, v.length());
|
||||
const String &m = *reinterpret_cast<const String *>(member);
|
||||
if (unlikely(m.length() == 0)) {
|
||||
v.remove(index);
|
||||
} else {
|
||||
v.set(index, m.unicode_at(0));
|
||||
}
|
||||
}
|
||||
static Variant::Type get_index_type() { return Variant::STRING; }
|
||||
static uint64_t get_indexed_size(const Variant *base) { return VariantInternal::get_string(base)->length(); }
|
||||
};
|
||||
|
||||
#define INDEXED_SETGET_STRUCT_DICT(m_base_type) \
|
||||
struct VariantIndexedSetGet_##m_base_type { \
|
||||
static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \
|
||||
|
@ -758,6 +843,7 @@ static void register_indexed_member(Variant::Type p_type) {
|
|||
void register_indexed_setters_getters() {
|
||||
#define REGISTER_INDEXED_MEMBER(m_base_type) register_indexed_member<VariantIndexedSetGet_##m_base_type>(GetTypeInfo<m_base_type>::VARIANT_TYPE)
|
||||
|
||||
REGISTER_INDEXED_MEMBER(String);
|
||||
REGISTER_INDEXED_MEMBER(Vector2);
|
||||
REGISTER_INDEXED_MEMBER(Vector2i);
|
||||
REGISTER_INDEXED_MEMBER(Vector3);
|
||||
|
|
|
@ -513,6 +513,12 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="operator []" qualifiers="operator">
|
||||
<return type="String" />
|
||||
<argument index="0" name="index" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="pad_decimals" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="digits" type="int" />
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "core/os/main_loop.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
#include "tests/test_macros.h"
|
||||
|
||||
|
@ -1380,6 +1381,78 @@ TEST_CASE("[String] validate_node_name") {
|
|||
String name_with_invalid_chars = "Name with invalid characters :.@removed!";
|
||||
CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!");
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant indexed get") {
|
||||
Variant s = String("abcd");
|
||||
bool valid = false;
|
||||
bool oob = true;
|
||||
|
||||
String r = s.get_indexed(1, valid, oob);
|
||||
|
||||
CHECK(valid);
|
||||
CHECK_FALSE(oob);
|
||||
CHECK_EQ(r, String("b"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant validated indexed get") {
|
||||
Variant s = String("abcd");
|
||||
|
||||
Variant::ValidatedIndexedGetter getter = Variant::get_member_validated_indexed_getter(Variant::STRING);
|
||||
|
||||
Variant r;
|
||||
bool oob = true;
|
||||
getter(&s, 1, &r, &oob);
|
||||
|
||||
CHECK_FALSE(oob);
|
||||
CHECK_EQ(r, String("b"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant ptr indexed get") {
|
||||
String s("abcd");
|
||||
|
||||
Variant::PTRIndexedGetter getter = Variant::get_member_ptr_indexed_getter(Variant::STRING);
|
||||
|
||||
String r;
|
||||
getter(&s, 1, &r);
|
||||
|
||||
CHECK_EQ(r, String("b"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant indexed set") {
|
||||
Variant s = String("abcd");
|
||||
bool valid = false;
|
||||
bool oob = true;
|
||||
|
||||
s.set_indexed(1, String("z"), valid, oob);
|
||||
|
||||
CHECK(valid);
|
||||
CHECK_FALSE(oob);
|
||||
CHECK_EQ(s, String("azcd"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant validated indexed set") {
|
||||
Variant s = String("abcd");
|
||||
|
||||
Variant::ValidatedIndexedSetter setter = Variant::get_member_validated_indexed_setter(Variant::STRING);
|
||||
|
||||
Variant v = String("z");
|
||||
bool oob = true;
|
||||
setter(&s, 1, &v, &oob);
|
||||
|
||||
CHECK_FALSE(oob);
|
||||
CHECK_EQ(s, String("azcd"));
|
||||
}
|
||||
|
||||
TEST_CASE("[String] Variant ptr indexed set") {
|
||||
String s("abcd");
|
||||
|
||||
Variant::PTRIndexedSetter setter = Variant::get_member_ptr_indexed_setter(Variant::STRING);
|
||||
|
||||
String v("z");
|
||||
setter(&s, 1, &v);
|
||||
|
||||
CHECK_EQ(s, String("azcd"));
|
||||
}
|
||||
} // namespace TestString
|
||||
|
||||
#endif // TEST_STRING_H
|
||||
|
|
Loading…
Reference in a new issue