Merge pull request #40999 from bruvzg/ctl_string_to_utf32

[Complex Test Layouts] Refactor `String` to use UTF-32 encoding.
This commit is contained in:
Rémi Verschelde 2020-09-03 21:35:27 +02:00 committed by GitHub
commit 27763b67bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 4889 additions and 1686 deletions

View file

@ -390,7 +390,7 @@ String _to_hex(float p_val) {
String ret;
for (int i = 0; i < 2; i++) {
CharType c[2] = { 0, 0 };
char32_t c[2] = { 0, 0 };
int lv = v & 0xF;
if (lv < 10) {
c[0] = '0' + lv;
@ -399,7 +399,7 @@ String _to_hex(float p_val) {
}
v >>= 4;
String cs = (const CharType *)c;
String cs = (const char32_t *)c;
ret = cs + ret;
}

View file

@ -40,6 +40,7 @@
template <class T>
class Vector;
class String;
class Char16String;
class CharString;
template <class T, class V>
class VMap;
@ -49,6 +50,7 @@ class CowData {
template <class TV>
friend class Vector;
friend class String;
friend class Char16String;
friend class CharString;
template <class TV, class VV>
friend class VMap;

View file

@ -146,6 +146,8 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return (uint32_t)p_uchar; }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return (uint32_t)p_uchar; }
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }

View file

@ -46,7 +46,7 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_
void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {
PathMD5 pmd5(path.md5_buffer());
//printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b);
//printf("adding path %s, %lli, %lli\n", path.utf8().get_data(), pmd5.a, pmd5.b);
bool exists = files.has(pmd5);

View file

@ -148,7 +148,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
}
bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset = 0) {
//printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
//printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
// load with offset feature only supported for PCK files
ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives.");
@ -201,7 +201,7 @@ bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files);
//printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str());
//printf("packed data add path %s, %s\n", p_name.utf8().get_data(), fname.utf8().get_data());
if ((i + 1) < gi.number_entry) {
unzGoToNextFile(zfile);

View file

@ -71,7 +71,7 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) {
}
int n = 0;
CharType c = p_string[i];
char32_t c = p_string[i];
if (c >= '0' && c <= '9') {
n = c - '0';
} else if (c >= 'a' && c <= 'f') {
@ -101,7 +101,7 @@ void IP_Address::_parse_ipv6(const String &p_string) {
int parts_idx = 0;
for (int i = 0; i < p_string.length(); i++) {
CharType c = p_string[i];
char32_t c = p_string[i];
if (c == ':') {
if (i == 0) {
continue; // next must be a ":"

View file

@ -125,7 +125,7 @@ String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_key
return _print_var(p_var, p_indent, 0, p_sort_keys);
}
Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {
Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {
while (p_len > 0) {
switch (p_str[index]) {
case '\n': {
@ -180,12 +180,12 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
} else if (p_str[index] == '\\') {
//escaped characters...
index++;
CharType next = p_str[index];
char32_t next = p_str[index];
if (next == 0) {
r_err_str = "Unterminated String";
return ERR_PARSE_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -206,7 +206,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
case 'u': {
// hex number
for (int j = 0; j < 4; j++) {
CharType c = p_str[index + j + 1];
char32_t c = p_str[index + j + 1];
if (c == 0) {
r_err_str = "Unterminated String";
return ERR_PARSE_ERROR;
@ -215,7 +215,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
r_err_str = "Malformed hex constant in string";
return ERR_PARSE_ERROR;
}
CharType v;
char32_t v;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
@ -264,7 +264,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
if (p_str[index] == '-' || (p_str[index] >= '0' && p_str[index] <= '9')) {
//a number
const CharType *rptr;
const char32_t *rptr;
double number = String::to_float(&p_str[index], &rptr);
index += (rptr - &p_str[index]);
r_token.type = TK_NUMBER;
@ -293,7 +293,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
return ERR_PARSE_ERROR;
}
Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
if (token.type == TK_CURLY_BRACKET_OPEN) {
Dictionary d;
Error err = _parse_object(d, p_str, index, p_len, line, r_err_str);
@ -337,7 +337,7 @@ Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, in
}
}
Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
Token token;
bool need_comma = false;
@ -375,7 +375,7 @@ Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_
return ERR_PARSE_ERROR;
}
Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) {
Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) {
bool at_key = true;
String key;
Token token;
@ -439,7 +439,7 @@ Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index,
}
Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
const CharType *str = p_json.ptr();
const char32_t *str = p_json.ptr();
int idx = 0;
int len = p_json.length();
Token token;

View file

@ -65,10 +65,10 @@ class JSON {
static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys);
static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
public:
static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true);

View file

@ -36,7 +36,7 @@
VARIANT_ENUM_CAST(XMLParser::NodeType);
static bool _equalsn(const CharType *str1, const CharType *str2, int len) {
static bool _equalsn(const char32_t *str1, const char32_t *str2, int len) {
int i;
for (i = 0; i < len && str1[i] && str2[i]; ++i) {
if (str1[i] != str2[i]) {
@ -64,7 +64,7 @@ String XMLParser::_replace_special_characters(const String &origstr) {
int specialChar = -1;
for (int i = 0; i < (int)special_characters.size(); ++i) {
const CharType *p = &origstr[pos] + 1;
const char32_t *p = &origstr[pos] + 1;
if (_equalsn(&special_characters[i][1], p, special_characters[i].length() - 1)) {
specialChar = i;

View file

@ -596,7 +596,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
} break;
case TEXT_CHAR: {
CharType result[2] = { *p_inputs[0], 0 };
char32_t result[2] = { *p_inputs[0], 0 };
*r_return = String(result);
@ -739,7 +739,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
////////
static bool _is_number(CharType c) {
static bool _is_number(char32_t c) {
return (c >= '0' && c <= '9');
}
@ -747,7 +747,7 @@ Error Expression::_get_token(Token &r_token) {
while (true) {
#define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++])
CharType cchar = GET_CHAR();
char32_t cchar = GET_CHAR();
switch (cchar) {
case 0: {
@ -900,7 +900,7 @@ Error Expression::_get_token(Token &r_token) {
case '"': {
String str;
while (true) {
CharType ch = GET_CHAR();
char32_t ch = GET_CHAR();
if (ch == 0) {
_set_error("Unterminated String");
@ -912,13 +912,13 @@ Error Expression::_get_token(Token &r_token) {
} else if (ch == '\\') {
//escaped characters...
CharType next = GET_CHAR();
char32_t next = GET_CHAR();
if (next == 0) {
_set_error("Unterminated String");
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -939,7 +939,7 @@ Error Expression::_get_token(Token &r_token) {
case 'u': {
// hex number
for (int j = 0; j < 4; j++) {
CharType c = GET_CHAR();
char32_t c = GET_CHAR();
if (c == 0) {
_set_error("Unterminated String");
@ -951,7 +951,7 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType v;
char32_t v;
if (_is_number(c)) {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
@ -992,7 +992,7 @@ Error Expression::_get_token(Token &r_token) {
break;
}
CharType next_char = (str_ofs >= expression.length()) ? 0 : expression[str_ofs];
char32_t next_char = (str_ofs >= expression.length()) ? 0 : expression[str_ofs];
if (_is_number(cchar) || (cchar == '.' && _is_number(next_char))) {
//a number
@ -1004,7 +1004,7 @@ Error Expression::_get_token(Token &r_token) {
#define READING_DONE 4
int reading = READING_INT;
CharType c = cchar;
char32_t c = cchar;
bool exp_sign = false;
bool exp_beg = false;
bool is_float = false;

View file

@ -181,18 +181,18 @@ VARIANT_ENUM_CAST(Variant::Type);
VARIANT_ENUM_CAST(Variant::Operator);
template <>
struct VariantCaster<wchar_t> {
static _FORCE_INLINE_ wchar_t cast(const Variant &p_variant) {
return (wchar_t)p_variant.operator int();
struct VariantCaster<char32_t> {
static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) {
return (char32_t)p_variant.operator int();
}
};
#ifdef PTRCALL_ENABLED
template <>
struct PtrToArg<wchar_t> {
_FORCE_INLINE_ static wchar_t convert(const void *p_ptr) {
return wchar_t(*reinterpret_cast<const int *>(p_ptr));
struct PtrToArg<char32_t> {
_FORCE_INLINE_ static char32_t convert(const void *p_ptr) {
return char32_t(*reinterpret_cast<const int *>(p_ptr));
}
_FORCE_INLINE_ static void encode(wchar_t p_val, const void *p_ptr) {
_FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) {
*(int *)p_ptr = p_val;
}
};

View file

@ -234,7 +234,7 @@ double FileAccess::get_double() const {
String FileAccess::get_token() const {
CharString token;
CharType c = get_8();
char32_t c = get_8();
while (!eof_reached()) {
if (c <= ' ') {
@ -299,7 +299,7 @@ public:
String FileAccess::get_line() const {
CharBuffer line;
CharType c = get_8();
char32_t c = get_8();
while (!eof_reached()) {
if (c == '\n' || c == '\0') {
@ -342,8 +342,8 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
bool in_quote = false;
String current;
for (int i = 0; i < l.length(); i++) {
CharType c = l[i];
CharType s[2] = { 0, 0 };
char32_t c = l[i];
char32_t s[2] = { 0, 0 };
if (!in_quote && c == p_delim[0]) {
strings.push_back(current);

View file

@ -35,21 +35,21 @@
template <int SHORT_BUFFER_SIZE = 64>
class StringBuffer {
CharType short_buffer[SHORT_BUFFER_SIZE];
char32_t short_buffer[SHORT_BUFFER_SIZE];
String buffer;
int string_length = 0;
_FORCE_INLINE_ CharType *current_buffer_ptr() {
_FORCE_INLINE_ char32_t *current_buffer_ptr() {
return static_cast<String &>(buffer).empty() ? short_buffer : buffer.ptrw();
}
public:
StringBuffer &append(CharType p_char);
StringBuffer &append(char32_t p_char);
StringBuffer &append(const String &p_string);
StringBuffer &append(const char *p_str);
StringBuffer &append(const CharType *p_str, int p_clip_to_len = -1);
StringBuffer &append(const char32_t *p_str, int p_clip_to_len = -1);
_FORCE_INLINE_ void operator+=(CharType p_char) {
_FORCE_INLINE_ void operator+=(char32_t p_char) {
append(p_char);
}
@ -61,7 +61,7 @@ public:
append(p_str);
}
_FORCE_INLINE_ void operator+=(const CharType *p_str) {
_FORCE_INLINE_ void operator+=(const char32_t *p_str) {
append(p_str);
}
@ -80,7 +80,7 @@ public:
};
template <int SHORT_BUFFER_SIZE>
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(CharType p_char) {
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(char32_t p_char) {
reserve(string_length + 2);
current_buffer_ptr()[string_length++] = p_char;
return *this;
@ -88,7 +88,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(CharTyp
template <int SHORT_BUFFER_SIZE>
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const String &p_string) {
return append(p_string.c_str());
return append(p_string.get_data());
}
template <int SHORT_BUFFER_SIZE>
@ -96,7 +96,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const c
int len = strlen(p_str);
reserve(string_length + len + 1);
CharType *buf = current_buffer_ptr();
char32_t *buf = current_buffer_ptr();
for (const char *c_ptr = p_str; *c_ptr; ++c_ptr) {
buf[string_length++] = *c_ptr;
}
@ -104,13 +104,13 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const c
}
template <int SHORT_BUFFER_SIZE>
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const CharType *p_str, int p_clip_to_len) {
StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const char32_t *p_str, int p_clip_to_len) {
int len = 0;
while ((p_clip_to_len < 0 || len < p_clip_to_len) && p_str[len]) {
++len;
}
reserve(string_length + len + 1);
memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(CharType));
memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(char32_t));
string_length += len;
return *this;
@ -125,7 +125,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_
bool need_copy = string_length > 0 && buffer.empty();
buffer.resize(next_power_of_2(p_size));
if (need_copy) {
memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(CharType));
memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(char32_t));
}
return *this;

View file

@ -61,7 +61,7 @@ String StringBuilder::as_string() const {
return "";
}
CharType *buffer = memnew_arr(CharType, string_length);
char32_t *buffer = memnew_arr(char32_t, string_length);
int current_position = 0;
@ -73,7 +73,7 @@ String StringBuilder::as_string() const {
// Godot string
const String &s = strings[godot_string_elem];
memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(CharType));
memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(char32_t));
current_position += s.length();

View file

@ -317,7 +317,7 @@ StringName StringName::search(const char *p_name) {
return StringName(); //does not exist
}
StringName StringName::search(const CharType *p_name) {
StringName StringName::search(const char32_t *p_name) {
ERR_FAIL_COND_V(!configured, StringName());
ERR_FAIL_COND_V(!p_name, StringName());

View file

@ -122,7 +122,7 @@ public:
}
static StringName search(const char *p_name);
static StringName search(const CharType *p_name);
static StringName search(const char32_t *p_name);
static StringName search(const String &p_name);
struct AlphCompare {

View file

@ -132,7 +132,8 @@ MAKE_TYPE_INFO_WITH_META(uint32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_
MAKE_TYPE_INFO_WITH_META(int32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT32)
MAKE_TYPE_INFO_WITH_META(uint64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT64)
MAKE_TYPE_INFO_WITH_META(int64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT64)
MAKE_TYPE_INFO(wchar_t, Variant::INT)
MAKE_TYPE_INFO(char16_t, Variant::INT)
MAKE_TYPE_INFO(char32_t, Variant::INT)
MAKE_TYPE_INFO_WITH_META(float, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_FLOAT)
MAKE_TYPE_INFO_WITH_META(double, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_DOUBLE)

File diff suppressed because it is too large Load diff

View file

@ -36,8 +36,13 @@
#include "core/typedefs.h"
#include "core/vector.h"
/*************************************************************************/
/* CharProxy */
/*************************************************************************/
template <class T>
class CharProxy {
friend class Char16String;
friend class CharString;
friend class String;
@ -71,6 +76,54 @@ public:
}
};
/*************************************************************************/
/* Char16String */
/*************************************************************************/
class Char16String {
CowData<char16_t> _cowdata;
static const char16_t _null;
public:
_FORCE_INLINE_ char16_t *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const char16_t *ptr() const { return _cowdata.ptr(); }
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(int p_size) { return _cowdata.resize(p_size); }
_FORCE_INLINE_ char16_t get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const char16_t &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ const char16_t &operator[](int p_index) const {
if (unlikely(p_index == _cowdata.size())) {
return _null;
}
return _cowdata.get(p_index);
}
_FORCE_INLINE_ CharProxy<char16_t> operator[](int p_index) { return CharProxy<char16_t>(p_index, _cowdata); }
_FORCE_INLINE_ Char16String() {}
_FORCE_INLINE_ Char16String(const Char16String &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ Char16String operator=(const Char16String &p_str) {
_cowdata._ref(p_str._cowdata);
return *this;
}
_FORCE_INLINE_ Char16String(const char16_t *p_cstr) { copy_from(p_cstr); }
Char16String &operator=(const char16_t *p_cstr);
bool operator<(const Char16String &p_right) const;
Char16String &operator+=(char16_t p_char);
int length() const { return size() ? size() - 1 : 0; }
const char16_t *get_data() const;
operator const char16_t *() const { return get_data(); };
protected:
void copy_from(const char16_t *p_cstr);
};
/*************************************************************************/
/* CharString */
/*************************************************************************/
class CharString {
CowData<char> _cowdata;
static const char _null;
@ -111,26 +164,35 @@ protected:
void copy_from(const char *p_cstr);
};
typedef wchar_t CharType;
/*************************************************************************/
/* String */
/*************************************************************************/
struct StrRange {
const CharType *c_str;
const char32_t *c_str;
int len;
StrRange(const CharType *p_c_str = nullptr, int p_len = 0) {
StrRange(const char32_t *p_c_str = nullptr, int p_len = 0) {
c_str = p_c_str;
len = p_len;
}
};
class String {
CowData<CharType> _cowdata;
static const CharType _null;
CowData<char32_t> _cowdata;
static const char32_t _null;
void copy_from(const char *p_cstr);
void copy_from(const CharType *p_cstr, const int p_clip_to = -1);
void copy_from(const CharType &p_char);
void copy_from_unchecked(const CharType *p_char, const int p_length);
void copy_from(const char *p_cstr, const int p_clip_to);
void copy_from(const wchar_t *p_cstr);
void copy_from(const wchar_t *p_cstr, const int p_clip_to);
void copy_from(const char32_t *p_cstr);
void copy_from(const char32_t *p_cstr, const int p_clip_to);
void copy_from(const char32_t &p_char);
void copy_from_unchecked(const char32_t *p_char, const int p_length);
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;
@ -140,48 +202,56 @@ public:
npos = -1 ///<for "some" compatibility with std::string (npos is a huge value in std::string)
};
_FORCE_INLINE_ CharType *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const CharType *ptr() const { return _cowdata.ptr(); }
_FORCE_INLINE_ char32_t *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const char32_t *ptr() const { return _cowdata.ptr(); }
void remove(int p_index) { _cowdata.remove(p_index); }
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ CharType get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const CharType &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ char32_t get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const char32_t &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(int p_size) { return _cowdata.resize(p_size); }
_FORCE_INLINE_ const CharType &operator[](int p_index) const {
_FORCE_INLINE_ const char32_t &operator[](int p_index) const {
if (unlikely(p_index == _cowdata.size())) {
return _null;
}
return _cowdata.get(p_index);
}
_FORCE_INLINE_ CharProxy<CharType> operator[](int p_index) { return CharProxy<CharType>(p_index, _cowdata); }
_FORCE_INLINE_ CharProxy<char32_t> operator[](int p_index) { return CharProxy<char32_t>(p_index, _cowdata); }
bool operator==(const String &p_str) const;
bool operator!=(const String &p_str) const;
String operator+(const String &p_str) const;
//String operator+(CharType p_char) const;
String &operator+=(const String &);
String &operator+=(CharType p_char);
String &operator+=(char32_t p_char);
String &operator+=(const char *p_str);
String &operator+=(const CharType *p_str);
String &operator+=(const wchar_t *p_str);
String &operator+=(const char32_t *p_str);
/* Compatibility Operators */
void operator=(const char *p_str);
void operator=(const CharType *p_str);
void operator=(const wchar_t *p_str);
void operator=(const char32_t *p_str);
bool operator==(const char *p_str) const;
bool operator==(const CharType *p_str) const;
bool operator==(const wchar_t *p_str) const;
bool operator==(const char32_t *p_str) const;
bool operator==(const StrRange &p_str_range) const;
bool operator!=(const char *p_str) const;
bool operator!=(const CharType *p_str) const;
bool operator<(const CharType *p_str) const;
bool operator!=(const wchar_t *p_str) const;
bool operator!=(const char32_t *p_str) const;
bool operator<(const char32_t *p_str) const;
bool operator<(const char *p_str) const;
bool operator<(const wchar_t *p_str) const;
bool operator<(const String &p_str) const;
bool operator<=(const String &p_str) const;
@ -189,7 +259,7 @@ public:
signed char nocasecmp_to(const String &p_str) const;
signed char naturalnocasecmp_to(const String &p_str) const;
const CharType *c_str() const;
const char32_t *get_data() const;
/* standard size stuff */
_FORCE_INLINE_ int length() const {
@ -197,11 +267,13 @@ public:
return s ? (s - 1) : 0; // length does not include zero
}
bool is_valid_string() const;
/* complex helpers */
String substr(int p_from, int p_chars = -1) const;
int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed
int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed
int find_char(const CharType &p_char, 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 rfind(const String &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
@ -238,26 +310,31 @@ public:
static String num_real(double p_num);
static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false);
static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false);
static String chr(CharType p_char);
static String chr(char32_t p_char);
static String md5(const uint8_t *p_md5);
static String hex_encode_buffer(const uint8_t *p_buffer, int p_len);
bool is_numeric() const;
double to_float() const;
double to_float() const;
int64_t hex_to_int(bool p_with_prefix = true) const;
int64_t bin_to_int(bool p_with_prefix = true) const;
int64_t to_int() const;
static int64_t to_int(const char *p_str, int p_len = -1);
static int64_t to_int(const wchar_t *p_str, int p_len = -1);
static int64_t to_int(const char32_t *p_str, int p_len = -1, bool p_clamp = false);
static double to_float(const char *p_str);
static double to_float(const CharType *p_str, const CharType **r_end = nullptr);
static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false);
static double to_float(const wchar_t *p_str, const wchar_t **r_end = nullptr);
static double to_float(const char32_t *p_str, const char32_t **r_end = nullptr);
String capitalize() const;
String camelcase_to_underscore(bool lowercase = true) const;
String get_with_code_lines() const;
int get_slice_count(String p_splitter) const;
String get_slice(String p_splitter, int p_slice) const;
String get_slicec(CharType 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> rsplit(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const;
@ -267,10 +344,10 @@ public:
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
String join(Vector<String> parts);
String join(Vector<String> parts) const;
static CharType char_uppercase(CharType p_char);
static CharType char_lowercase(CharType p_char);
static char32_t char_uppercase(char32_t p_char);
static char32_t char_lowercase(char32_t p_char);
String to_upper() const;
String to_lower() const;
@ -287,7 +364,7 @@ public:
String get_extension() const;
String get_basename() const;
String plus_file(const String &p_file) const;
CharType ord_at(int p_idx) const;
char32_t ord_at(int p_idx) const;
void erase(int p_pos, int p_chars);
@ -296,8 +373,14 @@ public:
bool parse_utf8(const char *p_utf8, int p_len = -1); //return true on error
static String utf8(const char *p_utf8, int p_len = -1);
static uint32_t hash(const CharType *p_cstr, int p_len); /* hash the string */
static uint32_t hash(const CharType *p_cstr); /* hash the string */
Char16String utf16() const;
bool parse_utf16(const char16_t *p_utf16, int p_len = -1); //return true on error
static String utf16(const char16_t *p_utf16, int p_len = -1);
static uint32_t hash(const char32_t *p_cstr, int p_len); /* hash the string */
static uint32_t hash(const char32_t *p_cstr); /* hash the string */
static uint32_t hash(const wchar_t *p_cstr, int p_len); /* hash the string */
static uint32_t hash(const wchar_t *p_cstr); /* hash the string */
static uint32_t hash(const char *p_cstr, int p_len); /* hash the string */
static uint32_t hash(const char *p_cstr); /* hash the string */
uint32_t hash() const; /* hash the string */
@ -348,7 +431,7 @@ public:
/**
* The constructors must not depend on other overloads
*/
/* String(CharType p_char);*/
/* String(char32_t p_char);*/
_FORCE_INLINE_ String() {}
_FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); }
@ -358,14 +441,20 @@ public:
}
String(const char *p_str);
String(const CharType *p_str, int p_clip_to_len = -1);
String(const wchar_t *p_str);
String(const char32_t *p_str);
String(const char *p_str, int p_clip_to_len);
String(const wchar_t *p_str, int p_clip_to_len);
String(const char32_t *p_str, int p_clip_to_len);
String(const StrRange &p_range);
};
bool operator==(const char *p_chr, const String &p_str);
bool operator==(const wchar_t *p_chr, const String &p_str);
String operator+(const char *p_chr, const String &p_str);
String operator+(CharType p_chr, const String &p_str);
String operator+(const wchar_t *p_chr, const String &p_str);
String operator+(char32_t p_chr, const String &p_str);
String itos(int64_t p_val);
String uitos(uint64_t p_val);
@ -387,15 +476,18 @@ struct NaturalNoCaseComparator {
template <typename L, typename R>
_FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
while (true) {
if (*l_ptr == 0 && *r_ptr == 0) {
const char32_t l = *l_ptr;
const char32_t r = *r_ptr;
if (l == 0 && r == 0) {
return false;
} else if (*l_ptr == 0) {
} else if (l == 0) {
return true;
} else if (*r_ptr == 0) {
} else if (r == 0) {
return false;
} else if (*l_ptr < *r_ptr) {
} else if (l < r) {
return true;
} else if (*l_ptr > *r_ptr) {
} else if (l > r) {
return false;
}
@ -432,7 +524,7 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
String RTR(const String &p_text, const String &p_context = "");
String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context = "");
bool is_symbol(CharType c);
bool is_symbol(char32_t c);
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
#endif // USTRING_H

View file

@ -1558,7 +1558,7 @@ Variant::operator unsigned char() const {
}
}
Variant::operator CharType() const {
Variant::operator char32_t() const {
return operator unsigned int();
}
@ -2445,7 +2445,7 @@ Variant::Variant(const char *const p_cstring) {
memnew_placement(_data._mem, String((const char *)p_cstring));
}
Variant::Variant(const CharType *p_wstring) {
Variant::Variant(const char32_t *p_wstring) {
type = STRING;
memnew_placement(_data._mem, String(p_wstring));
}

View file

@ -246,7 +246,7 @@ public:
operator ObjectID() const;
operator CharType() const;
operator char32_t() const;
operator float() const;
operator double() const;
operator String() const;
@ -323,7 +323,7 @@ public:
Variant(const String &p_string);
Variant(const StringName &p_string);
Variant(const char *const p_cstring);
Variant(const CharType *p_wstring);
Variant(const char32_t *p_wstring);
Variant(const Vector2 &p_vector2);
Variant(const Vector2i &p_vector2i);
Variant(const Rect2 &p_rect2);

View file

@ -239,6 +239,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(String, casecmp_to);
VCALL_LOCALMEM1R(String, nocasecmp_to);
VCALL_LOCALMEM1R(String, naturalnocasecmp_to);
VCALL_LOCALMEM0R(String, length);
VCALL_LOCALMEM3R(String, count);
VCALL_LOCALMEM3R(String, countn);
@ -311,6 +312,8 @@ struct _VariantCall {
VCALL_LOCALMEM0R(String, to_int);
VCALL_LOCALMEM0R(String, to_float);
VCALL_LOCALMEM0R(String, hex_to_int);
VCALL_LOCALMEM2R(String, lpad);
VCALL_LOCALMEM2R(String, rpad);
VCALL_LOCALMEM1R(String, pad_decimals);
VCALL_LOCALMEM1R(String, pad_zeros);
VCALL_LOCALMEM1R(String, trim_prefix);
@ -350,6 +353,39 @@ struct _VariantCall {
r_ret = retval;
}
static void _call_String_to_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) {
String *s = reinterpret_cast<String *>(p_self._data._mem);
if (s->empty()) {
r_ret = PackedByteArray();
return;
}
Char16String charstr = s->utf16();
PackedByteArray retval;
size_t len = charstr.length() * 2;
retval.resize(len);
uint8_t *w = retval.ptrw();
copymem(w, (const void *)charstr.ptr(), len);
r_ret = retval;
}
static void _call_String_to_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) {
String *s = reinterpret_cast<String *>(p_self._data._mem);
if (s->empty()) {
r_ret = PackedByteArray();
return;
}
PackedByteArray retval;
size_t len = s->length() * 4;
retval.resize(len);
uint8_t *w = retval.ptrw();
copymem(w, (const void *)s->ptr(), len);
r_ret = retval;
}
VCALL_LOCALMEM1R(Vector2, distance_to);
VCALL_LOCALMEM1R(Vector2, distance_squared_to);
VCALL_LOCALMEM0R(Vector2, length);
@ -618,6 +654,26 @@ struct _VariantCall {
r_ret = s;
}
static void _call_PackedByteArray_get_string_from_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) {
PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem);
String s;
if (ba->size() > 0) {
const uint8_t *r = ba->ptr();
s.parse_utf16((const char16_t *)r, ba->size() / 2);
}
r_ret = s;
}
static void _call_PackedByteArray_get_string_from_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) {
PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem);
String s;
if (ba->size() > 0) {
const uint8_t *r = ba->ptr();
s = String((const char32_t *)r, ba->size() / 4);
}
r_ret = s;
}
static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) {
PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem);
PackedByteArray compressed;
@ -1789,6 +1845,7 @@ void register_variant_methods() {
/* STRING */
ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray());
ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray());
ADDFUNC1R(STRING, INT, String, naturalnocasecmp_to, STRING, "to", varray());
ADDFUNC0R(STRING, INT, String, length, varray());
ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray(-1));
@ -1867,6 +1924,8 @@ void register_variant_methods() {
ADDFUNC0R(STRING, INT, String, to_int, varray());
ADDFUNC0R(STRING, FLOAT, String, to_float, varray());
ADDFUNC0R(STRING, INT, String, hex_to_int, varray());
ADDFUNC2R(STRING, STRING, String, lpad, INT, "min_length", STRING, "character", varray(" "));
ADDFUNC2R(STRING, STRING, String, rpad, INT, "min_length", STRING, "character", varray(" "));
ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray());
ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray());
ADDFUNC1R(STRING, STRING, String, trim_prefix, STRING, "prefix", varray());
@ -1874,6 +1933,8 @@ void register_variant_methods() {
ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_ascii, varray());
ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf8, varray());
ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf16, varray());
ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf32, varray());
ADDFUNC0R(VECTOR2, FLOAT, Vector2, angle, varray());
ADDFUNC1R(VECTOR2, FLOAT, Vector2, angle_to, VECTOR2, "to", varray());
@ -2109,6 +2170,8 @@ void register_variant_methods() {
ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_ascii, varray());
ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf8, varray());
ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf16, varray());
ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf32, varray());
ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, hex_encode, varray());
ADDFUNC1R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, compress, INT, "compression_mode", varray(0));
ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));

View file

@ -4215,7 +4215,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
int split = csize / 2;
for (int i = 0; i < csize; i++) {
CharType chr = ' ';
char32_t chr = ' ';
if (i < split) {
if (i < sa.length()) {

View file

@ -35,7 +35,7 @@
#include "core/os/keyboard.h"
#include "core/string_buffer.h"
CharType VariantParser::StreamFile::get_char() {
char32_t VariantParser::StreamFile::get_char() {
return f->get_8();
}
@ -47,7 +47,7 @@ bool VariantParser::StreamFile::is_eof() const {
return f->eof_reached();
}
CharType VariantParser::StreamString::get_char() {
char32_t VariantParser::StreamString::get_char() {
if (pos > s.length()) {
return 0;
} else if (pos == s.length()) {
@ -94,7 +94,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
bool string_name = false;
while (true) {
CharType cchar;
char32_t cchar;
if (p_stream->saved) {
cchar = p_stream->saved;
p_stream->saved = 0;
@ -145,7 +145,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
}
case ';': {
while (true) {
CharType ch = p_stream->get_char();
char32_t ch = p_stream->get_char();
if (p_stream->is_eof()) {
r_token.type = TK_EOF;
return OK;
@ -173,7 +173,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
StringBuffer<> color_str;
color_str += '#';
while (true) {
CharType ch = p_stream->get_char();
char32_t ch = p_stream->get_char();
if (p_stream->is_eof()) {
r_token.type = TK_EOF;
return OK;
@ -204,7 +204,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
case '"': {
String str;
while (true) {
CharType ch = p_stream->get_char();
char32_t ch = p_stream->get_char();
if (ch == 0) {
r_err_str = "Unterminated String";
@ -214,13 +214,13 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
break;
} else if (ch == '\\') {
//escaped characters...
CharType next = p_stream->get_char();
char32_t next = p_stream->get_char();
if (next == 0) {
r_err_str = "Unterminated String";
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -241,7 +241,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
case 'u': {
//hex number
for (int j = 0; j < 4; j++) {
CharType c = p_stream->get_char();
char32_t c = p_stream->get_char();
if (c == 0) {
r_err_str = "Unterminated String";
r_token.type = TK_ERROR;
@ -252,7 +252,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType v;
char32_t v;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
@ -321,7 +321,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
cchar = p_stream->get_char();
}
CharType c = cchar;
char32_t c = cchar;
bool exp_sign = false;
bool exp_beg = false;
bool is_float = false;
@ -421,7 +421,7 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings,
String accum;
while (true) {
CharType c = p_stream->get_char();
char32_t c = p_stream->get_char();
if (p_stream->is_eof()) {
r_err_str = "Unexpected EOF while parsing old-style project.godot construct";
@ -1206,7 +1206,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin
r_tag.fields.clear();
while (true) {
CharType c = p_stream->get_char();
char32_t c = p_stream->get_char();
if (p_stream->is_eof()) {
r_err_str = "Unexpected EOF while parsing simple tag";
return ERR_PARSE_ERROR;
@ -1305,7 +1305,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
String what;
while (true) {
CharType c;
char32_t c;
if (p_stream->saved) {
c = p_stream->saved;
p_stream->saved = 0;
@ -1320,7 +1320,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
if (c == ';') { //comment
while (true) {
CharType ch = p_stream->get_char();
char32_t ch = p_stream->get_char();
if (p_stream->is_eof()) {
return ERR_FILE_EOF;
}

View file

@ -38,11 +38,11 @@
class VariantParser {
public:
struct Stream {
virtual CharType get_char() = 0;
virtual char32_t get_char() = 0;
virtual bool is_utf8() const = 0;
virtual bool is_eof() const = 0;
CharType saved = 0;
char32_t saved = 0;
Stream() {}
virtual ~Stream() {}
@ -51,7 +51,7 @@ public:
struct StreamFile : public Stream {
FileAccess *f = nullptr;
virtual CharType get_char();
virtual char32_t get_char();
virtual bool is_utf8() const;
virtual bool is_eof() const;
@ -62,7 +62,7 @@ public:
String s;
int pos = 0;
virtual CharType get_char();
virtual char32_t get_char();
virtual bool is_utf8() const;
virtual bool is_eof() const;

View file

@ -68,14 +68,28 @@
<return type="String">
</return>
<description>
Returns a copy of the array's contents as [String]. Fast alternative to [method get_string_from_utf8] if the content is ASCII-only. Unlike the UTF-8 function this function maps every byte to a character in the array. Multibyte sequences will not be interpreted correctly. For parsing user input always use [method get_string_from_utf8].
Converts ASCII/Latin-1 encoded array to [String]. Fast alternative to [method get_string_from_utf8] if the content is ASCII/Latin-1 only. Unlike the UTF-8 function this function maps every byte to a character in the array. Multibyte sequences will not be interpreted correctly. For parsing user input always use [method get_string_from_utf8].
</description>
</method>
<method name="get_string_from_utf16">
<return type="String">
</return>
<description>
Converts UTF-16 encoded array to [String]. If the BOM is missing, system endianness is assumed. Returns empty string if source array is not vaild UTF-16 string.
</description>
</method>
<method name="get_string_from_utf32">
<return type="String">
</return>
<description>
Converts UTF-32 encoded array to [String]. System endianness is assumed. Returns empty string if source array is not vaild UTF-32 string.
</description>
</method>
<method name="get_string_from_utf8">
<return type="String">
</return>
<description>
Returns a copy of the array's contents as [String]. Slower than [method get_string_from_ascii] but supports UTF-8 encoded data. Use this function if you are unsure about the source of the data. For user input this function should always be preferred.
Converts UTF-8 encoded array to [String]. Slower than [method get_string_from_ascii] but supports UTF-8 encoded data. Use this function if you are unsure about the source of the data. For user input this function should always be preferred. Returns empty string if source array is not vaild UTF-8 string.
</description>
</method>
<method name="has">

View file

@ -654,6 +654,17 @@
Returns the string's amount of characters.
</description>
</method>
<method name="lpad">
<return type="String">
</return>
<argument index="0" name="min_length" type="int">
</argument>
<argument index="1" name="character" type="String" default="&quot; &quot;">
</argument>
<description>
Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the left of the string.
</description>
</method>
<method name="lstrip">
<return type="String">
</return>
@ -695,6 +706,15 @@
Returns the MD5 hash of the string as a string.
</description>
</method>
<method name="naturalnocasecmp_to">
<return type="int">
</return>
<argument index="0" name="to" type="String">
</argument>
<description>
Performs a case-insensitive natural order comparison to another string. Returns [code]-1[/code] if less than, [code]+1[/code] if greater than, or [code]0[/code] if equal.
</description>
</method>
<method name="nocasecmp_to">
<return type="int">
</return>
@ -816,6 +836,17 @@
Returns the right side of the string from a given position.
</description>
</method>
<method name="rpad">
<return type="String">
</return>
<argument index="0" name="min_length" type="int">
</argument>
<argument index="1" name="character" type="String" default="&quot; &quot;">
</argument>
<description>
Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the right of the string.
</description>
</method>
<method name="rsplit">
<return type="PackedStringArray">
</return>
@ -953,7 +984,7 @@
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is a character array) to [PackedByteArray] (which is an array of bytes). The conversion is faster compared to [method to_utf8], as this method assumes that all the characters in the String are ASCII characters.
Converts the String (which is a character array) to ASCII/Latin-1 encoded [PackedByteArray] (which is an array of bytes). The conversion is faster compared to [method to_utf8], as this method assumes that all the characters in the String are ASCII/Latin-1 characters, unsupported characters are replaced with spaces.
</description>
</method>
<method name="to_float">
@ -984,11 +1015,25 @@
Returns the string converted to uppercase.
</description>
</method>
<method name="to_utf16">
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is an array of characters) to UTF-16 encoded [PackedByteArray] (which is an array of bytes).
</description>
</method>
<method name="to_utf32">
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is an array of characters) to UTF-32 encoded [PackedByteArray] (which is an array of bytes).
</description>
</method>
<method name="to_utf8">
<return type="PackedByteArray">
</return>
<description>
Converts the String (which is an array of characters) to [PackedByteArray] (which is an array of bytes). The conversion is a bit slower than [method to_ascii], but supports all UTF-8 characters. Therefore, you should prefer this function over [method to_ascii].
Converts the String (which is an array of characters) to UTF-8 encode [PackedByteArray] (which is an array of bytes). The conversion is a bit slower than [method to_ascii], but supports all UTF-8 characters. Therefore, you should prefer this function over [method to_ascii].
</description>
</method>
<method name="trim_prefix">

View file

@ -78,7 +78,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
path_src = p_path;
path = fix_path(p_path);
//printf("opening %ls, %i\n", path.c_str(), Memory::get_static_mem_usage());
//printf("opening %s, %i\n", path.utf8().get_data(), Memory::get_static_mem_usage());
ERR_FAIL_COND_V_MSG(f, ERR_ALREADY_IN_USE, "File is already in use.");
const char *mode_string;

View file

@ -3650,7 +3650,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
//print_line("DEBUG: SAMPLER: texel buffer");
} else {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported buffer type.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported buffer type.";
}
return false;
}
@ -3673,7 +3673,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
} else {
//print_line("DEBUG: sampler unknown");
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported sampler type.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported sampler type.";
}
return false;
}
@ -3698,7 +3698,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
if (reflection.getType()->getQualifier().layoutPushConstant) {
uint32_t len = reflection.size;
if (push_constant.push_constant_size != 0 && push_constant.push_constant_size != len) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' push constants for different stages should all be the same size.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' push constants for different stages should all be the same size.";
return false;
}
push_constant.push_constant_size = len;
@ -3714,7 +3714,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
//print_line("DEBUG: Storage buffer");
} else {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported block type: (" + itos(reflection.getType()->getQualifier().storage) + ").";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported block type: (" + itos(reflection.getType()->getQualifier().storage) + ").";
}
return false;
}
@ -3743,7 +3743,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
}
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' unsupported uniform type.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' unsupported uniform type.";
}
return false;
}
@ -3751,7 +3751,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
if (!reflection.getType()->getQualifier().hasBinding()) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' lacks a binding number.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' lacks a binding number.";
}
return false;
}
@ -3760,14 +3760,14 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
if (set >= MAX_UNIFORM_SETS) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").";
}
return false;
}
if (set >= limits.maxBoundDescriptorSets) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").";
}
return false;
}
@ -3781,7 +3781,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
//already exists, verify that it's the same type
if (bindings[set][i].descriptorType != layout_binding.descriptorType) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type.";
}
return false;
}
@ -3789,7 +3789,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
//also, verify that it's the same size
if (bindings[set][i].descriptorCount != layout_binding.descriptorCount || uniform_infos[set][i].length != info.length) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size.";
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size.";
}
return false;
}

View file

@ -65,7 +65,7 @@ Error DirAccessWindows::list_dir_begin() {
_cishidden = false;
list_dir_end();
p->h = FindFirstFileExW((current_dir + "\\*").c_str(), FindExInfoStandard, &p->fu, FindExSearchNameMatch, nullptr, 0);
p->h = FindFirstFileExW((LPCWSTR)(String(current_dir + "\\*").utf16().get_data()), FindExInfoStandard, &p->fu, FindExSearchNameMatch, nullptr, 0);
if (p->h == INVALID_HANDLE_VALUE) {
return ERR_CANT_OPEN;
@ -75,13 +75,14 @@ Error DirAccessWindows::list_dir_begin() {
}
String DirAccessWindows::get_next() {
if (p->h == INVALID_HANDLE_VALUE)
if (p->h == INVALID_HANDLE_VALUE) {
return "";
}
_cisdir = (p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
_cishidden = (p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
String name = p->fu.cFileName;
String name = String::utf16((const char16_t *)(p->fu.cFileName));
if (FindNextFileW(p->h, &p->fu) == 0) {
FindClose(p->h);
@ -111,8 +112,9 @@ int DirAccessWindows::get_drive_count() {
}
String DirAccessWindows::get_drive(int p_drive) {
if (p_drive < 0 || p_drive >= drive_count)
if (p_drive < 0 || p_drive >= drive_count) {
return "";
}
return String::chr(drives[p_drive]) + ":";
}
@ -122,18 +124,17 @@ Error DirAccessWindows::change_dir(String p_dir) {
p_dir = fix_path(p_dir);
wchar_t real_current_dir_name[2048];
WCHAR real_current_dir_name[2048];
GetCurrentDirectoryW(2048, real_current_dir_name);
String prev_dir = real_current_dir_name;
String prev_dir = String::utf16((const char16_t *)real_current_dir_name);
SetCurrentDirectoryW(current_dir.c_str());
bool worked = (SetCurrentDirectoryW(p_dir.c_str()) != 0);
SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data()));
bool worked = (SetCurrentDirectoryW((LPCWSTR)(p_dir.utf16().get_data())) != 0);
String base = _get_root_path();
if (base != "") {
GetCurrentDirectoryW(2048, real_current_dir_name);
String new_dir;
new_dir = String(real_current_dir_name).replace("\\", "/");
String new_dir = String::utf16((const char16_t *)real_current_dir_name).replace("\\", "/");
if (!new_dir.begins_with(base)) {
worked = false;
}
@ -141,13 +142,11 @@ Error DirAccessWindows::change_dir(String p_dir) {
if (worked) {
GetCurrentDirectoryW(2048, real_current_dir_name);
current_dir = real_current_dir_name; // TODO, utf8 parser
current_dir = String::utf16((const char16_t *)real_current_dir_name);
current_dir = current_dir.replace("\\", "/");
}
} //else {
SetCurrentDirectoryW(prev_dir.c_str());
//}
SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data()));
return worked ? OK : ERR_INVALID_PARAMETER;
}
@ -156,8 +155,9 @@ Error DirAccessWindows::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
p_dir = fix_path(p_dir);
if (p_dir.is_rel_path())
if (p_dir.is_rel_path()) {
p_dir = current_dir.plus_file(p_dir);
}
p_dir = p_dir.replace("/", "\\");
@ -167,16 +167,16 @@ Error DirAccessWindows::make_dir(String p_dir) {
p_dir = "\\\\?\\" + p_dir; //done according to
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx
success = CreateDirectoryW(p_dir.c_str(), nullptr);
success = CreateDirectoryW((LPCWSTR)(p_dir.utf16().get_data()), nullptr);
err = GetLastError();
if (success) {
return OK;
};
}
if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) {
return ERR_ALREADY_EXISTS;
};
}
return ERR_CANT_CREATE;
}
@ -185,12 +185,11 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) {
String base = _get_root_path();
if (base != "") {
String bd = current_dir.replace("\\", "/").replace_first(base, "");
if (bd.begins_with("/"))
if (bd.begins_with("/")) {
return _get_root_string() + bd.substr(1, bd.length());
else
} else {
return _get_root_string() + bd;
} else {
}
}
if (p_include_drive) {
@ -209,20 +208,18 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) {
bool DirAccessWindows::file_exists(String p_file) {
GLOBAL_LOCK_FUNCTION
if (!p_file.is_abs_path())
if (!p_file.is_abs_path()) {
p_file = get_current_dir().plus_file(p_file);
}
p_file = fix_path(p_file);
//p_file.replace("/","\\");
//WIN32_FILE_ATTRIBUTE_DATA fileInfo;
DWORD fileAttr;
fileAttr = GetFileAttributesW(p_file.c_str());
if (INVALID_FILE_ATTRIBUTES == fileAttr)
fileAttr = GetFileAttributesW((LPCWSTR)(p_file.utf16().get_data()));
if (INVALID_FILE_ATTRIBUTES == fileAttr) {
return false;
}
return !(fileAttr & FILE_ATTRIBUTE_DIRECTORY);
}
@ -230,31 +227,30 @@ bool DirAccessWindows::file_exists(String p_file) {
bool DirAccessWindows::dir_exists(String p_dir) {
GLOBAL_LOCK_FUNCTION
if (p_dir.is_rel_path())
if (p_dir.is_rel_path()) {
p_dir = get_current_dir().plus_file(p_dir);
}
p_dir = fix_path(p_dir);
//p_dir.replace("/","\\");
//WIN32_FILE_ATTRIBUTE_DATA fileInfo;
DWORD fileAttr;
fileAttr = GetFileAttributesW(p_dir.c_str());
if (INVALID_FILE_ATTRIBUTES == fileAttr)
fileAttr = GetFileAttributesW((LPCWSTR)(p_dir.utf16().get_data()));
if (INVALID_FILE_ATTRIBUTES == fileAttr) {
return false;
}
return (fileAttr & FILE_ATTRIBUTE_DIRECTORY);
}
Error DirAccessWindows::rename(String p_path, String p_new_path) {
if (p_path.is_rel_path())
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
p_path = fix_path(p_path);
if (p_new_path.is_rel_path())
if (p_new_path.is_rel_path()) {
p_new_path = get_current_dir().plus_file(p_new_path);
}
p_new_path = fix_path(p_new_path);
@ -262,16 +258,16 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) {
if (p_path.to_lower() == p_new_path.to_lower()) {
WCHAR tmpfile[MAX_PATH];
if (!GetTempFileNameW(fix_path(get_current_dir()).c_str(), nullptr, 0, tmpfile)) {
if (!GetTempFileNameW((LPCWSTR)(fix_path(get_current_dir()).utf16().get_data()), nullptr, 0, tmpfile)) {
return FAILED;
}
if (!::ReplaceFileW(tmpfile, p_path.c_str(), nullptr, 0, nullptr, nullptr)) {
if (!::ReplaceFileW(tmpfile, (LPCWSTR)(p_path.utf16().get_data()), nullptr, 0, nullptr, nullptr)) {
DeleteFileW(tmpfile);
return FAILED;
}
return ::_wrename(tmpfile, p_new_path.c_str()) == 0 ? OK : FAILED;
return ::_wrename(tmpfile, (LPCWSTR)(p_new_path.utf16().get_data())) == 0 ? OK : FAILED;
} else {
if (file_exists(p_new_path)) {
@ -280,60 +276,60 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) {
}
}
return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED;
return ::_wrename((LPCWSTR)(p_path.utf16().get_data()), (LPCWSTR)(p_new_path.utf16().get_data())) == 0 ? OK : FAILED;
}
}
Error DirAccessWindows::remove(String p_path) {
if (p_path.is_rel_path())
if (p_path.is_rel_path()) {
p_path = get_current_dir().plus_file(p_path);
}
p_path = fix_path(p_path);
DWORD fileAttr;
fileAttr = GetFileAttributesW(p_path.c_str());
if (INVALID_FILE_ATTRIBUTES == fileAttr)
fileAttr = GetFileAttributesW((LPCWSTR)(p_path.utf16().get_data()));
if (INVALID_FILE_ATTRIBUTES == fileAttr) {
return FAILED;
if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY))
return ::_wrmdir(p_path.c_str()) == 0 ? OK : FAILED;
else
return ::_wunlink(p_path.c_str()) == 0 ? OK : FAILED;
}
if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY)) {
return ::_wrmdir((LPCWSTR)(p_path.utf16().get_data())) == 0 ? OK : FAILED;
} else {
return ::_wunlink((LPCWSTR)(p_path.utf16().get_data())) == 0 ? OK : FAILED;
}
}
/*
FileType DirAccessWindows::get_file_type(const String& p_file) const {
WCHAR real_current_dir_name[2048];
GetCurrentDirectoryW(2048, real_current_dir_name);
String prev_dir = Strong::utf16((const char16_t *)real_current_dir_name);
wchar_t real_current_dir_name[2048];
GetCurrentDirectoryW(2048,real_current_dir_name);
String prev_dir=real_current_dir_name;
bool worked SetCurrentDirectoryW(current_dir.c_str());
bool worked = SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data()));
DWORD attr;
if (worked) {
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
attr = GetFileAttributesExW(p_file.c_str(), GetFileExInfoStandard, &fileInfo);
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
attr = GetFileAttributesExW((LPCWSTR)(p_file.utf16().get_data()), GetFileExInfoStandard, &fileInfo);
}
SetCurrentDirectoryW(prev_dir.c_str());
SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data()));
if (!worked)
if (!worked) {
return FILE_TYPE_NONE;
}
return (attr&FILE_ATTRIBUTE_DIRECTORY)?FILE_TYPE_
return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FILE_TYPE_
}
*/
size_t DirAccessWindows::get_space_left() {
uint64_t bytes = 0;
if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr))
if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) {
return 0;
}
//this is either 0 or a value in bytes.
return (size_t)bytes;
@ -352,7 +348,7 @@ String DirAccessWindows::get_filesystem_type() const {
DWORD dwMaxFileNameLength = 0;
DWORD dwFileSystemFlags = 0;
if (::GetVolumeInformationW(unit.c_str(),
if (::GetVolumeInformationW((LPCWSTR)(unit.utf16().get_data()),
szVolumeName,
sizeof(szVolumeName),
&dwSerialNumber,
@ -360,7 +356,7 @@ String DirAccessWindows::get_filesystem_type() const {
&dwFileSystemFlags,
szFileSystemName,
sizeof(szFileSystemName)) == TRUE) {
return String(szFileSystemName);
return String::utf16((const char16_t *)szFileSystemName);
}
ERR_FAIL_V("");

View file

@ -59,29 +59,32 @@ void FileAccessWindows::check_errors() const {
Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
path_src = p_path;
path = fix_path(p_path);
if (f)
if (f) {
close();
}
const wchar_t *mode_string;
const WCHAR *mode_string;
if (p_mode_flags == READ)
if (p_mode_flags == READ) {
mode_string = L"rb";
else if (p_mode_flags == WRITE)
} else if (p_mode_flags == WRITE) {
mode_string = L"wb";
else if (p_mode_flags == READ_WRITE)
} else if (p_mode_flags == READ_WRITE) {
mode_string = L"rb+";
else if (p_mode_flags == WRITE_READ)
} else if (p_mode_flags == WRITE_READ) {
mode_string = L"wb+";
else
} else {
return ERR_INVALID_PARAMETER;
}
/* pretty much every implementation that uses fopen as primary
backend supports utf8 encoding */
struct _stat st;
if (_wstat(path.c_str(), &st) == 0) {
if (!S_ISREG(st.st_mode))
if (_wstat((LPCWSTR)(path.utf16().get_data()), &st) == 0) {
if (!S_ISREG(st.st_mode)) {
return ERR_FILE_CANT_OPEN;
}
};
#ifdef TOOLS_ENABLED
@ -91,9 +94,9 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
// platforms).
if (p_mode_flags == READ) {
WIN32_FIND_DATAW d;
HANDLE f = FindFirstFileW(path.c_str(), &d);
HANDLE f = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d);
if (f != INVALID_HANDLE_VALUE) {
String fname = d.cFileName;
String fname = String::utf16((const char16_t *)(d.cFileName));
if (fname != String()) {
String base_file = path.get_file();
if (base_file != fname && base_file.findn(fname) == 0) {
@ -110,7 +113,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
path = path + ".tmp";
}
errno_t errcode = _wfopen_s(&f, path.c_str(), mode_string);
errno_t errcode = _wfopen_s(&f, (LPCWSTR)(path.utf16().get_data()), mode_string);
if (f == nullptr) {
switch (errcode) {
@ -130,8 +133,9 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
}
void FileAccessWindows::close() {
if (!f)
if (!f) {
return;
}
fclose(f);
f = nullptr;
@ -148,16 +152,16 @@ void FileAccessWindows::close() {
// UWP has no PathFileExists, so we check attributes instead
DWORD fileAttr;
fileAttr = GetFileAttributesW(save_path.c_str());
fileAttr = GetFileAttributesW((LPCWSTR)(save_path.utf16().get_data()));
if (INVALID_FILE_ATTRIBUTES == fileAttr) {
#else
if (!PathFileExistsW(save_path.c_str())) {
if (!PathFileExistsW((LPCWSTR)(save_path.utf16().get_data()))) {
#endif
//creating new file
rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0;
rename_error = _wrename((LPCWSTR)((save_path + ".tmp").utf16().get_data()), (LPCWSTR)(save_path.utf16().get_data())) != 0;
} else {
//atomic replace for existing file
rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), nullptr, 2 | 4, nullptr, nullptr);
rename_error = !ReplaceFileW((LPCWSTR)(save_path.utf16().get_data()), (LPCWSTR)((save_path + ".tmp").utf16().get_data()), nullptr, 2 | 4, nullptr, nullptr);
}
if (rename_error) {
attempts--;
@ -192,15 +196,17 @@ bool FileAccessWindows::is_open() const {
void FileAccessWindows::seek(size_t p_position) {
ERR_FAIL_COND(!f);
last_error = OK;
if (fseek(f, p_position, SEEK_SET))
if (fseek(f, p_position, SEEK_SET)) {
check_errors();
}
prev_op = 0;
}
void FileAccessWindows::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
if (fseek(f, p_position, SEEK_END))
if (fseek(f, p_position, SEEK_END)) {
check_errors();
}
prev_op = 0;
}
@ -209,7 +215,7 @@ size_t FileAccessWindows::get_position() const {
aux_position = ftell(f);
if (!aux_position) {
check_errors();
};
}
return aux_position;
}
@ -241,7 +247,7 @@ uint8_t FileAccessWindows::get_8() const {
if (fread(&b, 1, 1, f) == 0) {
check_errors();
b = '\0';
};
}
return b;
}
@ -266,8 +272,9 @@ Error FileAccessWindows::get_error() const {
void FileAccessWindows::flush() {
ERR_FAIL_COND(!f);
fflush(f);
if (prev_op == WRITE)
if (prev_op == WRITE) {
prev_op = 0;
}
}
void FileAccessWindows::store_8(uint8_t p_dest) {
@ -298,9 +305,9 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) {
bool FileAccessWindows::file_exists(const String &p_name) {
FILE *g;
//printf("opening file %s\n", p_fname.c_str());
//printf("opening file %s\n", p_fname.utf8().get_data());
String filename = fix_path(p_name);
_wfopen_s(&g, filename.c_str(), L"rb");
_wfopen_s(&g, (LPCWSTR)(filename.utf16().get_data()), L"rb");
if (g == nullptr) {
return false;
} else {
@ -315,7 +322,7 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
file = file.substr(0, file.length() - 1);
struct _stat st;
int rv = _wstat(file.c_str(), &st);
int rv = _wstat((LPCWSTR)(file.utf16().get_data()), &st);
if (rv == 0) {
return st.st_mtime;

View file

@ -714,7 +714,7 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
const String &signalname = signal;
String midname = selectedNode->get_name();
for (int i = 0; i < midname.length(); i++) { //TODO: Regex filter may be cleaner.
CharType c = midname[i];
char32_t c = midname[i];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) {
if (c == ' ') {
// Replace spaces with underlines.

View file

@ -244,7 +244,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
class_desc->push_cell();
class_desc->push_align(RichTextLabel::ALIGN_RIGHT);
} else {
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
}
@ -761,7 +761,7 @@ void EditorHelp::_update_doc() {
signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
class_desc->push_font(doc_code_font); // monofont
class_desc->push_color(headline_color);
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
_add_text(cd.signals[i].name);
class_desc->pop();
@ -876,7 +876,7 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_code_font);
class_desc->push_color(headline_color);
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
_add_text(enum_list[i].name);
class_desc->pop();
@ -890,7 +890,7 @@ void EditorHelp::_update_doc() {
if (enum_list[i].description != "") {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 };
static const char32_t dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 };
class_desc->add_text(String(dash));
_add_text(DTR(enum_list[i].description));
class_desc->pop();
@ -937,12 +937,12 @@ void EditorHelp::_update_doc() {
Vector<float> color = stripped.split_floats(",");
if (color.size() >= 3) {
class_desc->push_color(Color(color[0], color[1], color[2]));
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
class_desc->pop();
}
} else {
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
}
@ -960,7 +960,7 @@ void EditorHelp::_update_doc() {
if (constants[i].description != "") {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 };
static const char32_t dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 };
class_desc->add_text(String(dash));
_add_text(DTR(constants[i].description));
class_desc->pop();
@ -1002,7 +1002,7 @@ void EditorHelp::_update_doc() {
class_desc->push_cell();
class_desc->push_font(doc_code_font);
static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 };
class_desc->add_text(String(prefix));
_add_type(cd.properties[i].type, cd.properties[i].enumeration);

View file

@ -192,9 +192,9 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L
String exec = OS::get_singleton()->get_executable_path();
printf("Running: %ls", exec.c_str());
printf("Running: %s", exec.utf8().get_data());
for (List<String>::Element *E = args.front(); E; E = E->next()) {
printf(" %ls", E->get().c_str());
printf(" %s", E->get().utf8().get_data());
};
printf("\n");

View file

@ -54,7 +54,7 @@ inline void pop_back(T &container) {
}
// TODO Copied from TextEdit private, would be nice to extract it in a single place
static bool is_text_char(CharType c) {
static bool is_text_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
@ -854,7 +854,7 @@ public:
String get_line(FileAccess *f) {
_line_buffer.clear();
CharType c = f->get_8();
char32_t c = f->get_8();
while (!f->eof_reached()) {
if (c == '\n') {

View file

@ -100,7 +100,7 @@ void InputMapEditor::_notification(int p_what) {
}
static bool _validate_action_name(const String &p_name) {
const CharType *cstr = p_name.c_str();
const char32_t *cstr = p_name.get_data();
for (int i = 0; cstr[i]; i++) {
if (cstr[i] == '/' || cstr[i] == ':' || cstr[i] == '"' ||
cstr[i] == '=' || cstr[i] == '\\' || cstr[i] < 32) {

View file

@ -6256,7 +6256,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}

View file

@ -466,7 +466,7 @@ EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
///////////////////////////////////////////////////////////////////////////
static bool _is_text_char(CharType c) {
static bool _is_text_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
@ -525,7 +525,7 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size
bool prev_is_text = false;
bool in_keyword = false;
for (int i = 0; i < code.length(); i++) {
CharType c = code[i];
char32_t c = code[i];
if (c > 32) {
if (col < thumbnail_size) {
Color color = text_color;

View file

@ -3729,7 +3729,7 @@ void Node3DEditorViewport::_perform_drop_data() {
files_str += error_files[i].get_file().get_basename() + ",";
}
files_str = files_str.substr(0, files_str.length() - 1);
accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data()));
accept->popup_centered();
}
}

File diff suppressed because it is too large Load diff

View file

@ -3731,6 +3731,27 @@
["godot_char_string *", "p_cs"]
]
},
{
"name": "godot_char16_string_length",
"return_type": "godot_int",
"arguments": [
["const godot_char16_string *", "p_cs"]
]
},
{
"name": "godot_char16_string_get_data",
"return_type": "const char16_t *",
"arguments": [
["const godot_char16_string *", "p_cs"]
]
},
{
"name": "godot_char16_string_destroy",
"return_type": "void",
"arguments": [
["godot_char16_string *", "p_cs"]
]
},
{
"name": "godot_string_new",
"return_type": "void",
@ -3747,7 +3768,83 @@
]
},
{
"name": "godot_string_new_with_wide_string",
"name": "godot_string_new_with_latin1_chars",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char *", "p_contents"]
]
},
{
"name": "godot_string_new_with_utf8_chars",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char *", "p_contents"]
]
},
{
"name": "godot_string_new_with_utf16_chars",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char16_t *", "p_contents"]
]
},
{
"name": "godot_string_new_with_utf32_chars",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char32_t *", "p_contents"]
]
},
{
"name": "godot_string_new_with_wide_chars",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const wchar_t *", "p_contents"]
]
},
{
"name": "godot_string_new_with_latin1_chars_and_len",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char *", "p_contents"],
["const int", "p_size"]
]
},
{
"name": "godot_string_new_with_utf8_chars_and_len",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char *", "p_contents"],
["const int", "p_size"]
]
},
{
"name": "godot_string_new_with_utf16_chars_and_len",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char16_t *", "p_contents"],
["const int", "p_size"]
]
},
{
"name": "godot_string_new_with_utf32_chars_and_len",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
["const char32_t *", "p_contents"],
["const int", "p_size"]
]
},
{
"name": "godot_string_new_with_wide_chars_and_len",
"return_type": "void",
"arguments": [
["godot_string *", "r_dest"],
@ -3757,7 +3854,7 @@
},
{
"name": "godot_string_operator_index",
"return_type": "const wchar_t *",
"return_type": "const godot_char_type *",
"arguments": [
["godot_string *", "p_self"],
["const godot_int", "p_idx"]
@ -3765,15 +3862,15 @@
},
{
"name": "godot_string_operator_index_const",
"return_type": "wchar_t",
"return_type": "godot_char_type",
"arguments": [
["const godot_string *", "p_self"],
["const godot_int", "p_idx"]
]
},
{
"name": "godot_string_wide_str",
"return_type": "const wchar_t *",
"name": "godot_string_get_data",
"return_type": "const godot_char_type *",
"arguments": [
["const godot_string *", "p_self"]
]
@ -3807,7 +3904,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"],
["godot_int", "p_to"]
]
@ -3817,7 +3914,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"],
["godot_int", "p_to"]
]
@ -3878,7 +3975,7 @@
},
{
"name": "godot_string_bigrams",
"return_type": "godot_array",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"]
]
@ -3887,7 +3984,7 @@
"name": "godot_string_chr",
"return_type": "godot_string",
"arguments": [
["wchar_t", "p_character"]
["godot_char_type", "p_character"]
]
},
{
@ -3898,12 +3995,20 @@
["const godot_string *", "p_string"]
]
},
{
"name": "godot_string_ends_with_char_array",
"return_type": "godot_bool",
"arguments": [
["const godot_string *", "p_self"],
["const char *", "p_char_array"]
]
},
{
"name": "godot_string_find",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"]
["const godot_string *", "p_what"]
]
},
{
@ -3911,7 +4016,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"]
]
},
@ -3920,7 +4025,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_keys"]
["const godot_packed_string_array *", "p_keys"]
]
},
{
@ -3928,7 +4033,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_keys"],
["const godot_packed_string_array *", "p_keys"],
["godot_int", "p_from"]
]
},
@ -3937,7 +4042,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_keys"],
["const godot_packed_string_array *", "p_keys"],
["godot_int", "p_from"],
["godot_int *", "r_key"]
]
@ -3947,7 +4052,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"]
["const godot_string *", "p_what"]
]
},
{
@ -3955,7 +4060,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"]
]
},
@ -3984,27 +4089,13 @@
["godot_int", "p_len"]
]
},
{
"name": "godot_string_hex_to_int",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_hex_to_int_without_prefix",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_insert",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_int", "p_at_pos"],
["godot_string", "p_string"]
["const godot_string *", "p_string"]
]
},
{
@ -4137,8 +4228,8 @@
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_key"],
["godot_string", "p_with"]
["const godot_string *", "p_key"],
["const godot_string *", "p_with"]
]
},
{
@ -4146,8 +4237,8 @@
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_key"],
["godot_string", "p_with"]
["const godot_string *", "p_key"],
["const godot_string *", "p_with"]
]
},
{
@ -4155,8 +4246,8 @@
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_key"],
["godot_string", "p_with"]
["const godot_string *", "p_key"],
["const godot_string *", "p_with"]
]
},
{
@ -4164,7 +4255,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"]
["const godot_string *", "p_what"]
]
},
{
@ -4172,7 +4263,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"]
["const godot_string *", "p_what"]
]
},
{
@ -4180,7 +4271,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"]
]
},
@ -4189,7 +4280,7 @@
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_what"],
["const godot_string *", "p_what"],
["godot_int", "p_from"]
]
},
@ -4237,15 +4328,15 @@
]
},
{
"name": "godot_string_to_float",
"return_type": "double",
"name": "godot_string_to_int",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_to_int",
"return_type": "godot_int",
"name": "godot_string_to_float",
"return_type": "double",
"arguments": [
["const godot_string *", "p_self"]
]
@ -4278,6 +4369,14 @@
["const char *", "p_what"]
]
},
{
"name": "godot_string_wchar_to_float",
"return_type": "double",
"arguments": [
["const wchar_t *", "p_str"],
["const wchar_t **", "r_end"]
]
},
{
"name": "godot_string_char_to_int",
"return_type": "godot_int",
@ -4287,7 +4386,7 @@
},
{
"name": "godot_string_wchar_to_int",
"return_type": "int64_t",
"return_type": "godot_int",
"arguments": [
["const wchar_t *", "p_str"]
]
@ -4301,48 +4400,33 @@
]
},
{
"name": "godot_string_char_to_int64_with_len",
"return_type": "int64_t",
"name": "godot_string_wchar_to_int_with_len",
"return_type": "godot_int",
"arguments": [
["const wchar_t *", "p_str"],
["int", "p_len"]
]
},
{
"name": "godot_string_hex_to_int64",
"return_type": "int64_t",
"name": "godot_string_hex_to_int",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_hex_to_int64_with_prefix",
"return_type": "int64_t",
"name": "godot_string_hex_to_int_with_prefix",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_to_int64",
"return_type": "int64_t",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_unicode_char_to_float",
"return_type": "double",
"arguments": [
["const wchar_t *", "p_str"],
["const wchar_t **", "r_end"]
]
},
{
"name": "godot_string_get_slice_count",
"return_type": "godot_int",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_splitter"]
["const godot_string *", "p_splitter"]
]
},
{
@ -4350,7 +4434,7 @@
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_string", "p_splitter"],
["const godot_string *", "p_splitter"],
["godot_int", "p_slice"]
]
},
@ -4359,13 +4443,13 @@
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["wchar_t", "p_splitter"],
["godot_char_type", "p_splitter"],
["godot_int", "p_slice"]
]
},
{
"name": "godot_string_split",
"return_type": "godot_array",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
@ -4373,23 +4457,59 @@
},
{
"name": "godot_string_split_allow_empty",
"return_type": "godot_array",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
]
},
{
"name": "godot_string_split_with_maxsplit",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"],
["const godot_bool", "p_allow_empty"],
["const godot_int", "p_maxsplit"]
]
},
{
"name": "godot_string_rsplit",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
]
},
{
"name": "godot_string_rsplit_allow_empty",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
]
},
{
"name": "godot_string_rsplit_with_maxsplit",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"],
["const godot_bool", "p_allow_empty"],
["const godot_int", "p_maxsplit"]
]
},
{
"name": "godot_string_split_floats",
"return_type": "godot_array",
"return_type": "godot_packed_float32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
]
},
{
"name": "godot_string_split_floats_allows_empty",
"return_type": "godot_array",
"name": "godot_string_split_floats_allow_empty",
"return_type": "godot_packed_float32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
@ -4397,31 +4517,31 @@
},
{
"name": "godot_string_split_floats_mk",
"return_type": "godot_array",
"return_type": "godot_packed_float32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_splitters"]
["const godot_packed_string_array *", "p_splitters"]
]
},
{
"name": "godot_string_split_floats_mk_allows_empty",
"return_type": "godot_array",
"name": "godot_string_split_floats_mk_allow_empty",
"return_type": "godot_packed_float32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_splitters"]
["const godot_packed_string_array *", "p_splitters"]
]
},
{
"name": "godot_string_split_ints",
"return_type": "godot_array",
"return_type": "godot_packed_int32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
]
},
{
"name": "godot_string_split_ints_allows_empty",
"return_type": "godot_array",
"name": "godot_string_split_ints_allow_empty",
"return_type": "godot_packed_int32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_splitter"]
@ -4429,27 +4549,35 @@
},
{
"name": "godot_string_split_ints_mk",
"return_type": "godot_array",
"return_type": "godot_packed_int32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_splitters"]
["const godot_packed_string_array *", "p_splitters"]
]
},
{
"name": "godot_string_split_ints_mk_allows_empty",
"return_type": "godot_array",
"name": "godot_string_split_ints_mk_allow_empty",
"return_type": "godot_packed_int32_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_array *", "p_splitters"]
["const godot_packed_string_array *", "p_splitters"]
]
},
{
"name": "godot_string_split_spaces",
"return_type": "godot_array",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_lstrip",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_chars"]
]
},
{
"name": "godot_string_rstrip",
"return_type": "godot_string",
@ -4458,16 +4586,6 @@
["const godot_string *", "p_chars"]
]
},
{
"name": "godot_string_rsplit",
"return_type": "godot_packed_string_array",
"arguments": [
["const godot_string *", "p_self"],
["const godot_string *", "p_divisor"],
["const godot_bool", "p_allow_empty"],
["const godot_int", "p_maxsplit"]
]
},
{
"name": "godot_string_trim_prefix",
"return_type": "godot_string",
@ -4486,16 +4604,16 @@
},
{
"name": "godot_string_char_lowercase",
"return_type": "wchar_t",
"return_type": "godot_char_type",
"arguments": [
["wchar_t", "p_char"]
["godot_char_type", "p_char"]
]
},
{
"name": "godot_string_char_uppercase",
"return_type": "wchar_t",
"return_type": "godot_char_type",
"arguments": [
["wchar_t", "p_char"]
["godot_char_type", "p_char"]
]
},
{
@ -4536,7 +4654,7 @@
},
{
"name": "godot_string_ord_at",
"return_type": "wchar_t",
"return_type": "godot_char_type",
"arguments": [
["const godot_string *", "p_self"],
["godot_int", "p_idx"]
@ -4558,6 +4676,14 @@
["godot_int", "p_pos"]
]
},
{
"name": "godot_string_repeat",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_int", "p_count"]
]
},
{
"name": "godot_string_strip_edges",
"return_type": "godot_string",
@ -4591,7 +4717,7 @@
]
},
{
"name": "godot_string_ascii_extended",
"name": "godot_string_latin1",
"return_type": "godot_char_string",
"arguments": [
["const godot_string *", "p_self"]
@ -4622,17 +4748,26 @@
]
},
{
"name": "godot_string_chars_to_utf8",
"return_type": "godot_string",
"name": "godot_string_utf16",
"return_type": "godot_char16_string",
"arguments": [
["const char *", "p_utf8"]
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_chars_to_utf8_with_len",
"return_type": "godot_string",
"name": "godot_string_parse_utf16",
"return_type": "godot_bool",
"arguments": [
["const char *", "p_utf8"],
["godot_string *", "p_self"],
["const char16_t *", "p_utf16"]
]
},
{
"name": "godot_string_parse_utf16_with_len",
"return_type": "godot_bool",
"arguments": [
["godot_string *", "p_self"],
["const char16_t *", "p_utf16"],
["godot_int", "p_len"]
]
},
@ -4666,14 +4801,14 @@
]
},
{
"name": "godot_string_hash_utf8_chars",
"name": "godot_string_hash_wide_chars",
"return_type": "uint32_t",
"arguments": [
["const wchar_t *", "p_str"]
]
},
{
"name": "godot_string_hash_utf8_chars_with_len",
"name": "godot_string_hash_wide_chars_with_len",
"return_type": "uint32_t",
"arguments": [
["const wchar_t *", "p_str"],
@ -4694,6 +4829,20 @@
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_sha1_buffer",
"return_type": "godot_packed_byte_array",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_sha1_text",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_sha256_buffer",
"return_type": "godot_packed_byte_array",
@ -4822,14 +4971,6 @@
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_word_wrap",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["godot_int", "p_chars_per_line"]
]
},
{
"name": "godot_string_xml_escape",
"return_type": "godot_string",
@ -4865,6 +5006,21 @@
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_join",
"return_type": "godot_string",
"arguments": [
["const godot_string *", "p_self"],
["const godot_packed_string_array *", "p_parts"]
]
},
{
"name": "godot_string_is_valid_filename",
"return_type": "godot_bool",
"arguments": [
["const godot_string *", "p_self"]
]
},
{
"name": "godot_string_is_valid_float",
"return_type": "godot_bool",

View file

@ -38,10 +38,11 @@ extern "C" {
#include <stdint.h>
#include <wchar.h>
typedef wchar_t godot_char_type;
typedef char32_t godot_char_type;
#define GODOT_STRING_SIZE sizeof(void *)
#define GODOT_CHAR_STRING_SIZE sizeof(void *)
#define GODOT_CHAR16_STRING_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
@ -58,6 +59,13 @@ typedef struct {
} godot_char_string;
#endif
#ifndef GODOT_CORE_API_GODOT_CHAR16_STRING_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_CHAR16_STRING_TYPE_DEFINED
typedef struct {
uint8_t _dont_touch_that[GODOT_CHAR16_STRING_SIZE];
} godot_char16_string;
#endif
// reduce extern "C" nesting for VS2013
#ifdef __cplusplus
}
@ -75,13 +83,28 @@ godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs);
const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs);
void GDAPI godot_char_string_destroy(godot_char_string *p_cs);
godot_int GDAPI godot_char16_string_length(const godot_char16_string *p_cs);
const char16_t GDAPI *godot_char16_string_get_data(const godot_char16_string *p_cs);
void GDAPI godot_char16_string_destroy(godot_char16_string *p_cs);
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
const wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx);
wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx);
const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self);
void GDAPI godot_string_new_with_latin1_chars(godot_string *r_dest, const char *p_contents);
void GDAPI godot_string_new_with_utf8_chars(godot_string *r_dest, const char *p_contents);
void GDAPI godot_string_new_with_utf16_chars(godot_string *r_dest, const char16_t *p_contents);
void GDAPI godot_string_new_with_utf32_chars(godot_string *r_dest, const char32_t *p_contents);
void GDAPI godot_string_new_with_wide_chars(godot_string *r_dest, const wchar_t *p_contents);
void GDAPI godot_string_new_with_latin1_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size);
void GDAPI godot_string_new_with_utf8_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size);
void GDAPI godot_string_new_with_utf16_chars_and_len(godot_string *r_dest, const char16_t *p_contents, const int p_size);
void GDAPI godot_string_new_with_utf32_chars_and_len(godot_string *r_dest, const char32_t *p_contents, const int p_size);
void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
const godot_char_type GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx);
godot_char_type GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx);
const godot_char_type GDAPI *godot_string_get_data(const godot_string *p_self);
godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b);
godot_bool GDAPI godot_string_operator_less(const godot_string *p_self, const godot_string *p_b);
@ -89,7 +112,7 @@ godot_string GDAPI godot_string_operator_plus(const godot_string *p_self, const
/* Standard size stuff */
godot_int GDAPI godot_string_length(const godot_string *p_self);
/*+++*/ godot_int GDAPI godot_string_length(const godot_string *p_self);
/* Helpers */
@ -99,24 +122,25 @@ signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, c
godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string);
godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self, const char *p_char_array);
godot_array GDAPI godot_string_bigrams(const godot_string *p_self);
godot_string GDAPI godot_string_chr(wchar_t p_character);
godot_packed_string_array GDAPI godot_string_bigrams(const godot_string *p_self);
godot_string GDAPI godot_string_chr(godot_char_type p_character);
godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_string *p_string);
godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what);
godot_int GDAPI godot_string_find_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys);
godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_array *p_keys, godot_int p_from);
godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key);
godot_int GDAPI godot_string_findn(const godot_string *p_self, godot_string p_what);
godot_int GDAPI godot_string_findn_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
godot_bool GDAPI godot_string_ends_with_char_array(const godot_string *p_self, const char *p_char_array);
godot_int GDAPI godot_string_count(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to);
godot_int GDAPI godot_string_countn(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to);
godot_int GDAPI godot_string_find(const godot_string *p_self, const godot_string *p_what);
godot_int GDAPI godot_string_find_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from);
godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_packed_string_array *p_keys);
godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from);
godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from, godot_int *r_key);
godot_int GDAPI godot_string_findn(const godot_string *p_self, const godot_string *p_what);
godot_int GDAPI godot_string_findn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from);
godot_string GDAPI godot_string_format(const godot_string *p_self, const godot_variant *p_values);
godot_string GDAPI godot_string_format_with_custom_placeholder(const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder);
godot_string GDAPI godot_string_hex_encode_buffer(const uint8_t *p_buffer, godot_int p_len);
godot_int GDAPI godot_string_hex_to_int(const godot_string *p_self);
godot_int GDAPI godot_string_hex_to_int_without_prefix(const godot_string *p_self);
godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, godot_string p_string);
godot_int GDAPI godot_string_hex_to_int_with_prefix(const godot_string *p_self);
godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, const godot_string *p_string);
godot_bool GDAPI godot_string_is_numeric(const godot_string *p_self);
godot_bool GDAPI godot_string_is_subsequence_of(const godot_string *p_self, const godot_string *p_string);
godot_bool GDAPI godot_string_is_subsequence_ofi(const godot_string *p_self, const godot_string *p_string);
@ -133,13 +157,13 @@ godot_string GDAPI godot_string_num_scientific(double p_num);
godot_string GDAPI godot_string_num_with_decimals(double p_num, godot_int p_decimals);
godot_string GDAPI godot_string_pad_decimals(const godot_string *p_self, godot_int p_digits);
godot_string GDAPI godot_string_pad_zeros(const godot_string *p_self, godot_int p_digits);
godot_string GDAPI godot_string_replace_first(const godot_string *p_self, godot_string p_key, godot_string p_with);
godot_string GDAPI godot_string_replace(const godot_string *p_self, godot_string p_key, godot_string p_with);
godot_string GDAPI godot_string_replacen(const godot_string *p_self, godot_string p_key, godot_string p_with);
godot_int GDAPI godot_string_rfind(const godot_string *p_self, godot_string p_what);
godot_int GDAPI godot_string_rfindn(const godot_string *p_self, godot_string p_what);
godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
godot_string GDAPI godot_string_replace_first(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with);
godot_string GDAPI godot_string_replace(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with);
godot_string GDAPI godot_string_replacen(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with);
godot_int GDAPI godot_string_rfind(const godot_string *p_self, const godot_string *p_what);
godot_int GDAPI godot_string_rfindn(const godot_string *p_self, const godot_string *p_what);
godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from);
godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from);
godot_string GDAPI godot_string_rpad(const godot_string *p_self, godot_int p_min_length);
godot_string GDAPI godot_string_rpad_with_custom_character(const godot_string *p_self, godot_int p_min_length, const godot_string *p_character);
godot_real GDAPI godot_string_similarity(const godot_string *p_self, const godot_string *p_string);
@ -151,64 +175,79 @@ godot_int GDAPI godot_string_to_int(const godot_string *p_self);
godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_self);
godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_string *p_self);
godot_string GDAPI godot_string_capitalize(const godot_string *p_self);
double GDAPI godot_string_char_to_float(const char *p_what);
double GDAPI godot_string_wchar_to_float(const wchar_t *p_str, const wchar_t **r_end);
godot_int GDAPI godot_string_char_to_int(const char *p_what);
int64_t GDAPI godot_string_wchar_to_int(const wchar_t *p_str);
godot_int GDAPI godot_string_wchar_to_int(const wchar_t *p_str);
godot_int GDAPI godot_string_char_to_int_with_len(const char *p_what, godot_int p_len);
int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_len);
int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self);
int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self);
int64_t GDAPI godot_string_to_int64(const godot_string *p_self);
double GDAPI godot_string_unicode_char_to_float(const wchar_t *p_str, const wchar_t **r_end);
godot_int GDAPI godot_string_wchar_to_int_with_len(const wchar_t *p_str, int p_len);
godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, godot_string p_splitter);
godot_string GDAPI godot_string_get_slice(const godot_string *p_self, godot_string p_splitter, godot_int p_slice);
godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p_splitter, godot_int p_slice);
godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, const godot_string *p_splitter);
godot_string GDAPI godot_string_get_slice(const godot_string *p_self, const godot_string *p_splitter, godot_int p_slice);
godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, godot_char_type p_splitter, godot_int p_slice);
godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_array *p_splitters);
godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters);
godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_array *p_splitters);
godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters);
godot_array GDAPI godot_string_split_spaces(const godot_string *p_self);
godot_packed_string_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_string_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_string_array GDAPI godot_string_split_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit);
wchar_t GDAPI godot_string_char_lowercase(wchar_t p_char);
wchar_t GDAPI godot_string_char_uppercase(wchar_t p_char);
godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_string_array GDAPI godot_string_rsplit_allow_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_string_array GDAPI godot_string_rsplit_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit);
godot_packed_float32_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_float32_array GDAPI godot_string_split_floats_allow_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_float32_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters);
godot_packed_float32_array GDAPI godot_string_split_floats_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters);
godot_packed_int32_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_int32_array GDAPI godot_string_split_ints_allow_empty(const godot_string *p_self, const godot_string *p_splitter);
godot_packed_int32_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters);
godot_packed_int32_array GDAPI godot_string_split_ints_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters);
godot_packed_string_array GDAPI godot_string_split_spaces(const godot_string *p_self);
godot_char_type GDAPI godot_string_char_lowercase(godot_char_type p_char);
godot_char_type GDAPI godot_string_char_uppercase(godot_char_type p_char);
godot_string GDAPI godot_string_to_lower(const godot_string *p_self);
godot_string GDAPI godot_string_to_upper(const godot_string *p_self);
godot_string GDAPI godot_string_get_basename(const godot_string *p_self);
godot_string GDAPI godot_string_get_extension(const godot_string *p_self);
godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos);
wchar_t GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx);
godot_char_type GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx);
godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godot_string *p_file);
godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_pos);
godot_string GDAPI godot_string_repeat(const godot_string *p_self, godot_int p_count);
godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bool p_left, godot_bool p_right);
godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self);
void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars);
godot_char_string GDAPI godot_string_ascii(const godot_string *p_self);
godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self);
godot_char_string GDAPI godot_string_latin1(const godot_string *p_self);
godot_char_string GDAPI godot_string_utf8(const godot_string *p_self);
godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8);
godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len);
godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8);
godot_string GDAPI godot_string_chars_to_utf8_with_len(const char *p_utf8, godot_int p_len);
godot_char16_string GDAPI godot_string_utf16(const godot_string *p_self);
godot_bool GDAPI godot_string_parse_utf16(godot_string *p_self, const char16_t *p_utf16);
godot_bool GDAPI godot_string_parse_utf16_with_len(godot_string *p_self, const char16_t *p_utf16, godot_int p_len);
uint32_t GDAPI godot_string_hash(const godot_string *p_self);
uint64_t GDAPI godot_string_hash64(const godot_string *p_self);
uint32_t GDAPI godot_string_hash_chars(const char *p_cstr);
uint32_t GDAPI godot_string_hash_chars_with_len(const char *p_cstr, godot_int p_len);
uint32_t GDAPI godot_string_hash_utf8_chars(const wchar_t *p_str);
uint32_t GDAPI godot_string_hash_utf8_chars_with_len(const wchar_t *p_str, godot_int p_len);
uint32_t GDAPI godot_string_hash_wide_chars(const wchar_t *p_str);
uint32_t GDAPI godot_string_hash_wide_chars_with_len(const wchar_t *p_str, godot_int p_len);
godot_packed_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self);
godot_string GDAPI godot_string_md5_text(const godot_string *p_self);
godot_packed_byte_array GDAPI godot_string_sha1_buffer(const godot_string *p_self);
godot_string GDAPI godot_string_sha1_text(const godot_string *p_self);
godot_packed_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self);
godot_string GDAPI godot_string_sha256_text(const godot_string *p_self);
@ -231,14 +270,15 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self);
godot_string GDAPI godot_string_http_escape(const godot_string *p_self);
godot_string GDAPI godot_string_http_unescape(const godot_string *p_self);
godot_string GDAPI godot_string_json_escape(const godot_string *p_self);
godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line);
godot_string GDAPI godot_string_xml_escape(const godot_string *p_self);
godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self);
godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self);
godot_string GDAPI godot_string_percent_decode(const godot_string *p_self);
godot_string GDAPI godot_string_percent_encode(const godot_string *p_self);
godot_string GDAPI godot_string_join(const godot_string *p_self, const godot_packed_string_array *p_parts);
godot_bool GDAPI godot_string_is_valid_filename(const godot_string *p_self);
godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self);
godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix);
godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self);
@ -249,8 +289,8 @@ godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self);
godot_string GDAPI godot_string_dedent(const godot_string *p_self);
godot_string GDAPI godot_string_trim_prefix(const godot_string *p_self, const godot_string *p_prefix);
godot_string GDAPI godot_string_trim_suffix(const godot_string *p_self, const godot_string *p_suffix);
godot_string GDAPI godot_string_lstrip(const godot_string *p_self, const godot_string *p_chars);
godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars);
godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_divisor, const godot_bool p_allow_empty, const godot_int p_maxsplit);
void GDAPI godot_string_destroy(godot_string *p_self);

View file

@ -176,10 +176,10 @@ List<ClassAPI> generate_c_api_classes() {
// Register global constants as a fake GlobalConstants singleton class
{
ClassAPI global_constants_api;
global_constants_api.class_name = L"GlobalConstants";
global_constants_api.class_name = "GlobalConstants";
global_constants_api.api_type = ClassDB::API_CORE;
global_constants_api.is_singleton = true;
global_constants_api.singleton_name = L"GlobalConstants";
global_constants_api.singleton_name = "GlobalConstants";
global_constants_api.is_instanciable = false;
const int constants_count = GlobalConstants::get_global_constant_count();
for (int i = 0; i < constants_count; ++i) {

View file

@ -33,15 +33,15 @@
#include "../gdscript_tokenizer.h"
#include "editor/editor_settings.h"
static bool _is_char(CharType c) {
static bool _is_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
static bool _is_hex_symbol(CharType c) {
static bool _is_hex_symbol(char32_t c) {
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}
static bool _is_bin_symbol(CharType c) {
static bool _is_bin_symbol(char32_t c) {
return (c == '0' || c == '1');
}
@ -119,7 +119,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
/* search the line */
bool match = true;
const CharType *start_key = color_regions[c].start_key.c_str();
const char32_t *start_key = color_regions[c].start_key.get_data();
for (int k = 0; k < start_key_length; k++) {
if (start_key[k] != str[from + k]) {
match = false;
@ -156,7 +156,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line)
/* search the line */
int region_end_index = -1;
int end_key_length = color_regions[in_region].end_key.length();
const CharType *end_key = color_regions[in_region].end_key.c_str();
const char32_t *end_key = color_regions[in_region].end_key.get_data();
for (; from < line_length; from++) {
if (line_length - from < end_key_length) {
break;

View file

@ -635,7 +635,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
case TEXT_CHAR: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
CharType result[2] = { *p_args[0], 0 };
char32_t result[2] = { *p_args[0], 0 };
r_ret = String(result);
} break;
case TEXT_ORD: {

View file

@ -327,7 +327,7 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_
bool found = false;
const String &line = lines[i];
for (int j = 0; j < line.size(); j++) {
if (line[j] == CharType(0xFFFF)) {
if (line[j] == char32_t(0xFFFF)) {
found = true;
break;
} else if (line[j] == '\t') {

View file

@ -222,7 +222,7 @@ String GDScriptTokenizer::get_token_name(Token::Type p_token_type) {
void GDScriptTokenizer::set_source_code(const String &p_source_code) {
source = p_source_code;
if (source.empty()) {
_source = L"";
_source = U"";
} else {
_source = source.ptr();
}
@ -263,7 +263,7 @@ bool GDScriptTokenizer::is_past_cursor() const {
return true;
}
CharType GDScriptTokenizer::_advance() {
char32_t GDScriptTokenizer::_advance() {
if (unlikely(_is_at_end())) {
return '\0';
}
@ -282,15 +282,15 @@ CharType GDScriptTokenizer::_advance() {
return _peek(-1);
}
void GDScriptTokenizer::push_paren(CharType p_char) {
void GDScriptTokenizer::push_paren(char32_t p_char) {
paren_stack.push_back(p_char);
}
bool GDScriptTokenizer::pop_paren(CharType p_expected) {
bool GDScriptTokenizer::pop_paren(char32_t p_expected) {
if (paren_stack.empty()) {
return false;
}
CharType actual = paren_stack.back()->get();
char32_t actual = paren_stack.back()->get();
paren_stack.pop_back();
return actual == p_expected;
@ -302,19 +302,19 @@ GDScriptTokenizer::Token GDScriptTokenizer::pop_error() {
return error;
}
static bool _is_alphanumeric(CharType c) {
static bool _is_alphanumeric(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
static bool _is_digit(CharType c) {
static bool _is_digit(char32_t c) {
return (c >= '0' && c <= '9');
}
static bool _is_hex_digit(CharType c) {
static bool _is_hex_digit(char32_t c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
static bool _is_binary_digit(CharType c) {
static bool _is_binary_digit(char32_t c) {
return (c == '0' || c == '1');
}
@ -404,7 +404,7 @@ void GDScriptTokenizer::push_error(const Token &p_error) {
error_stack.push_back(p_error);
}
GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(CharType p_paren) {
GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(char32_t p_paren) {
if (paren_stack.empty()) {
return make_error(vformat("Closing \"%c\" doesn't have an opening counterpart.", p_paren));
}
@ -413,8 +413,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(CharType p_paren) {
return error;
}
GDScriptTokenizer::Token GDScriptTokenizer::check_vcs_marker(CharType p_test, Token::Type p_double_type) {
const CharType *next = _current + 1;
GDScriptTokenizer::Token GDScriptTokenizer::check_vcs_marker(char32_t p_test, Token::Type p_double_type) {
const char32_t *next = _current + 1;
int chars = 2; // Two already matched.
// Test before consuming characters, since we don't want to consume more than needed.
@ -602,7 +602,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() {
bool has_decimal = false;
bool has_exponent = false;
bool has_error = false;
bool (*digit_check_func)(CharType) = _is_digit;
bool (*digit_check_func)(char32_t) = _is_digit;
if (_peek(-1) == '.') {
has_decimal = true;
@ -762,7 +762,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() {
_advance();
}
CharType quote_char = _peek(-1);
char32_t quote_char = _peek(-1);
if (_peek() == quote_char && _peek(1) == quote_char) {
is_multiline = true;
@ -779,7 +779,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() {
return make_error("Unterminated string.");
}
CharType ch = _peek();
char32_t ch = _peek();
if (ch == '\\') {
// Escape pattern.
@ -789,13 +789,13 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() {
}
// Grab escape character.
CharType code = _peek();
char32_t code = _peek();
_advance();
if (_is_at_end()) {
return make_error("Unterminated string.");
}
CharType escaped = 0;
char32_t escaped = 0;
bool valid_escape = true;
switch (code) {
@ -836,8 +836,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() {
return make_error("Unterminated string.");
}
CharType digit = _peek();
CharType value = 0;
char32_t digit = _peek();
char32_t value = 0;
if (digit >= '0' && digit <= '9') {
value = digit - '0';
} else if (digit >= 'a' && digit <= 'f') {
@ -940,7 +940,7 @@ void GDScriptTokenizer::check_indent() {
}
for (;;) {
CharType current_indent_char = _peek();
char32_t current_indent_char = _peek();
int indent_count = 0;
if (current_indent_char != ' ' && current_indent_char != '\t' && current_indent_char != '\r' && current_indent_char != '\n' && current_indent_char != '#') {
@ -970,7 +970,7 @@ void GDScriptTokenizer::check_indent() {
// Check indent level.
bool mixed = false;
while (!_is_at_end()) {
CharType space = _peek();
char32_t space = _peek();
if (space == '\t') {
// Consider individual tab columns.
column += tab_size - 1;
@ -1103,7 +1103,7 @@ void GDScriptTokenizer::_skip_whitespace() {
}
for (;;) {
CharType c = _peek();
char32_t c = _peek();
switch (c) {
case ' ':
_advance();
@ -1192,7 +1192,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
return make_token(Token::TK_EOF);
}
const CharType c = _advance();
const char32_t c = _advance();
if (c == '\\') {
// Line continuation with backslash.

View file

@ -183,14 +183,14 @@ public:
private:
String source;
const CharType *_source = nullptr;
const CharType *_current = nullptr;
const char32_t *_source = nullptr;
const char32_t *_current = nullptr;
int line = -1, column = -1;
int cursor_line = -1, cursor_column = -1;
int tab_size = 4;
// Keep track of multichar tokens.
const CharType *_start = nullptr;
const char32_t *_start = nullptr;
int start_line = 0, start_column = 0;
int leftmost_column = 0, rightmost_column = 0;
@ -202,30 +202,30 @@ private:
Token last_newline;
int pending_indents = 0;
List<int> indent_stack;
List<CharType> paren_stack;
CharType indent_char = '\0';
List<char32_t> paren_stack;
char32_t indent_char = '\0';
int position = 0;
int length = 0;
_FORCE_INLINE_ bool _is_at_end() { return position >= length; }
_FORCE_INLINE_ CharType _peek(int p_offset = 0) { return position + p_offset >= 0 && position + p_offset < length ? _current[p_offset] : '\0'; }
_FORCE_INLINE_ char32_t _peek(int p_offset = 0) { return position + p_offset >= 0 && position + p_offset < length ? _current[p_offset] : '\0'; }
int indent_level() const { return indent_stack.size(); }
bool has_error() const { return !error_stack.empty(); }
Token pop_error();
CharType _advance();
char32_t _advance();
void _skip_whitespace();
void check_indent();
Token make_error(const String &p_message);
void push_error(const String &p_message);
void push_error(const Token &p_error);
Token make_paren_error(CharType p_paren);
Token make_paren_error(char32_t p_paren);
Token make_token(Token::Type p_type);
Token make_literal(const Variant &p_literal);
Token make_identifier(const StringName &p_identifier);
Token check_vcs_marker(CharType p_test, Token::Type p_double_type);
void push_paren(CharType p_char);
bool pop_paren(CharType p_expected);
Token check_vcs_marker(char32_t p_test, Token::Type p_double_type);
void push_paren(char32_t p_char);
bool pop_paren(char32_t p_expected);
void newline(bool p_make_token);
Token number();

View file

@ -491,7 +491,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &
int start_pos = p_position.character;
for (int c = p_position.character; c >= 0; c--) {
start_pos = c;
CharType ch = line[c];
char32_t ch = line[c];
bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
if (!valid_char) {
break;
@ -500,7 +500,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &
int end_pos = p_position.character;
for (int c = p_position.character; c < line.length(); c++) {
CharType ch = line[c];
char32_t ch = line[c];
bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
if (!valid_char) {
break;
@ -552,7 +552,7 @@ Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_positi
}
while (c >= 0) {
const CharType &character = line[c];
const char32_t &character = line[c];
if (character == ')') {
++bracket_stack;
} else if (character == '(') {

View file

@ -151,7 +151,7 @@ ScriptClassParser::Token ScriptClassParser::get_token() {
case '"': {
bool verbatim = idx != 0 && code[idx - 1] == '@';
CharType begin_str = code[idx];
char32_t begin_str = code[idx];
idx++;
String tk_string = String();
while (true) {
@ -170,13 +170,13 @@ ScriptClassParser::Token ScriptClassParser::get_token() {
} else if (code[idx] == '\\' && !verbatim) {
//escaped characters...
idx++;
CharType next = code[idx];
char32_t next = code[idx];
if (next == 0) {
error_str = "Unterminated String";
error = true;
return TK_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -234,7 +234,7 @@ ScriptClassParser::Token ScriptClassParser::get_token() {
if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) {
//a number
const CharType *rptr;
const char32_t *rptr;
double number = String::to_float(&code[idx], &rptr);
idx += (rptr - &code[idx]);
value = number;

View file

@ -311,44 +311,6 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_
return false;
}
String mono_to_utf8_string(MonoString *p_mono_string) {
MonoError error;
char *utf8 = mono_string_to_utf8_checked(p_mono_string, &error);
if (!mono_error_ok(&error)) {
ERR_PRINT(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&error) + "'.");
mono_error_cleanup(&error);
return String();
}
String ret = String::utf8(utf8);
mono_free(utf8);
return ret;
}
String mono_to_utf16_string(MonoString *p_mono_string) {
int len = mono_string_length(p_mono_string);
String ret;
if (len == 0) {
return ret;
}
ret.resize(len + 1);
ret.set(len, 0);
CharType *src = (CharType *)mono_string_chars(p_mono_string);
CharType *dst = ret.ptrw();
for (int i = 0; i < len; i++) {
dst[i] = src[i];
}
return ret;
}
MonoObject *variant_to_mono_object(const Variant *p_var) {
ManagedType type;

View file

@ -69,15 +69,11 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_
// String
String mono_to_utf8_string(MonoString *p_mono_string);
String mono_to_utf16_string(MonoString *p_mono_string);
_FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) {
if constexpr (sizeof(CharType) == 2) {
return mono_to_utf16_string(p_mono_string);
}
return mono_to_utf8_string(p_mono_string);
char32_t *utf32 = (char32_t *)mono_string_to_utf32(p_mono_string);
String ret = String(utf32);
mono_free(utf32);
return ret;
}
_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) {
@ -88,20 +84,8 @@ _FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) {
return mono_string_to_godot_not_null(p_mono_string);
}
_FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) {
return mono_string_new(mono_domain_get(), p_string.utf8().get_data());
}
_FORCE_INLINE_ MonoString *mono_from_utf16_string(const String &p_string) {
return mono_string_from_utf16((mono_unichar2 *)p_string.c_str());
}
_FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
if constexpr (sizeof(CharType) == 2) {
return mono_from_utf16_string(p_string);
}
return mono_from_utf8_string(p_string);
return mono_string_from_utf32((mono_unichar4 *)(p_string.get_data()));
}
// Variant

View file

@ -71,12 +71,12 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value)
buffer.resize(512);
DWORD dwBufferSize = buffer.size();
LONG res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize);
LONG res = RegQueryValueExW(hKey, (LPCWSTR)(p_value_name.utf16().get_data()), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize);
if (res == ERROR_MORE_DATA) {
// dwBufferSize now contains the actual size
buffer.resize(dwBufferSize);
res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize);
res = RegQueryValueExW(hKey, (LPCWSTR)(p_value_name.utf16().get_data()), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize);
}
if (res == ERROR_SUCCESS) {
@ -90,7 +90,7 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value)
LONG _find_mono_in_reg(const String &p_subkey, MonoRegInfo &r_info, bool p_old_reg = false) {
HKEY hKey;
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey);
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey);
if (res != ERROR_SUCCESS)
goto cleanup;
@ -127,7 +127,7 @@ LONG _find_mono_in_reg_old(const String &p_subkey, MonoRegInfo &r_info) {
String default_clr;
HKEY hKey;
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey);
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey);
if (res != ERROR_SUCCESS)
goto cleanup;

View file

@ -86,7 +86,7 @@ String abspath(const String &p_path) {
String realpath(const String &p_path) {
#ifdef WINDOWS_ENABLED
// Open file without read/write access
HANDLE hFile = ::CreateFileW(p_path.c_str(), 0,
HANDLE hFile = ::CreateFileW((LPCWSTR)(p_path.utf16().get_data()), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
@ -130,7 +130,7 @@ String join(const String &p_a, const String &p_b) {
return p_b;
}
const CharType a_last = p_a[p_a.length() - 1];
const char32_t a_last = p_a[p_a.length() - 1];
if ((a_last == '/' || a_last == '\\') ||
(p_b.size() > 0 && (p_b[0] == '/' || p_b[0] == '\\'))) {
return p_a + p_b;

View file

@ -49,7 +49,7 @@ int sfind(const String &p_text, int p_from) {
return -1;
}
const CharType *src = p_text.c_str();
const char32_t *src = p_text.get_data();
for (int i = p_from; i <= (len - src_len); i++) {
bool found = true;
@ -64,7 +64,7 @@ int sfind(const String &p_text, int p_from) {
found = src[read_pos] == '%';
break;
case 1: {
CharType c = src[read_pos];
char32_t c = src[read_pos];
found = src[read_pos] == 's' || (c >= '0' && c <= '4');
break;
}
@ -121,7 +121,7 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const
int result = 0;
while ((result = sfind(p_text, search_from)) >= 0) {
CharType c = p_text[result + 1];
char32_t c = p_text[result + 1];
int req_index = (c == 's' ? findex++ : c - '0');

View file

@ -156,26 +156,13 @@ void RegExMatch::_bind_methods() {
}
void RegEx::_pattern_info(uint32_t what, void *where) const {
if (sizeof(CharType) == 2) {
pcre2_pattern_info_16((pcre2_code_16 *)code, what, where);
} else {
pcre2_pattern_info_32((pcre2_code_32 *)code, what, where);
}
pcre2_pattern_info_32((pcre2_code_32 *)code, what, where);
}
void RegEx::clear() {
if (sizeof(CharType) == 2) {
if (code) {
pcre2_code_free_16((pcre2_code_16 *)code);
code = nullptr;
}
} else {
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
code = nullptr;
}
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
code = nullptr;
}
}
@ -187,39 +174,20 @@ Error RegEx::compile(const String &p_pattern) {
PCRE2_SIZE offset;
uint32_t flags = PCRE2_DUPNAMES;
if (sizeof(CharType) == 2) {
pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx;
pcre2_compile_context_16 *cctx = pcre2_compile_context_create_16(gctx);
PCRE2_SPTR16 p = (PCRE2_SPTR16)pattern.c_str();
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_compile_context_32 *cctx = pcre2_compile_context_create_32(gctx);
PCRE2_SPTR32 p = (PCRE2_SPTR32)pattern.get_data();
code = pcre2_compile_16(p, pattern.length(), flags, &err, &offset, cctx);
code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx);
pcre2_compile_context_free_16(cctx);
pcre2_compile_context_free_32(cctx);
if (!code) {
PCRE2_UCHAR16 buf[256];
pcre2_get_error_message_16(err, buf, 256);
String message = String::num(offset) + ": " + String((const CharType *)buf);
ERR_PRINT(message.utf8());
return FAILED;
}
} else {
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_compile_context_32 *cctx = pcre2_compile_context_create_32(gctx);
PCRE2_SPTR32 p = (PCRE2_SPTR32)pattern.c_str();
code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx);
pcre2_compile_context_free_32(cctx);
if (!code) {
PCRE2_UCHAR32 buf[256];
pcre2_get_error_message_32(err, buf, 256);
String message = String::num(offset) + ": " + String((const CharType *)buf);
ERR_PRINT(message.utf8());
return FAILED;
}
if (!code) {
PCRE2_UCHAR32 buf[256];
pcre2_get_error_message_32(err, buf, 256);
String message = String::num(offset) + ": " + String((const char32_t *)buf);
ERR_PRINT(message.utf8());
return FAILED;
}
return OK;
}
@ -234,69 +202,39 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
length = p_end;
}
if (sizeof(CharType) == 2) {
pcre2_code_16 *c = (pcre2_code_16 *)code;
pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx;
pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx);
PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str();
pcre2_code_32 *c = (pcre2_code_32 *)code;
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.get_data();
pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx);
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_match_16(c, s, length, p_offset, 0, match, mctx);
if (res < 0) {
pcre2_match_data_free_16(match);
return nullptr;
}
uint32_t size = pcre2_get_ovector_count_16(match);
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(match);
result->data.resize(size);
for (uint32_t i = 0; i < size; i++) {
result->data.write[i].start = ovector[i * 2];
result->data.write[i].end = ovector[i * 2 + 1];
}
pcre2_match_data_free_16(match);
pcre2_match_context_free_16(mctx);
} else {
pcre2_code_32 *c = (pcre2_code_32 *)code;
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str();
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_match_32(c, s, length, p_offset, 0, match, mctx);
if (res < 0) {
pcre2_match_data_free_32(match);
pcre2_match_context_free_32(mctx);
return nullptr;
}
uint32_t size = pcre2_get_ovector_count_32(match);
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(match);
result->data.resize(size);
for (uint32_t i = 0; i < size; i++) {
result->data.write[i].start = ovector[i * 2];
result->data.write[i].end = ovector[i * 2 + 1];
}
int res = pcre2_match_32(c, s, length, p_offset, 0, match, mctx);
if (res < 0) {
pcre2_match_data_free_32(match);
pcre2_match_context_free_32(mctx);
return nullptr;
}
uint32_t size = pcre2_get_ovector_count_32(match);
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(match);
result->data.resize(size);
for (uint32_t i = 0; i < size; i++) {
result->data.write[i].start = ovector[i * 2];
result->data.write[i].end = ovector[i * 2 + 1];
}
pcre2_match_data_free_32(match);
pcre2_match_context_free_32(mctx);
result->subject = p_subject;
uint32_t count;
const CharType *table;
const char32_t *table;
uint32_t entry_size;
_pattern_info(PCRE2_INFO_NAMECOUNT, &count);
@ -304,7 +242,7 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
_pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &entry_size);
for (uint32_t i = 0; i < count; i++) {
CharType id = table[i * entry_size];
char32_t id = table[i * entry_size];
if (result->data[id].start == -1) {
continue;
}
@ -344,7 +282,7 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
const int safety_zone = 1;
PCRE2_SIZE olength = p_subject.length() + 1; // space for output string and one terminating \0 character
Vector<CharType> output;
Vector<char32_t> output;
output.resize(olength + safety_zone);
uint32_t flags = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH;
@ -357,55 +295,28 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
length = p_end;
}
if (sizeof(CharType) == 2) {
pcre2_code_16 *c = (pcre2_code_16 *)code;
pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx;
pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx);
PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str();
PCRE2_SPTR16 r = (PCRE2_SPTR16)p_replacement.c_str();
PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.ptrw();
pcre2_code_32 *c = (pcre2_code_32 *)code;
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.get_data();
PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.get_data();
PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw();
pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx);
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
output.resize(olength + safety_zone);
o = (PCRE2_UCHAR16 *)output.ptrw();
res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
if (res == PCRE2_ERROR_NOMEMORY) {
output.resize(olength + safety_zone);
o = (PCRE2_UCHAR32 *)output.ptrw();
res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
pcre2_match_data_free_16(match);
pcre2_match_context_free_16(mctx);
pcre2_match_data_free_32(match);
pcre2_match_context_free_32(mctx);
if (res < 0) {
return String();
}
} else {
pcre2_code_32 *c = (pcre2_code_32 *)code;
pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx;
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str();
PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.c_str();
PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw();
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
output.resize(olength + safety_zone);
o = (PCRE2_UCHAR32 *)output.ptrw();
res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
pcre2_match_data_free_32(match);
pcre2_match_context_free_32(mctx);
if (res < 0) {
return String();
}
if (res < 0) {
return String();
}
return String(output.ptr(), olength);
@ -435,7 +346,7 @@ Array RegEx::get_names() const {
ERR_FAIL_COND_V(!is_valid(), result);
uint32_t count;
const CharType *table;
const char32_t *table;
uint32_t entry_size;
_pattern_info(PCRE2_INFO_NAMECOUNT, &count);
@ -453,39 +364,21 @@ Array RegEx::get_names() const {
}
RegEx::RegEx() {
if (sizeof(CharType) == 2) {
general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr);
} else {
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
}
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
code = nullptr;
}
RegEx::RegEx(const String &p_pattern) {
if (sizeof(CharType) == 2) {
general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr);
} else {
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
}
general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr);
code = nullptr;
compile(p_pattern);
}
RegEx::~RegEx() {
if (sizeof(CharType) == 2) {
if (code) {
pcre2_code_free_16((pcre2_code_16 *)code);
}
pcre2_general_context_free_16((pcre2_general_context_16 *)general_ctx);
} else {
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
}
pcre2_general_context_free_32((pcre2_general_context_32 *)general_ctx);
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
}
pcre2_general_context_free_32((pcre2_general_context_32 *)general_ctx);
}
void RegEx::_bind_methods() {

View file

@ -1060,7 +1060,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
} break;
case VisualScriptBuiltinFunc::TEXT_CHAR: {
CharType result[2] = { *p_inputs[0], 0 };
char32_t result[2] = { *p_inputs[0], 0 };
*r_return = String(result);

View file

@ -187,7 +187,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
while (true) {
#define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++])
CharType cchar = GET_CHAR();
char32_t cchar = GET_CHAR();
if (cchar == 0) {
r_token.type = TK_EOF;
return OK;
@ -329,7 +329,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
case '"': {
String str;
while (true) {
CharType ch = GET_CHAR();
char32_t ch = GET_CHAR();
if (ch == 0) {
_set_error("Unterminated String");
@ -340,13 +340,13 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
} else if (ch == '\\') {
//escaped characters...
CharType next = GET_CHAR();
char32_t next = GET_CHAR();
if (next == 0) {
_set_error("Unterminated String");
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -367,7 +367,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
case 'u': {
// hex number
for (int j = 0; j < 4; j++) {
CharType c = GET_CHAR();
char32_t c = GET_CHAR();
if (c == 0) {
_set_error("Unterminated String");
@ -379,7 +379,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
r_token.type = TK_ERROR;
return ERR_PARSE_ERROR;
}
CharType v;
char32_t v;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
@ -431,7 +431,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
#define READING_DONE 4
int reading = READING_INT;
CharType c = cchar;
char32_t c = cchar;
bool exp_sign = false;
bool exp_beg = false;
bool is_float = false;

View file

@ -933,36 +933,36 @@ static const char *op_names[] = {
};
String VisualScriptOperator::get_caption() const {
static const wchar_t *op_names[] = {
static const char32_t *op_names[] = {
//comparison
L"A = B", //OP_EQUAL,
L"A \u2260 B", //OP_NOT_EQUAL,
L"A < B", //OP_LESS,
L"A \u2264 B", //OP_LESS_EQUAL,
L"A > B", //OP_GREATER,
L"A \u2265 B", //OP_GREATER_EQUAL,
U"A = B", //OP_EQUAL,
U"A \u2260 B", //OP_NOT_EQUAL,
U"A < B", //OP_LESS,
U"A \u2264 B", //OP_LESS_EQUAL,
U"A > B", //OP_GREATER,
U"A \u2265 B", //OP_GREATER_EQUAL,
//mathematic
L"A + B", //OP_ADD,
L"A - B", //OP_SUBTRACT,
L"A \u00D7 B", //OP_MULTIPLY,
L"A \u00F7 B", //OP_DIVIDE,
L"\u00AC A", //OP_NEGATE,
L"+ A", //OP_POSITIVE,
L"A mod B", //OP_MODULE,
L"A .. B", //OP_STRING_CONCAT,
U"A + B", //OP_ADD,
U"A - B", //OP_SUBTRACT,
U"A \u00D7 B", //OP_MULTIPLY,
U"A \u00F7 B", //OP_DIVIDE,
U"\u00AC A", //OP_NEGATE,
U"+ A", //OP_POSITIVE,
U"A mod B", //OP_MODULE,
U"A .. B", //OP_STRING_CONCAT,
//bitwise
L"A << B", //OP_SHIFT_LEFT,
L"A >> B", //OP_SHIFT_RIGHT,
L"A & B", //OP_BIT_AND,
L"A | B", //OP_BIT_OR,
L"A ^ B", //OP_BIT_XOR,
L"~A", //OP_BIT_NEGATE,
U"A << B", //OP_SHIFT_LEFT,
U"A >> B", //OP_SHIFT_RIGHT,
U"A & B", //OP_BIT_AND,
U"A | B", //OP_BIT_OR,
U"A ^ B", //OP_BIT_XOR,
U"~A", //OP_BIT_NEGATE,
//logic
L"A and B", //OP_AND,
L"A or B", //OP_OR,
L"A xor B", //OP_XOR,
L"not A", //OP_NOT,
L"A in B", //OP_IN,
U"A and B", //OP_AND,
U"A or B", //OP_OR,
U"A xor B", //OP_XOR,
U"not A", //OP_NOT,
U"A in B", //OP_IN,
};
return op_names[op];

View file

@ -453,7 +453,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
String name;
bool first = true;
for (int i = 0; i < basename.length(); i++) {
CharType c = basename[i];
char32_t c = basename[i];
if (c >= '0' && c <= '9' && first) {
continue;
}
@ -484,7 +484,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int segments = 0;
bool first = true;
for (int i = 0; i < pname.length(); i++) {
CharType c = pname[i];
char32_t c = pname[i];
if (first && c == '.') {
if (r_error) {
*r_error = TTR("Package segments must be of non-zero length.");
@ -873,7 +873,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
if (string_flags & UTF8_FLAG) {
} else {
uint32_t len = decode_uint16(&p_manifest[string_at]);
Vector<CharType> ucstring;
Vector<char32_t> ucstring;
ucstring.resize(len + 1);
for (uint32_t j = 0; j < len; j++) {
uint16_t c = decode_uint16(&p_manifest[string_at + 2 + 2 * j]);
@ -1334,7 +1334,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
} else {
String str;
for (uint32_t i = 0; i < len; i++) {
CharType c = decode_uint16(&p_bytes[offset + i * 2]);
char32_t c = decode_uint16(&p_bytes[offset + i * 2]);
if (c == 0) {
break;
}

View file

@ -701,7 +701,7 @@ Error DisplayServerIPhone::native_video_play(String p_path, float p_volume, Stri
if (p_path.begins_with("res://")) {
if (PackedData::get_singleton()->has_path(p_path)) {
printf("Unable to play %S using the native player as it resides in a .pck file\n", p_path.c_str());
printf("Unable to play %s using the native player as it resides in a .pck file\n", p_path.utf8().get_data());
return ERR_INVALID_PARAMETER;
} else {
p_path = p_path.replace("res:/", ProjectSettings::get_singleton()->get_resource_path());
@ -712,7 +712,7 @@ Error DisplayServerIPhone::native_video_play(String p_path, float p_volume, Stri
memdelete(f);
printf("Playing video: %S\n", p_path.c_str());
printf("Playing video: %s\n", p_path.utf8().get_data());
String file_path = ProjectSettings::get_singleton()->globalize_path(p_path);

View file

@ -115,7 +115,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
}
for (int i = 0; i < pname.length(); i++) {
CharType c = pname[i];
char32_t c = pname[i];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) {
if (r_error) {
*r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c));

View file

@ -138,7 +138,7 @@ Error InAppStore::request_product_info(Dictionary p_params) {
NSMutableArray *array = [[[NSMutableArray alloc] initWithCapacity:pids.size()] autorelease];
for (int i = 0; i < pids.size(); i++) {
printf("******** adding %ls to product list\n", pids[i].c_str());
printf("******** adding %s to product list\n", pids[i].utf8().get_data());
NSString *pid = [[[NSString alloc] initWithUTF8String:pids[i].utf8().get_data()] autorelease];
[array addObject:pid];
};

View file

@ -86,7 +86,7 @@ String iOS::get_rate_url(int p_app_id) const {
// ios7 for everything?
ret = templ_iOS7.replace("APP_ID", String::num(p_app_id));
printf("returning rate url %ls\n", ret.c_str());
printf("returning rate url %s\n", ret.utf8().get_data());
return ret;
};

View file

@ -278,7 +278,7 @@ Error OSIPhone::shell_open(String p_uri) {
return ERR_CANT_OPEN;
}
printf("opening url %ls\n", p_uri.c_str());
printf("opening url %s\n", p_uri.utf8().get_data());
// if (@available(iOS 10, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
@ -293,7 +293,7 @@ void OSIPhone::set_user_data_dir(String p_dir) {
DirAccess *da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %ls from %ls\n", user_data_dir.c_str(), p_dir.c_str());
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
memdelete(da);
}

View file

@ -67,7 +67,7 @@ static void handle_crash(int sig) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH);
}
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data());
char **strings = backtrace_symbols(bt_buffer, size);
if (strings) {
for (size_t i = 1; i < size; i++) {
@ -109,7 +109,7 @@ static void handle_crash(int sig) {
output.erase(output.length() - 1, 1);
}
fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str());
fprintf(stderr, "[%ld] %s (%s)\n", (long int)i, fname, output.utf8().get_data());
}
free(strings);

View file

@ -90,7 +90,7 @@ static void handle_crash(int sig) {
if (OS::get_singleton()->get_main_loop())
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH);
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data());
char **strings = backtrace_symbols(bt_buffer, size);
if (strings) {
void *load_addr = (void *)load_address();
@ -142,7 +142,7 @@ static void handle_crash(int sig) {
}
}
fprintf(stderr, "[%zu] %ls\n", i, output.c_str());
fprintf(stderr, "[%zu] %s\n", i, output.utf8().get_data());
}
free(strings);

View file

@ -78,7 +78,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
}
for (int i = 0; i < pname.length(); i++) {
CharType c = pname[i];
char32_t c = pname[i];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) {
if (r_error) {
*r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c));

View file

@ -296,7 +296,7 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
void OS_UWP::set_clipboard(const String &p_text) {
DataPackage ^ clip = ref new DataPackage();
clip->RequestedOperation = DataPackageOperation::Copy;
clip->SetText(ref new Platform::String((const wchar_t *)p_text.c_str()));
clip->SetText(ref new Platform::String((LPCWSTR)(p_text.utf16().get_data())));
Clipboard::SetContent(clip);
};
@ -346,8 +346,8 @@ void OS_UWP::finalize_core() {
}
void OS_UWP::alert(const String &p_alert, const String &p_title) {
Platform::String ^ alert = ref new Platform::String(p_alert.c_str());
Platform::String ^ title = ref new Platform::String(p_title.c_str());
Platform::String ^ alert = ref new Platform::String((LPCWSTR)(p_alert.utf16().get_data()));
Platform::String ^ title = ref new Platform::String((LPCWSTR)(p_title.utf16().get_data()));
MessageDialog ^ msg = ref new MessageDialog(alert, title);
@ -738,7 +738,7 @@ static String format_error_message(DWORD id) {
Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
String full_path = "game/" + p_path;
p_library_handle = (void *)LoadPackagedLibrary(full_path.c_str(), 0);
p_library_handle = (void *)LoadPackagedLibrary((LPCWSTR)(full_path.utf16().get_data()), 0);
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + full_path + ", error: " + format_error_message(GetLastError()) + ".");
return OK;
}

View file

@ -175,7 +175,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
msg = proj_settings->get("debug/settings/crash_handler/message");
}
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data());
int n = 0;
do {

View file

@ -42,7 +42,7 @@ static String format_error_message(DWORD id) {
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr);
String msg = "Error " + itos(id) + ": " + String(messageBuffer, size);
String msg = "Error " + itos(id) + ": " + String::utf16((const char16_t *)messageBuffer, size);
LocalFree(messageBuffer);
@ -78,7 +78,7 @@ String DisplayServerWindows::get_name() const {
}
void DisplayServerWindows::alert(const String &p_alert, const String &p_title) {
MessageBoxW(nullptr, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
MessageBoxW(nullptr, (LPCWSTR)(p_alert.utf16().get_data()), (LPCWSTR)(p_title.utf16().get_data()), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
}
void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
@ -177,11 +177,12 @@ void DisplayServerWindows::clipboard_set(const String &p_text) {
}
EmptyClipboard();
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType));
Char16String utf16 = text.utf16();
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (utf16.length() + 1) * sizeof(WCHAR));
ERR_FAIL_COND_MSG(mem == nullptr, "Unable to allocate memory for clipboard contents.");
LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType));
memcpy(lptstrCopy, utf16.get_data(), (utf16.length() + 1) * sizeof(WCHAR));
GlobalUnlock(mem);
SetClipboardData(CF_UNICODETEXT, mem);
@ -218,7 +219,7 @@ String DisplayServerWindows::clipboard_get() const {
if (mem != nullptr) {
LPWSTR ptr = (LPWSTR)GlobalLock(mem);
if (ptr != nullptr) {
ret = String((CharType *)ptr);
ret = String::utf16((const char16_t *)ptr);
GlobalUnlock(mem);
};
};
@ -593,7 +594,7 @@ void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_wi
_THREAD_SAFE_METHOD_
ERR_FAIL_COND(!windows.has(p_window));
SetWindowTextW(windows[p_window].hWnd, p_title.c_str());
SetWindowTextW(windows[p_window].hWnd, (LPCWSTR)(p_title.utf16().get_data()));
}
int DisplayServerWindows::window_get_current_screen(WindowID p_window) const {
@ -1423,13 +1424,13 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const {
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
GetKeyboardLayoutList(layout_count, layouts);
wchar_t buf[LOCALE_NAME_MAX_LENGTH];
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t));
WCHAR buf[LOCALE_NAME_MAX_LENGTH];
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(WCHAR));
LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
memfree(layouts);
return String(buf).substr(0, 2);
return String::utf16((const char16_t *)buf).substr(0, 2);
}
String _get_full_layout_name_from_registry(HKL p_layout) {
@ -1437,17 +1438,17 @@ String _get_full_layout_name_from_registry(HKL p_layout) {
String ret;
HKEY hkey;
wchar_t layout_text[1024];
memset(layout_text, 0, 1024 * sizeof(wchar_t));
WCHAR layout_text[1024];
memset(layout_text, 0, 1024 * sizeof(WCHAR));
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)id.c_str(), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) {
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)(id.utf16().get_data()), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) {
return ret;
}
DWORD buffer = 1024;
DWORD vtype = REG_SZ;
if (RegQueryValueExW(hkey, L"Layout Text", NULL, &vtype, (LPBYTE)layout_text, &buffer) == ERROR_SUCCESS) {
ret = String(layout_text);
ret = String::utf16((const char16_t *)layout_text);
}
RegCloseKey(hkey);
return ret;
@ -1463,15 +1464,15 @@ String DisplayServerWindows::keyboard_get_layout_name(int p_index) const {
String ret = _get_full_layout_name_from_registry(layouts[p_index]); // Try reading full name from Windows registry, fallback to locale name if failed (e.g. on Wine).
if (ret == String()) {
wchar_t buf[LOCALE_NAME_MAX_LENGTH];
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t));
WCHAR buf[LOCALE_NAME_MAX_LENGTH];
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(WCHAR));
LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
wchar_t name[1024];
memset(name, 0, 1024 * sizeof(wchar_t));
WCHAR name[1024];
memset(name, 0, 1024 * sizeof(WCHAR));
GetLocaleInfoEx(buf, LOCALE_SLOCALIZEDDISPLAYNAME, (LPWSTR)&name, 1024);
ret = String(name);
ret = String::utf16((const char16_t *)name);
}
memfree(layouts);
@ -2711,7 +2712,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_DROPFILES: {
HDROP hDropInfo = (HDROP)wParam;
const int buffsize = 4096;
wchar_t buf[buffsize];
WCHAR buf[buffsize];
int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0);
@ -2719,7 +2720,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
for (int i = 0; i < fcount; i++) {
DragQueryFileW(hDropInfo, i, buf, buffsize);
String file = buf;
String file = String::utf16((const char16_t *)buf);
files.push_back(file);
}

View file

@ -84,7 +84,7 @@ static String format_error_message(DWORD id) {
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr);
String msg = "Error " + itos(id) + ": " + String(messageBuffer, size);
String msg = "Error " + itos(id) + ": " + String::utf16((const char16_t *)messageBuffer, size);
LocalFree(messageBuffer);
@ -107,15 +107,11 @@ void RedirectIOToConsole() {
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
&coninfo);
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
coninfo.dwSize);
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
@ -265,10 +261,10 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
DLL_DIRECTORY_COOKIE cookie = nullptr;
if (p_also_set_library_path && has_dll_directory_api) {
cookie = add_dll_directory(path.get_base_dir().c_str());
cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data()));
}
p_library_handle = (void *)LoadLibraryExW(path.c_str(), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0);
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + format_error_message(GetLastError()) + ".");
if (cookie) {
@ -407,7 +403,7 @@ uint64_t OS_Windows::get_ticks_usec() const {
String OS_Windows::_quote_command_line_argument(const String &p_text) const {
for (int i = 0; i < p_text.size(); i++) {
CharType c = p_text[i];
char32_t c = p_text[i];
if (c == ' ' || c == '&' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '=' || c == ';' || c == '!' || c == '\'' || c == '+' || c == ',' || c == '`' || c == '~') {
return "\"" + p_text + "\"";
}
@ -428,7 +424,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
// Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
argss = _quote_command_line_argument(argss);
FILE *f = _wpopen(argss.c_str(), L"r");
FILE *f = _wpopen((LPCWSTR)(argss.utf16().get_data()), L"r");
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
char buf[65535];
@ -463,13 +459,8 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
ZeroMemory(&pi.pi, sizeof(pi.pi));
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
Vector<CharType> modstr; // Windows wants to change this no idea why.
modstr.resize(cmdline.size());
for (int i = 0; i < cmdline.size(); i++) {
modstr.write[i] = cmdline[i];
}
int ret = CreateProcessW(nullptr, modstr.ptrw(), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why.
int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
if (p_blocking) {
@ -509,26 +500,26 @@ int OS_Windows::get_process_id() const {
}
Error OS_Windows::set_cwd(const String &p_cwd) {
if (_wchdir(p_cwd.c_str()) != 0)
if (_wchdir((LPCWSTR)(p_cwd.utf16().get_data())) != 0)
return ERR_CANT_OPEN;
return OK;
}
String OS_Windows::get_executable_path() const {
wchar_t bufname[4096];
WCHAR bufname[4096];
GetModuleFileNameW(nullptr, bufname, 4096);
String s = bufname;
String s = String::utf16((const char16_t *)bufname);
return s;
}
bool OS_Windows::has_environment(const String &p_var) const {
#ifdef MINGW_ENABLED
return _wgetenv(p_var.c_str()) != nullptr;
return _wgetenv((LPCWSTR)(p_var.utf16().get_data())) != nullptr;
#else
wchar_t *env;
WCHAR *env;
size_t len;
_wdupenv_s(&env, &len, p_var.c_str());
_wdupenv_s(&env, &len, (LPCWSTR)(p_var.utf16().get_data()));
const bool has_env = env != nullptr;
free(env);
return has_env;
@ -536,16 +527,16 @@ bool OS_Windows::has_environment(const String &p_var) const {
};
String OS_Windows::get_environment(const String &p_var) const {
wchar_t wval[0x7Fff]; // MSDN says 32767 char is the maximum
int wlen = GetEnvironmentVariableW(p_var.c_str(), wval, 0x7Fff);
WCHAR wval[0x7fff]; // MSDN says 32767 char is the maximum
int wlen = GetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), wval, 0x7fff);
if (wlen > 0) {
return wval;
return String::utf16((const char16_t *)wval);
}
return "";
}
bool OS_Windows::set_environment(const String &p_var, const String &p_value) const {
return (bool)SetEnvironmentVariableW(p_var.c_str(), p_value.c_str());
return (bool)SetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), (LPCWSTR)(p_value.utf16().get_data()));
}
String OS_Windows::get_stdin_string(bool p_block) {
@ -558,7 +549,7 @@ String OS_Windows::get_stdin_string(bool p_block) {
}
Error OS_Windows::shell_open(String p_uri) {
ShellExecuteW(nullptr, nullptr, p_uri.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
ShellExecuteW(nullptr, nullptr, (LPCWSTR)(p_uri.utf16().get_data()), nullptr, nullptr, SW_SHOWNORMAL);
return OK;
}
@ -701,7 +692,7 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
PWSTR szPath;
HRESULT res = SHGetKnownFolderPath(id, 0, nullptr, &szPath);
ERR_FAIL_COND_V(res != S_OK, String());
String path = String(szPath);
String path = String::utf16((const char16_t *)szPath);
CoTaskMemFree(szPath);
return path;
}
@ -727,7 +718,7 @@ String OS_Windows::get_user_data_dir() const {
String OS_Windows::get_unique_id() const {
HW_PROFILE_INFO HwProfInfo;
ERR_FAIL_COND_V(!GetCurrentHwProfile(&HwProfInfo), "");
return String(HwProfInfo.szHwProfileGuid);
return String::utf16((const char16_t *)(HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN);
}
bool OS_Windows::_check_internal_feature_support(const String &p_feature) {
@ -744,9 +735,11 @@ bool OS_Windows::is_disable_crash_handler() const {
Error OS_Windows::move_to_trash(const String &p_path) {
SHFILEOPSTRUCTW sf;
WCHAR *from = new WCHAR[p_path.length() + 2];
wcscpy_s(from, p_path.length() + 1, p_path.c_str());
from[p_path.length() + 1] = 0;
Char16String utf16 = p_path.utf16();
WCHAR *from = new WCHAR[utf16.length() + 2];
wcscpy_s(from, utf16.length() + 1, (LPCWSTR)(utf16.get_data()));
from[utf16.length() + 1] = 0;
sf.hwnd = main_window;
sf.wFunc = FO_DELETE;

View file

@ -235,8 +235,8 @@ void Label::_notification(int p_what) {
float x_ofs_shadow = x_ofs;
for (int i = 0; i < from->word_len; i++) {
if (visible_chars < 0 || chars_total_shadow < visible_chars) {
CharType c = xl_text[i + pos];
CharType n = xl_text[i + pos + 1];
char32_t c = xl_text[i + pos];
char32_t n = xl_text[i + pos + 1];
if (uppercase) {
c = String::char_uppercase(c);
n = String::char_uppercase(n);
@ -255,8 +255,8 @@ void Label::_notification(int p_what) {
}
for (int i = 0; i < from->word_len; i++) {
if (visible_chars < 0 || chars_total < visible_chars) {
CharType c = xl_text[i + pos];
CharType n = xl_text[i + pos + 1];
char32_t c = xl_text[i + pos];
char32_t n = xl_text[i + pos + 1];
if (uppercase) {
c = String::char_uppercase(c);
n = String::char_uppercase(n);
@ -308,7 +308,7 @@ int Label::get_longest_line_width() const {
real_t line_width = 0;
for (int i = 0; i < xl_text.size(); i++) {
CharType current = xl_text[i];
char32_t current = xl_text[i];
if (uppercase) {
current = String::char_uppercase(current);
}
@ -390,7 +390,7 @@ void Label::regenerate_word_cache() {
WordCache *last = nullptr;
for (int i = 0; i <= xl_text.length(); i++) {
CharType current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works
char32_t current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works
if (uppercase) {
current = String::char_uppercase(current);

View file

@ -42,7 +42,7 @@
#include "editor/editor_settings.h"
#endif
#include "scene/main/window.h"
static bool _is_text_char(CharType c) {
static bool _is_text_char(char32_t c) {
return !is_symbol(c);
}
@ -582,7 +582,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (k->get_unicode() >= 32 && k->get_keycode() != KEY_DELETE) {
if (editable) {
selection_delete();
CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 };
char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 };
int prev_len = text.length();
append_at_cursor(ucodestr);
if (text.length() != prev_len) {
@ -807,8 +807,8 @@ void LineEdit::_notification(int p_what) {
break;
}
CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
int im_char_width = font->get_char_size(cchar, next).width;
if ((x_ofs + im_char_width) > ofs_max) {
@ -830,8 +830,8 @@ void LineEdit::_notification(int p_what) {
}
}
CharType cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs];
CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1];
char32_t cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs];
char32_t next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1];
int char_width = font->get_char_size(cchar, next).width;
// End of widget, break.
@ -870,8 +870,8 @@ void LineEdit::_notification(int p_what) {
break;
}
CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
int im_char_width = font->get_char_size(cchar, next).width;
if ((x_ofs + im_char_width) > ofs_max) {

View file

@ -59,7 +59,7 @@ public:
bool visibility;
Point2 offset;
Color color;
CharType character;
char32_t character;
float elapsed_time;
Dictionary environment;
@ -79,7 +79,7 @@ public:
Color get_color() { return color; }
void set_color(Color p_color) { color = p_color; }
int get_character() { return (int)character; }
void set_character(int p_char) { character = (CharType)p_char; }
void set_character(int p_char) { character = (char32_t)p_char; }
Dictionary get_environment() { return environment; }
void set_environment(Dictionary p_environment) { environment = p_environment; }
};

View file

@ -354,8 +354,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
font = p_base_font;
}
const CharType *c = text->text.c_str();
const CharType *cf = c;
const char32_t *c = text->text.get_data();
const char32_t *cf = c;
int ascent = font->get_ascent();
int descent = font->get_descent();
@ -461,7 +461,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
bool selected = false;
Color fx_color = Color(color);
Point2 fx_offset;
CharType fx_char = c[i];
char32_t fx_char = c[i];
if (selection.active) {
int cofs = (&c[i]) - cf;

View file

@ -44,23 +44,23 @@
#define TAB_PIXELS
inline bool _is_symbol(CharType c) {
inline bool _is_symbol(char32_t c) {
return is_symbol(c);
}
static bool _is_text_char(CharType c) {
static bool _is_text_char(char32_t c) {
return !is_symbol(c);
}
static bool _is_whitespace(CharType c) {
static bool _is_whitespace(char32_t c) {
return c == '\t' || c == ' ';
}
static bool _is_char(CharType c) {
static bool _is_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
static bool _is_pair_right_symbol(CharType c) {
static bool _is_pair_right_symbol(char32_t c) {
return c == '"' ||
c == '\'' ||
c == ')' ||
@ -68,7 +68,7 @@ static bool _is_pair_right_symbol(CharType c) {
c == '}';
}
static bool _is_pair_left_symbol(CharType c) {
static bool _is_pair_left_symbol(char32_t c) {
return c == '"' ||
c == '\'' ||
c == '(' ||
@ -76,11 +76,11 @@ static bool _is_pair_left_symbol(CharType c) {
c == '{';
}
static bool _is_pair_symbol(CharType c) {
static bool _is_pair_symbol(char32_t c) {
return _is_pair_left_symbol(c) || _is_pair_right_symbol(c);
}
static CharType _get_right_pair_symbol(CharType c) {
static char32_t _get_right_pair_symbol(char32_t c) {
if (c == '"') {
return '"';
}
@ -119,7 +119,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const {
int w = 0;
int len = text[p_line].data.length();
const CharType *str = text[p_line].data.c_str();
const char32_t *str = text[p_line].data.get_data();
// Update width.
@ -214,7 +214,7 @@ void TextEdit::Text::remove(int p_at) {
text.remove(p_at);
}
int TextEdit::Text::get_char_width(CharType c, CharType next_c, int px) const {
int TextEdit::Text::get_char_width(char32_t c, char32_t next_c, int px) const {
int tab_w = font->get_char_size(' ').width * indent_size;
int w = 0;
@ -654,8 +654,8 @@ void TextEdit::_notification(int p_what) {
if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
if (cursor.column < text[cursor.line].length()) {
// Check for open.
CharType c = text[cursor.line][cursor.column];
CharType closec = 0;
char32_t c = text[cursor.line][cursor.column];
char32_t closec = 0;
if (c == '[') {
closec = ']';
@ -671,10 +671,10 @@ void TextEdit::_notification(int p_what) {
for (int i = cursor.line; i < text.size(); i++) {
int from = i == cursor.line ? cursor.column + 1 : 0;
for (int j = from; j < text[i].length(); j++) {
CharType cc = text[i][j];
char32_t cc = text[i][j];
// Ignore any brackets inside a string.
if (cc == '"' || cc == '\'') {
CharType quotation = cc;
char32_t quotation = cc;
do {
j++;
if (!(j < text[i].length())) {
@ -720,8 +720,8 @@ void TextEdit::_notification(int p_what) {
}
if (cursor.column > 0) {
CharType c = text[cursor.line][cursor.column - 1];
CharType closec = 0;
char32_t c = text[cursor.line][cursor.column - 1];
char32_t closec = 0;
if (c == ']') {
closec = '[';
@ -737,10 +737,10 @@ void TextEdit::_notification(int p_what) {
for (int i = cursor.line; i >= 0; i--) {
int from = i == cursor.line ? cursor.column - 2 : text[i].length() - 1;
for (int j = from; j >= 0; j--) {
CharType cc = text[i][j];
char32_t cc = text[i][j];
// Ignore any brackets inside a string.
if (cc == '"' || cc == '\'') {
CharType quotation = cc;
char32_t quotation = cc;
do {
j--;
if (!(j >= 0)) {
@ -1303,8 +1303,8 @@ void TextEdit::_notification(int p_what) {
break;
}
CharType cchar = ime_text[ofs];
CharType next = ime_text[ofs + 1];
char32_t cchar = ime_text[ofs];
char32_t next = ime_text[ofs + 1];
int im_char_width = cache.font->get_char_size(cchar, next).width;
if ((char_ofs + char_margin + im_char_width) >= xmargin_end) {
@ -1399,8 +1399,8 @@ void TextEdit::_notification(int p_what) {
break;
}
CharType cchar = ime_text[ofs];
CharType next = ime_text[ofs + 1];
char32_t cchar = ime_text[ofs];
char32_t next = ime_text[ofs + 1];
int im_char_width = cache.font->get_char_size(cchar, next).width;
if ((char_ofs + char_margin + im_char_width) >= xmargin_end) {
@ -1661,12 +1661,12 @@ void TextEdit::_notification(int p_what) {
}
}
void TextEdit::_consume_pair_symbol(CharType ch) {
void TextEdit::_consume_pair_symbol(char32_t ch) {
int cursor_position_to_move = cursor_get_column() + 1;
CharType ch_single[2] = { ch, 0 };
CharType ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 };
CharType ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 };
char32_t ch_single[2] = { ch, 0 };
char32_t ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 };
char32_t ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 };
if (is_selection_active()) {
int new_column, new_line;
@ -1771,8 +1771,8 @@ void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column
bool remove_right_symbol = false;
if (cursor.column < text[cursor.line].length() && cursor.column > 0) {
CharType left_char = text[cursor.line][cursor.column - 1];
CharType right_char = text[cursor.line][cursor.column];
char32_t left_char = text[cursor.line][cursor.column - 1];
char32_t right_char = text[cursor.line][cursor.column];
if (right_char == _get_right_pair_symbol(left_char)) {
remove_right_symbol = true;
@ -2540,7 +2540,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_unicode() > 32) {
_reset_caret_blink_timer();
const CharType chr[2] = { (CharType)k->get_unicode(), 0 };
const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 };
if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
_consume_pair_symbol(chr[0]);
} else {
@ -2784,7 +2784,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
// No need to move the brace below if we are not taking the text with us.
char closing_char = _get_right_pair_symbol(indent_char);
char32_t closing_char = _get_right_pair_symbol(indent_char);
if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column]) && !k->get_command()) {
brace_indent = true;
ins += "\n" + ins.substr(1, ins.length() - 2);
@ -3312,7 +3312,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// Compute whitespace symbols seq length.
int current_line_whitespace_len = 0;
while (current_line_whitespace_len < text[cursor.line].length()) {
CharType c = text[cursor.line][current_line_whitespace_len];
char32_t c = text[cursor.line][current_line_whitespace_len];
if (c != '\t' && c != ' ') {
break;
}
@ -3458,7 +3458,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
int current_line_whitespace_len = 0;
while (current_line_whitespace_len < text[cursor.line].length()) {
CharType c = text[cursor.line][current_line_whitespace_len];
char32_t c = text[cursor.line][current_line_whitespace_len];
if (c != '\t' && c != ' ')
break;
current_line_whitespace_len++;
@ -3624,7 +3624,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
const CharType chr[2] = { (CharType)k->get_unicode(), 0 };
const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 };
if (completion_hint != "" && k->get_unicode() == ')') {
completion_hint = "";
@ -4251,7 +4251,7 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const {
}
while (col < line_text.length()) {
CharType c = line_text[col];
char32_t c = line_text[col];
int w = text.get_char_width(c, line_text[col + 1], px + word_px);
int indent_ofs = (cur_wrap_index != 0 ? tab_offset_px : 0);
@ -6115,9 +6115,9 @@ void TextEdit::_confirm_completion() {
// When inserted into the middle of an existing string/method, don't add an unnecessary quote/bracket.
String line = text[cursor.line];
CharType next_char = line[cursor.column];
CharType last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1];
CharType last_completion_char_display = completion_current.display[completion_current.display.length() - 1];
char32_t next_char = line[cursor.column];
char32_t last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1];
char32_t last_completion_char_display = completion_current.display[completion_current.display.length() - 1];
if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) {
_remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
@ -6161,7 +6161,7 @@ void TextEdit::_cancel_completion() {
update();
}
static bool _is_completable(CharType c) {
static bool _is_completable(char32_t c) {
return !_is_symbol(c) || c == '"' || c == '\'';
}
@ -6292,14 +6292,14 @@ void TextEdit::_update_completion_candidates() {
String display_lower = option.display.to_lower();
const CharType *ssq = &s[0];
const CharType *ssq_lower = &s_lower[0];
const char32_t *ssq = &s[0];
const char32_t *ssq_lower = &s_lower[0];
const CharType *tgt = &option.display[0];
const CharType *tgt_lower = &display_lower[0];
const char32_t *tgt = &option.display[0];
const char32_t *tgt_lower = &display_lower[0];
const CharType *ssq_last_tgt = nullptr;
const CharType *ssq_lower_last_tgt = nullptr;
const char32_t *ssq_last_tgt = nullptr;
const char32_t *ssq_lower_last_tgt = nullptr;
for (; *tgt; tgt++, tgt_lower++) {
if (*ssq == *tgt) {
@ -6416,7 +6416,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const {
int beg, end;
if (select_word(s, col, beg, end)) {
bool inside_quotes = false;
CharType selected_quote = '\0';
char32_t selected_quote = '\0';
int qbegin = 0, qend = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == '"' || s[i] == '\'') {

View file

@ -79,7 +79,7 @@ public:
void set_font(const Ref<Font> &p_font);
int get_line_width(int p_line) const;
int get_max_width(bool p_exclude_hidden = false) const;
int get_char_width(CharType c, CharType next_c, int px) const;
int get_char_width(char32_t c, char32_t next_c, int px) const;
void set_line_wrap_amount(int p_line, int p_wrap_amount) const;
int get_line_wrap_amount(int p_line) const;
void set(int p_line, const String &p_text);
@ -488,7 +488,7 @@ protected:
void _gui_input(const Ref<InputEvent> &p_gui_input);
void _notification(int p_what);
void _consume_pair_symbol(CharType ch);
void _consume_pair_symbol(char32_t ch);
void _consume_backspace_for_pair_symbol(int prev_line, int prev_column);
static void _bind_methods();

View file

@ -939,9 +939,9 @@ float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const
ERR_FAIL_COND_V(p_font.is_null(), 0);
if (p_font->has_outline()) {
p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], Color(1, 1, 1), true);
p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], Color(1, 1, 1), true);
}
return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], p_modulate);
return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], p_modulate);
}
void CanvasItem::_notify_transform(CanvasItem *p_node) {

View file

@ -1094,7 +1094,7 @@ String increase_numeric_string(const String &s) {
if (!carry) {
break;
}
CharType n = s[i];
char32_t n = s[i];
if (n == '9') { // keep carry as true: 9 + 1
res[i] = '0';
} else {
@ -1155,7 +1155,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co
String name_string = name;
String nums;
for (int i = name_string.length() - 1; i >= 0; i--) {
CharType n = name_string[i];
char32_t n = name_string[i];
if (n >= '0' && n <= '9') {
nums = String::chr(name_string[i]) + nums;
} else {

View file

@ -239,7 +239,7 @@ float DynamicFontAtSize::get_underline_thickness() const {
return underline_thickness;
}
const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
const Character *chr = char_map.getptr(p_char);
ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(nullptr, nullptr)));
@ -271,7 +271,7 @@ const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFon
return Pair<const Character *, DynamicFontAtSize *>(chr, const_cast<DynamicFontAtSize *>(this));
}
Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
Size2 DynamicFontAtSize::get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Size2(1, 1);
}
@ -297,7 +297,7 @@ String DynamicFontAtSize::get_available_chars() const {
FT_ULong charcode = FT_Get_First_Char(face, &gindex);
while (gindex != 0) {
if (charcode != 0) {
chars += CharType(charcode);
chars += char32_t(charcode);
}
charcode = FT_Get_Next_Char(face, charcode, &gindex);
}
@ -305,7 +305,7 @@ String DynamicFontAtSize::get_available_chars() const {
return chars;
}
float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const {
float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const {
if (!valid) {
return 0;
}
@ -560,7 +560,7 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b
return chr;
}
DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(CharType p_char) {
DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(char32_t p_char) {
Character ret = Character::not_found();
if (FT_Load_Char(face, p_char, FT_LOAD_NO_BITMAP | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)) != 0) {
@ -596,7 +596,7 @@ cleanup_stroker:
return ret;
}
void DynamicFontAtSize::_update_char(CharType p_char) {
void DynamicFontAtSize::_update_char(char32_t p_char) {
if (char_map.has(p_char)) {
return;
}
@ -849,7 +849,7 @@ float DynamicFont::get_underline_thickness() const {
return data_at_size->get_underline_thickness();
}
Size2 DynamicFont::get_char_size(CharType p_char, CharType p_next) const {
Size2 DynamicFont::get_char_size(char32_t p_char, char32_t p_next) const {
if (!data_at_size.is_valid()) {
return Size2(1, 1);
}
@ -891,7 +891,7 @@ bool DynamicFont::has_outline() const {
return outline_cache_id.outline_size > 0;
}
float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const {
float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const {
const Ref<DynamicFontAtSize> &font_at_size = p_outline && outline_cache_id.outline_size > 0 ? outline_data_at_size : data_at_size;
if (!font_at_size.is_valid()) {

View file

@ -159,17 +159,17 @@ class DynamicFontAtSize : public Reference {
int y;
};
const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Character _make_outline_char(CharType p_char);
const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Character _make_outline_char(char32_t p_char);
TexturePosition _find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height);
Character _bitmap_to_character(FT_Bitmap bitmap, int yofs, int xofs, float advance);
static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count);
static void _ft_stream_close(FT_Stream stream);
HashMap<CharType, Character> char_map;
HashMap<char32_t, Character> char_map;
_FORCE_INLINE_ void _update_char(CharType p_char);
_FORCE_INLINE_ void _update_char(char32_t p_char);
friend class DynamicFontData;
Ref<DynamicFontData> font;
@ -188,10 +188,10 @@ public:
float get_underline_position() const;
float get_underline_thickness() const;
Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Size2 get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
String get_available_chars() const;
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const;
float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const;
void set_texture_flags(uint32_t p_flags);
void update_oversampling();
@ -277,14 +277,14 @@ public:
virtual float get_underline_position() const override;
virtual float get_underline_thickness() const override;
virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const override;
virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override;
String get_available_chars() const;
virtual bool is_distance_field_hint() const override;
virtual bool has_outline() const override;
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override;
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override;
SelfList<DynamicFont> font_list;

View file

@ -125,7 +125,7 @@ void BitmapFont::_set_chars(const Vector<int> &p_chars) {
Vector<int> BitmapFont::_get_chars() const {
Vector<int> chars;
const CharType *key = nullptr;
const char32_t *key = nullptr;
while ((key = char_map.next(key))) {
const Character *c = char_map.getptr(*key);
@ -272,7 +272,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) {
}
}
} else if (type == "char") {
CharType idx = 0;
char32_t idx = 0;
if (keys.has("id")) {
idx = keys["id"].to_int();
}
@ -313,7 +313,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) {
add_char(idx, texture, rect, ofs, advance);
} else if (type == "kerning") {
CharType first = 0, second = 0;
char32_t first = 0, second = 0;
int k = 0;
if (keys.has("first")) {
@ -385,10 +385,10 @@ int BitmapFont::get_character_count() const {
return char_map.size();
};
Vector<CharType> BitmapFont::get_char_keys() const {
Vector<CharType> chars;
Vector<char32_t> BitmapFont::get_char_keys() const {
Vector<char32_t> chars;
chars.resize(char_map.size());
const CharType *ct = nullptr;
const char32_t *ct = nullptr;
int count = 0;
while ((ct = char_map.next(ct))) {
chars.write[count++] = *ct;
@ -397,7 +397,7 @@ Vector<CharType> BitmapFont::get_char_keys() const {
return chars;
};
BitmapFont::Character BitmapFont::get_character(CharType p_char) const {
BitmapFont::Character BitmapFont::get_character(char32_t p_char) const {
if (!char_map.has(p_char)) {
ERR_FAIL_V(Character());
};
@ -405,7 +405,7 @@ BitmapFont::Character BitmapFont::get_character(CharType p_char) const {
return char_map[p_char];
};
void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
void BitmapFont::add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) {
if (p_advance < 0) {
p_advance = p_rect.size.width;
}
@ -420,7 +420,7 @@ void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rec
char_map[p_char] = c;
}
void BitmapFont::add_kerning_pair(CharType p_A, CharType p_B, int p_kerning) {
void BitmapFont::add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) {
KerningPairKey kpk;
kpk.A = p_A;
kpk.B = p_B;
@ -444,7 +444,7 @@ Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const {
return ret;
}
int BitmapFont::get_kerning_pair(CharType p_A, CharType p_B) const {
int BitmapFont::get_kerning_pair(char32_t p_A, char32_t p_B) const {
KerningPairKey kpk;
kpk.A = p_A;
kpk.B = p_B;
@ -482,7 +482,7 @@ Size2 Font::get_string_size(const String &p_string) const {
if (l == 0) {
return Size2(0, get_height());
}
const CharType *sptr = &p_string[0];
const char32_t *sptr = &p_string[0];
for (int i = 0; i < l; i++) {
w += get_char_size(sptr[i], sptr[i + 1]).width;
@ -534,7 +534,7 @@ Ref<BitmapFont> BitmapFont::get_fallback() const {
return fallback;
}
float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const {
float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const {
const Character *c = char_map.getptr(p_char);
if (!c) {
@ -556,7 +556,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c
return get_char_size(p_char, p_next).width;
}
Size2 BitmapFont::get_char_size(CharType p_char, CharType p_next) const {
Size2 BitmapFont::get_char_size(char32_t p_char, char32_t p_next) const {
const Character *c = char_map.getptr(p_char);
if (!c) {

View file

@ -49,7 +49,7 @@ public:
virtual float get_underline_position() const = 0;
virtual float get_underline_thickness() const = 0;
virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const = 0;
virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const = 0;
Size2 get_string_size(const String &p_string) const;
Size2 get_wordwrap_string_size(const String &p_string, float p_width) const;
@ -59,7 +59,7 @@ public:
void draw_halign(RID p_canvas_item, const Point2 &p_pos, HAlign p_align, float p_width, const String &p_text, const Color &p_modulate = Color(1, 1, 1), const Color &p_outline_modulate = Color(1, 1, 1)) const;
virtual bool has_outline() const { return false; }
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0;
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0;
void update_changes();
Font();
@ -74,8 +74,8 @@ class FontDrawer {
struct PendingDraw {
RID canvas_item;
Point2 pos;
CharType chr;
CharType next;
char32_t chr;
char32_t next;
Color modulate;
};
@ -88,7 +88,7 @@ public:
has_outline = p_font->has_outline();
}
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1)) {
float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1)) {
if (has_outline) {
PendingDraw draw = { p_canvas_item, p_pos, p_char, p_next, p_modulate };
pending_draws.push_back(draw);
@ -137,7 +137,7 @@ public:
};
private:
HashMap<CharType, Character> char_map;
HashMap<char32_t, Character> char_map;
Map<KerningPairKey, int> kerning_map;
float height;
@ -169,20 +169,20 @@ public:
float get_underline_thickness() const override;
void add_texture(const Ref<Texture2D> &p_texture);
void add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1);
void add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1);
int get_character_count() const;
Vector<CharType> get_char_keys() const;
Character get_character(CharType p_char) const;
Vector<char32_t> get_char_keys() const;
Character get_character(char32_t p_char) const;
int get_texture_count() const;
Ref<Texture2D> get_texture(int p_idx) const;
void add_kerning_pair(CharType p_A, CharType p_B, int p_kerning);
int get_kerning_pair(CharType p_A, CharType p_B) const;
void add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning);
int get_kerning_pair(char32_t p_A, char32_t p_B) const;
Vector<KerningPairKey> get_kerning_pair_keys() const;
Size2 get_char_size(CharType p_char, CharType p_next = 0) const override;
Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override;
void set_fallback(const Ref<BitmapFont> &p_fallback);
Ref<BitmapFont> get_fallback() const;
@ -192,7 +192,7 @@ public:
void set_distance_field_hint(bool p_distance_field);
bool is_distance_field_hint() const override;
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override;
float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override;
BitmapFont();
~BitmapFont();

View file

@ -125,11 +125,11 @@ void SyntaxHighlighter::_bind_methods() {
////////////////////////////////////////////////////////////////////////////////
static bool _is_char(CharType c) {
static bool _is_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
static bool _is_hex_symbol(CharType c) {
static bool _is_hex_symbol(char32_t c) {
return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}
@ -195,7 +195,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) {
/* search the line */
bool match = true;
const CharType *start_key = color_regions[c].start_key.c_str();
const char32_t *start_key = color_regions[c].start_key.get_data();
for (int k = 0; k < start_key_length; k++) {
if (start_key[k] != str[from + k]) {
match = false;
@ -232,7 +232,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) {
/* search the line */
int region_end_index = -1;
int end_key_length = color_regions[in_region].end_key.length();
const CharType *end_key = color_regions[in_region].end_key.c_str();
const char32_t *end_key = color_regions[in_region].end_key.get_data();
for (; from < line_length; from++) {
if (line_length - from < end_key_length) {
break;

View file

@ -40,7 +40,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
if (slash == -1) {
return false;
}
int id = String::to_int(n.c_str(), slash);
int id = String::to_int(n.get_data(), slash);
if (!tile_map.has(id)) {
create_tile(id);
@ -216,7 +216,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
if (slash == -1) {
return false;
}
int id = String::to_int(n.c_str(), slash);
int id = String::to_int(n.get_data(), slash);
ERR_FAIL_COND_V(!tile_map.has(id), false);

View file

@ -33,15 +33,15 @@
#include "core/print_string.h"
#include "servers/rendering_server.h"
static bool _is_text_char(CharType c) {
static bool _is_text_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
static bool _is_number(CharType c) {
static bool _is_number(char32_t c) {
return (c >= '0' && c <= '9');
}
static bool _is_hex(CharType c) {
static bool _is_hex(char32_t c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
@ -334,7 +334,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
};
ShaderLanguage::Token ShaderLanguage::_get_token() {
#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : CharType(0))
#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : char32_t(0))
while (true) {
char_idx++;
@ -582,11 +582,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
break;
}
str += CharType(GETCHAR(i));
str += char32_t(GETCHAR(i));
i++;
}
CharType last_char = str[str.length() - 1];
char32_t last_char = str[str.length() - 1];
if (hexa_found) {
//integer(hex)
@ -663,7 +663,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
String str;
while (_is_text_char(GETCHAR(0))) {
str += CharType(GETCHAR(0));
str += char32_t(GETCHAR(0));
char_idx++;
}
@ -3869,7 +3869,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
const CharType *c = ident.ptr();
const char32_t *c = ident.ptr();
for (int i = 0; i < l; i++) {
switch (c[i]) {
case 'r':
@ -3933,7 +3933,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
const CharType *c = ident.ptr();
const char32_t *c = ident.ptr();
for (int i = 0; i < l; i++) {
switch (c[i]) {
case 'r':
@ -4000,7 +4000,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
const CharType *c = ident.ptr();
const char32_t *c = ident.ptr();
for (int i = 0; i < l; i++) {
switch (c[i]) {
case 'r':
@ -7039,7 +7039,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
static int _get_first_ident_pos(const String &p_code) {
int idx = 0;
#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0))
#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : char32_t(0))
while (true) {
if (GETCHAR(0) == '/' && GETCHAR(1) == '/') {
@ -7300,7 +7300,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (j == completion_argument) {
calltip += CharType(0xFFFF);
calltip += char32_t(0xFFFF);
}
if (shader->functions[i].function->arguments[j].is_const) {
@ -7320,7 +7320,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += shader->functions[i].function->arguments[j].name;
if (j == completion_argument) {
calltip += CharType(0xFFFF);
calltip += char32_t(0xFFFF);
}
}
@ -7383,7 +7383,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (i == completion_argument) {
calltip += CharType(0xFFFF);
calltip += char32_t(0xFFFF);
}
if (out_arg >= 0 && i == out_arg) {
@ -7393,7 +7393,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += get_datatype_name(builtin_func_defs[idx].args[i]);
if (i == completion_argument) {
calltip += CharType(0xFFFF);
calltip += char32_t(0xFFFF);
}
found_arg = true;

0
servers/text_server.h Normal file
View file

View file

@ -6,6 +6,9 @@ env.tests_sources = []
env_tests = env.Clone()
# Include GDNative headers.
env_tests.Append(CPPPATH=["#modules/gdnative/include"])
# We must disable the THREAD_LOCAL entirely in doctest to prevent crashes on debugging
# Since we link with /MT thread_local is always expired when the header is used
# So the debugger crashes the engine and it causes weird errors

1985
tests/test_gdnative_string.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,7 @@
#include "test_class_db.h"
#include "test_color.h"
#include "test_expression.h"
#include "test_gdnative_string.h"
#include "test_gradient.h"
#include "test_gui.h"
#include "test_math.h"

View file

@ -162,7 +162,7 @@ class GetClassAndNamespace {
} break;
case '\'':
case '"': {
CharType begin_str = code[idx];
char32_t begin_str = code[idx];
idx++;
String tk_string = String();
while (true) {
@ -176,13 +176,13 @@ class GetClassAndNamespace {
} else if (code[idx] == '\\') {
//escaped characters...
idx++;
CharType next = code[idx];
char32_t next = code[idx];
if (next == 0) {
error_str = "Unterminated String";
error = true;
return TK_ERROR;
}
CharType res = 0;
char32_t res = 0;
switch (next) {
case 'b':
@ -241,7 +241,7 @@ class GetClassAndNamespace {
if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) {
//a number
const CharType *rptr;
const char32_t *rptr;
double number = String::to_float(&code[idx], &rptr);
idx += (rptr - &code[idx]);
value = number;

View file

@ -325,7 +325,7 @@ MainLoop *test() {
String code;
while (true) {
CharType c = fa->get_8();
char32_t c = fa->get_8();
if (fa->eof_reached()) {
break;
}

View file

@ -48,36 +48,159 @@
namespace TestString {
TEST_CASE("[String] Assign from cstr") {
String s = "Hello";
CHECK(wcscmp(s.c_str(), L"Hello") == 0);
int u32scmp(const char32_t *l, const char32_t *r) {
for (; *l == *r && *l && *r; l++, r++)
;
return *l - *r;
}
TEST_CASE("[String] Assign from string (operator=)") {
TEST_CASE("[String] Assign Latin-1 char string") {
String s = "Hello";
CHECK(u32scmp(s.get_data(), U"Hello") == 0);
}
TEST_CASE("[String] Assign from Latin-1 char string (operator=)") {
String s = "Dolly";
const String &t = s;
CHECK(wcscmp(t.c_str(), L"Dolly") == 0);
CHECK(u32scmp(t.get_data(), U"Dolly") == 0);
}
TEST_CASE("[String] Assign from c-string (copycon)") {
TEST_CASE("[String] Assign from Latin-1 char string (copycon)") {
String s("Sheep");
const String &t(s);
CHECK(wcscmp(t.c_str(), L"Sheep") == 0);
const String &t1(s);
CHECK(u32scmp(t1.get_data(), U"Sheep") == 0);
String t2 = String("Sheep", 3);
CHECK(u32scmp(t2.get_data(), U"She") == 0);
}
TEST_CASE("[String] Assign from c-widechar (operator=)") {
String s(L"Give me");
CHECK(wcscmp(s.c_str(), L"Give me") == 0);
TEST_CASE("[String] Assign from wchar_t string (operator=)") {
String s = L"Give me";
CHECK(u32scmp(s.get_data(), U"Give me") == 0);
}
TEST_CASE("[String] Assign from c-widechar (copycon)") {
TEST_CASE("[String] Assign from wchar_t string (copycon)") {
String s(L"Wool");
CHECK(wcscmp(s.c_str(), L"Wool") == 0);
CHECK(u32scmp(s.get_data(), U"Wool") == 0);
}
TEST_CASE("[String] Assign from char32_t string (operator=)") {
String s = U"Give me";
CHECK(u32scmp(s.get_data(), U"Give me") == 0);
}
TEST_CASE("[String] Assign from char32_t string (copycon)") {
String s(U"Wool");
CHECK(u32scmp(s.get_data(), U"Wool") == 0);
}
TEST_CASE("[String] UTF8") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s = u32str;
bool err = s.parse_utf8(s.utf8().get_data());
CHECK(!err);
CHECK(s == u32str);
err = s.parse_utf8((const char *)u8str);
CHECK(!err);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == s);
}
TEST_CASE("[String] UTF16") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const char16_t u16str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
String s = u32str;
bool err = s.parse_utf16(s.utf16().get_data());
CHECK(!err);
CHECK(s == u32str);
err = s.parse_utf16(u16str);
CHECK(!err);
CHECK(s == u32str);
Char16String cs = u16str;
CHECK(String::utf16(cs) == s);
}
TEST_CASE("[String] UTF8 with BOM") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s;
bool err = s.parse_utf8((const char *)u8str);
CHECK(!err);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == s);
}
TEST_CASE("[String] UTF16 with BOM") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const char16_t u16str[] = { 0xFEFF, 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
static const char16_t u16str_swap[] = { 0xFFFE, 0x2000, 0x4500, 0x4A30, 0x0F36, 0x8830, 0x4630, 0x3CD8, 0xA4DF, 0 };
String s;
bool err = s.parse_utf16(u16str);
CHECK(!err);
CHECK(s == u32str);
err = s.parse_utf16(u16str_swap);
CHECK(!err);
CHECK(s == u32str);
Char16String cs = u16str;
CHECK(String::utf16(cs) == s);
cs = u16str_swap;
CHECK(String::utf16(cs) == s);
}
TEST_CASE("[String] Invalid UTF8") {
ERR_PRINT_OFF
static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s;
bool err = s.parse_utf8((const char *)u8str);
CHECK(err);
CHECK(s == String());
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == String());
ERR_PRINT_ON
}
TEST_CASE("[String] Invalid UTF16") {
ERR_PRINT_OFF
static const char16_t u16str[] = { 0x0045, 0x304A, 0x3088, 0x3046, 0xDFA4, 0 };
String s;
bool err = s.parse_utf16(u16str);
CHECK(err);
CHECK(s == String());
Char16String cs = u16str;
CHECK(String::utf16(cs) == String());
ERR_PRINT_ON
}
TEST_CASE("[String] ASCII") {
String s = U"Primero Leche";
String t = s.ascii(false).get_data();
CHECK(s == t);
t = s.ascii(true).get_data();
CHECK(s == t);
}
TEST_CASE("[String] Comparisons (equal)") {
String s = "Test Compare";
CHECK(s == "Test Compare");
CHECK(s == U"Test Compare");
CHECK(s == L"Test Compare");
CHECK(s == String("Test Compare"));
}
@ -85,6 +208,7 @@ TEST_CASE("[String] Comparisons (equal)") {
TEST_CASE("[String] Comparisons (not equal)") {
String s = "Test Compare";
CHECK(s != "Peanut");
CHECK(s != U"Coconut");
CHECK(s != L"Coconut");
CHECK(s != String("Butter"));
}
@ -92,6 +216,7 @@ TEST_CASE("[String] Comparisons (not equal)") {
TEST_CASE("[String] Comparisons (operator <)") {
String s = "Bees";
CHECK(s < "Elephant");
CHECK(!(s < U"Amber"));
CHECK(!(s < L"Amber"));
CHECK(!(s < String("Beatrix")));
}
@ -103,7 +228,7 @@ TEST_CASE("[String] Concatenation") {
s += ' ';
s += 'a';
s += String(" ");
s = s + L"Nice";
s = s + U"Nice";
s = s + " ";
s = s + String("Day");
@ -130,34 +255,49 @@ TEST_CASE("[String] Testing for empty string") {
CHECK(String("").empty());
}
TEST_CASE("[String] Test chr") {
CHECK(String::chr('H') == "H");
CHECK(String::chr(0x3012)[0] == 0x3012);
ERR_PRINT_OFF
CHECK(String::chr(0xd812)[0] == 0xfffd); // Unpaired UTF-16 surrogate
CHECK(String::chr(0x20d812)[0] == 0xfffd); // Outside UTF-32 range
ERR_PRINT_ON
}
TEST_CASE("[String] Operator []") {
String a = "Kugar Sane";
a[0] = 'S';
a[6] = 'C';
CHECK(a == "Sugar Cane");
CHECK(a[1] == 'u');
CHECK(a.ord_at(1) == 'u');
}
TEST_CASE("[String] Case function test") {
String a = "MoMoNgA";
CHECK(a.to_upper() == "MOMONGA");
CHECK(a.to_lower() == "momonga");
}
TEST_CASE("[String] Case compare function test") {
String a = "MoMoNgA";
CHECK(a.casecmp_to("momonga") != 0);
CHECK(a.nocasecmp_to("momonga") == 0);
}
TEST_CASE("[String] UTF8") {
/* how can i embed UTF in here? */
static const CharType ustr[] = { 0x304A, 0x360F, 0x3088, 0x3046, 0 };
//static const wchar_t ustr[] = { 'P', 0xCE, 'p',0xD3, 0 };
String s = ustr;
s.parse_utf8(s.utf8().get_data());
CHECK(s == ustr);
TEST_CASE("[String] Natural compare function test") {
String a = "img2.png";
CHECK(a.nocasecmp_to("img10.png") > 0);
CHECK(a.naturalnocasecmp_to("img10.png") < 0);
}
TEST_CASE("[String] ASCII") {
String s = L"Primero Leche";
String t = s.ascii().get_data();
CHECK(s == t);
TEST_CASE("[String] hex_encode_buffer") {
static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3 };
String s = String::hex_encode_buffer(u8str, 6);
CHECK(s == U"45e3818a8fe3");
}
TEST_CASE("[String] Substr") {
@ -165,24 +305,45 @@ TEST_CASE("[String] Substr") {
CHECK(s.substr(3, 4) == "ler ");
}
TEST_CASE("[string] Find") {
String s = "Pretty Woman";
s.find("Revenge of the Monster Truck");
TEST_CASE("[String] Find") {
String s = "Pretty Woman Woman";
CHECK(s.find("tty") == 3);
CHECK(s.find("Wo", 9) == 13);
CHECK(s.find("Revenge of the Monster Truck") == -1);
CHECK(s.rfind("man") == 15);
}
TEST_CASE("[String] find no case") {
String s = "Pretty Whale";
TEST_CASE("[String] Find no case") {
String s = "Pretty Whale Whale";
CHECK(s.findn("WHA") == 7);
CHECK(s.findn("WHA", 9) == 13);
CHECK(s.findn("Revenge of the Monster SawFish") == -1);
CHECK(s.rfindn("WHA") == 13);
}
TEST_CASE("[String] Find MK") {
Vector<String> keys;
keys.push_back("sty");
keys.push_back("tty");
keys.push_back("man");
String s = "Pretty Woman";
int key = 0;
CHECK(s.findmk(keys, 0, &key) == 3);
CHECK(key == 1);
CHECK(s.findmk(keys, 5, &key) == 9);
CHECK(key == 2);
}
TEST_CASE("[String] Find and replace") {
String s = "Happy Birthday, Anna!";
s = s.replace("Birthday", "Halloween");
CHECK(s == "Happy Halloween, Anna!");
s = s.replace_first("H", "W");
CHECK(s == "Wappy Halloween, Anna!");
}
TEST_CASE("[String] Insertion") {
@ -193,6 +354,12 @@ TEST_CASE("[String] Insertion") {
TEST_CASE("[String] Number to string") {
CHECK(String::num(3.141593) == "3.141593");
CHECK(String::num(3.141593, 3) == "3.142");
CHECK(String::num_real(3.141593) == "3.141593");
CHECK(String::num_scientific(30000000) == "3e+07");
CHECK(String::num_int64(3141593) == "3141593");
CHECK(String::num_int64(0xA141593, 16) == "a141593");
CHECK(String::num_int64(0xA141593, 16, true) == "A141593");
}
TEST_CASE("[String] String to integer") {
@ -204,6 +371,18 @@ TEST_CASE("[String] String to integer") {
}
}
TEST_CASE("[String] Hex to integer") {
static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" };
static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD };
static const bool wo_prefix[4] = { false, true, true, true };
static const bool w_prefix[4] = { true, false, true, false };
for (int i = 0; i < 4; i++) {
CHECK((String(nums[i]).hex_to_int(true) == num[i]) == w_prefix[i]);
CHECK((String(nums[i]).hex_to_int(false) == num[i]) == wo_prefix[i]);
}
}
TEST_CASE("[String] String to float") {
static const char *nums[4] = { "-12348298412.2", "0.05", "2.0002", " -0.0001" };
static const double num[4] = { -12348298412.2, 0.05, 2.0002, -0.0001 };
@ -213,6 +392,11 @@ TEST_CASE("[String] String to float") {
}
}
TEST_CASE("[String] CamelCase to underscore") {
CHECK(String("TestTestStringGD").camelcase_to_underscore(false) == String("Test_Test_String_GD"));
CHECK(String("TestTestStringGD").camelcase_to_underscore(true) == String("test_test_string_gd"));
}
TEST_CASE("[String] Slicing") {
String s = "Mars,Jupiter,Saturn,Uranus";
@ -222,6 +406,69 @@ TEST_CASE("[String] Slicing") {
}
}
TEST_CASE("[String] Splitting") {
String s = "Mars,Jupiter,Saturn,Uranus";
Vector<String> l;
const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" };
const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" };
l = s.split(",", true, 2);
CHECK(l.size() == 3);
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices_l[i]);
}
l = s.rsplit(",", true, 2);
CHECK(l.size() == 3);
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices_r[i]);
}
s = "Mars Jupiter Saturn Uranus";
const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" };
l = s.split_spaces();
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices_s[i]);
}
s = "1.2;2.3 4.5";
const double slices_d[3] = { 1.2, 2.3, 4.5 };
Vector<float> f;
f = s.split_floats(";");
CHECK(f.size() == 2);
for (int i = 0; i < f.size(); i++) {
CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
}
Vector<String> keys;
keys.push_back(";");
keys.push_back(" ");
f = s.split_floats_mk(keys);
CHECK(f.size() == 3);
for (int i = 0; i < f.size(); i++) {
CHECK(ABS(f[i] - slices_d[i]) <= 0.00001);
}
s = "1;2 4";
const int slices_i[3] = { 1, 2, 4 };
Vector<int> ii;
ii = s.split_ints(";");
CHECK(ii.size() == 2);
for (int i = 0; i < ii.size(); i++) {
CHECK(ii[i] == slices_i[i]);
}
ii = s.split_ints_mk(keys);
CHECK(ii.size() == 3);
for (int i = 0; i < ii.size(); i++) {
CHECK(ii[i] == slices_i[i]);
}
}
TEST_CASE("[String] Erasing") {
String s = "Josephine is such a cute girl!";
s.erase(s.find("cute "), String("cute ").length());
@ -239,7 +486,7 @@ TEST_CASE("[String] Regex substitution") {
struct test_27_data {
char const *data;
char const *begin;
char const *part;
bool expected;
};
@ -253,9 +500,9 @@ TEST_CASE("[String] Begins with") {
bool state = true;
for (size_t i = 0; state && i < count; ++i) {
String s = tc[i].data;
state = s.begins_with(tc[i].begin) == tc[i].expected;
state = s.begins_with(tc[i].part) == tc[i].expected;
if (state) {
String sb = tc[i].begin;
String sb = tc[i].part;
state = s.begins_with(sb) == tc[i].expected;
}
CHECK(state);
@ -266,6 +513,42 @@ TEST_CASE("[String] Begins with") {
CHECK(state);
}
TEST_CASE("[String] Ends with") {
test_27_data tc[] = {
{ "res://foobar", "foobar", true },
{ "res", "res://", false },
{ "abc", "abc", true }
};
size_t count = sizeof(tc) / sizeof(tc[0]);
bool state = true;
for (size_t i = 0; state && i < count; ++i) {
String s = tc[i].data;
state = s.ends_with(tc[i].part) == tc[i].expected;
if (state) {
String sb = tc[i].part;
state = s.ends_with(sb) == tc[i].expected;
}
CHECK(state);
if (!state) {
break;
}
};
CHECK(state);
}
TEST_CASE("[String] format") {
const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\"";
Dictionary value_dictionary;
value_dictionary["red"] = 10;
value_dictionary["green"] = 20;
value_dictionary["blue"] = "bla";
value_dictionary["alpha"] = 0.4;
String value = value_format.format(value_dictionary, "$_");
CHECK(value == "red=\"10\" green=\"20\" blue=\"bla\" alpha=\"0.4\"");
}
TEST_CASE("[String] sprintf") {
String format, output;
Array args;
@ -560,6 +843,38 @@ TEST_CASE("[String] sprintf") {
CHECK(output == "%c requires number or single-character string");
}
TEST_CASE("[String] is_numeric") {
CHECK(String("12").is_numeric());
CHECK(String("1.2").is_numeric());
CHECK(!String("AF").is_numeric());
CHECK(String("-12").is_numeric());
CHECK(String("-1.2").is_numeric());
}
TEST_CASE("[String] pad") {
String s = String("test");
CHECK(s.lpad(10, "x") == U"xxxxxxtest");
CHECK(s.rpad(10, "x") == U"testxxxxxx");
s = String("10.10");
CHECK(s.pad_decimals(4) == U"10.1000");
CHECK(s.pad_zeros(4) == U"0010.10");
}
TEST_CASE("[String] is_subsequence_of") {
String a = "is subsequence of";
CHECK(String("sub").is_subsequence_of(a));
CHECK(!String("Sub").is_subsequence_of(a));
CHECK(String("Sub").is_subsequence_ofi(a));
}
TEST_CASE("[String] match") {
CHECK(String("img1.png").match("*.png"));
CHECK(!String("img1.jpeg").match("*.png"));
CHECK(!String("img1.Png").match("*.png"));
CHECK(String("img1.Png").matchn("*.png"));
}
TEST_CASE("[String] IPVX address to string") {
IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true);
@ -792,7 +1107,196 @@ TEST_CASE("[String] Count and countn functionality") {
COUNT_TEST(String("testTest-TeStatest").countn("tEsT", 4, 16) == 2);
CHECK(state);
#undef COUNT_TEST
}
TEST_CASE("[String] Bigrams") {
String s = "abcd";
Vector<String> bigr = s.bigrams();
CHECK(bigr.size() == 3);
CHECK(bigr[0] == "ab");
CHECK(bigr[1] == "bc");
CHECK(bigr[2] == "cd");
}
TEST_CASE("[String] c-escape/unescape") {
String s = "\\1\a2\b\f3\n45\r6\t7\v8\'9\?0\"";
CHECK(s.c_escape().c_unescape() == s);
}
TEST_CASE("[String] dedent") {
String s = " aaa\n bbb";
String t = "aaa\nbbb";
CHECK(s.dedent() == t);
}
TEST_CASE("[String] Path functions") {
static const char *path[4] = { "C:\\Godot\\project\\test.tscn", "/Godot/project/test.xscn", "../Godot/project/test.scn", "Godot\\test.doc" };
static const char *base_dir[4] = { "C:\\Godot\\project", "/Godot/project", "../Godot/project", "Godot" };
static const char *base_name[4] = { "C:\\Godot\\project\\test", "/Godot/project/test", "../Godot/project/test", "Godot\\test" };
static const char *ext[4] = { "tscn", "xscn", "scn", "doc" };
static const char *file[4] = { "test.tscn", "test.xscn", "test.scn", "test.doc" };
static const bool abs[4] = { true, true, false, false };
for (int i = 0; i < 4; i++) {
CHECK(String(path[i]).get_base_dir() == base_dir[i]);
CHECK(String(path[i]).get_basename() == base_name[i]);
CHECK(String(path[i]).get_extension() == ext[i]);
CHECK(String(path[i]).get_file() == file[i]);
CHECK(String(path[i]).is_abs_path() == abs[i]);
CHECK(String(path[i]).is_rel_path() != abs[i]);
CHECK(String(path[i]).simplify_path().get_base_dir().plus_file(file[i]) == String(path[i]).simplify_path());
}
static const char *file_name[3] = { "test.tscn", "test://.xscn", "?tes*t.scn" };
static const bool valid[3] = { true, false, false };
for (int i = 0; i < 3; i++) {
CHECK(String(file_name[i]).is_valid_filename() == valid[i]);
}
}
TEST_CASE("[String] hash") {
String a = "Test";
String b = "Test";
String c = "West";
CHECK(a.hash() == b.hash());
CHECK(a.hash() != c.hash());
CHECK(a.hash64() == b.hash64());
CHECK(a.hash64() != c.hash64());
}
TEST_CASE("[String] http_escape/unescape") {
String s = "Godot Engine:'docs'";
String t = "Godot%20Engine%3A%27docs%27";
CHECK(s.http_escape() == t);
CHECK(t.http_unescape() == s);
}
TEST_CASE("[String] percent_encode/decode") { // Note: is it redundant? Seems to be same as http_escape/unescape but in lower case.
String s = "Godot Engine:'docs'";
String t = "Godot%20Engine%3a%27docs%27";
CHECK(s.percent_encode() == t);
CHECK(t.percent_decode() == s);
}
TEST_CASE("[String] xml_escape/unescape") {
String s = "\"Test\" <test@test&'test'>";
CHECK(s.xml_escape(true).xml_unescape() == s);
CHECK(s.xml_escape(false).xml_unescape() == s);
}
TEST_CASE("[String] Strip escapes") {
String s = "\t\tTest Test\r\n Test";
CHECK(s.strip_escapes() == "Test Test Test");
}
TEST_CASE("[String] Similarity") {
String a = "Test";
String b = "West";
String c = "Toad";
CHECK(a.similarity(b) > a.similarity(c));
}
TEST_CASE("[String] Strip edges") {
String s = "\t Test Test ";
CHECK(s.strip_edges(true, false) == "Test Test ");
CHECK(s.strip_edges(false, true) == "\t Test Test");
CHECK(s.strip_edges(true, true) == "Test Test");
}
TEST_CASE("[String] Trim") {
String s = "aaaTestbbb";
CHECK(s.trim_prefix("aaa") == "Testbbb");
CHECK(s.trim_suffix("bbb") == "aaaTest");
CHECK(s.trim_suffix("Test") == s);
}
TEST_CASE("[String] Right/Left") {
String s = "aaaTestbbb";
// ^
CHECK(s.right(6) == "tbbb");
CHECK(s.left(6) == "aaaTes");
}
TEST_CASE("[String] Repeat") {
String s = "abababab";
String x = "ab";
String t = x.repeat(4);
CHECK(t == s);
}
TEST_CASE("[String] SHA1/SHA256/MD5") {
String s = "Godot";
String sha1 = "a1e91f39b9fce6a9998b14bdbe2aa2b39dc2d201";
static uint8_t sha1_buf[20] = {
0xA1, 0xE9, 0x1F, 0x39, 0xB9, 0xFC, 0xE6, 0xA9, 0x99, 0x8B, 0x14, 0xBD, 0xBE, 0x2A, 0xA2, 0xB3,
0x9D, 0xC2, 0xD2, 0x01
};
String sha256 = "2a02b2443f7985d89d09001086ae3dcfa6eb0f55c6ef170715d42328e16e6cb8";
static uint8_t sha256_buf[32] = {
0x2A, 0x02, 0xB2, 0x44, 0x3F, 0x79, 0x85, 0xD8, 0x9D, 0x09, 0x00, 0x10, 0x86, 0xAE, 0x3D, 0xCF,
0xA6, 0xEB, 0x0F, 0x55, 0xC6, 0xEF, 0x17, 0x07, 0x15, 0xD4, 0x23, 0x28, 0xE1, 0x6E, 0x6C, 0xB8
};
String md5 = "4a336d087aeb0390da10ee2ea7cb87f8";
static uint8_t md5_buf[16] = {
0x4A, 0x33, 0x6D, 0x08, 0x7A, 0xEB, 0x03, 0x90, 0xDA, 0x10, 0xEE, 0x2E, 0xA7, 0xCB, 0x87, 0xF8
};
PackedByteArray buf = s.sha1_buffer();
CHECK(memcmp(sha1_buf, buf.ptr(), 20) == 0);
CHECK(s.sha1_text() == sha1);
buf = s.sha256_buffer();
CHECK(memcmp(sha256_buf, buf.ptr(), 32) == 0);
CHECK(s.sha256_text() == sha256);
buf = s.md5_buffer();
CHECK(memcmp(md5_buf, buf.ptr(), 16) == 0);
CHECK(s.md5_text() == md5);
}
TEST_CASE("[String] Join") {
String s = ", ";
Vector<String> parts;
parts.push_back("One");
parts.push_back("B");
parts.push_back("C");
String t = s.join(parts);
CHECK(t == "One, B, C");
}
TEST_CASE("[String] Is_*") {
static const char *data[12] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1" };
static bool isnum[12] = { true, true, true, false, false, false, false, false, false, false, false, false };
static bool isint[12] = { true, true, false, false, false, false, false, false, false, false, false, false };
static bool ishex[12] = { true, true, false, false, true, false, true, false, true, false, false, false };
static bool ishex_p[12] = { false, false, false, false, false, false, false, true, false, false, false, false };
static bool isflt[12] = { true, true, true, false, true, true, false, false, false, false, false, false };
static bool isid[12] = { false, false, false, false, false, false, false, false, true, true, false, false };
for (int i = 0; i < 12; i++) {
String s = String(data[i]);
CHECK(s.is_numeric() == isnum[i]);
CHECK(s.is_valid_integer() == isint[i]);
CHECK(s.is_valid_hex_number(false) == ishex[i]);
CHECK(s.is_valid_hex_number(true) == ishex_p[i]);
CHECK(s.is_valid_float() == isflt[i]);
CHECK(s.is_valid_identifier() == isid[i]);
}
}
TEST_CASE("[String] humanize_size") {
CHECK(String::humanize_size(1000) == "1000 B");
CHECK(String::humanize_size(1025) == "1.00 KiB");
CHECK(String::humanize_size(1025300) == "1001.2 KiB");
CHECK(String::humanize_size(100523550) == "95.86 MiB");
CHECK(String::humanize_size(5345555000) == "4.97 GiB");
}
} // namespace TestString
#endif // TEST_STRING_H