summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorHein-Pieter van Braam <hp@tmm.cx>2019-01-04 16:01:54 +0000
committerHein-Pieter van Braam <hp@tmm.cx>2019-01-04 17:48:03 +0000
commitac99ed3cda12abe155f16a96ac0c716b2dbe6231 (patch)
tree2bae704d3f5852b415555b8393ec8eddf3b00500 /core
parent1504c961125c76f007bc2ff061c3854effbe3e56 (diff)
downloadredot-engine-ac99ed3cda12abe155f16a96ac0c716b2dbe6231.tar.gz
String[size()] should return a default constructed CharType
As per the C++ standard 21.3.4.1 for std::string: Returns: If pos < size(), returns data()[pos]. Otherwise, if pos == size(), the const version returns charT(). Otherwise, the behavior is undefined. Since the behavior is undefined Godot now does the same thing for const and non-const versions of operator[]. This fixes #21242 and fixes #22221.
Diffstat (limited to 'core')
-rw-r--r--core/ustring.cpp3
-rw-r--r--core/ustring.h20
2 files changed, 21 insertions, 2 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 23ea3f3617..0ff5cc77a4 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -58,6 +58,9 @@
#define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
#define IS_HEX_DIGIT(m_d) (((m_d) >= '0' && (m_d) <= '9') || ((m_d) >= 'a' && (m_d) <= 'f') || ((m_d) >= 'A' && (m_d) <= 'F'))
+const char CharString::_null = 0;
+const CharType String::_null = 0;
+
bool is_symbol(CharType c) {
return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' ');
}
diff --git a/core/ustring.h b/core/ustring.h
index b6cfb81e70..1773e94b0e 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -47,6 +47,7 @@ class CharProxy {
const int _index;
CowData<T> &_cowdata;
+ static const T _null = 0;
_FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &cowdata) :
_index(p_index),
@@ -54,6 +55,9 @@ class CharProxy {
public:
_FORCE_INLINE_ operator T() const {
+ if (unlikely(_index == _cowdata.size()))
+ return _null;
+
return _cowdata.get(_index);
}
@@ -73,6 +77,7 @@ public:
class CharString {
CowData<char> _cowdata;
+ static const char _null;
public:
_FORCE_INLINE_ char *ptrw() { return _cowdata.ptrw(); }
@@ -83,7 +88,12 @@ public:
_FORCE_INLINE_ char get(int p_index) { return _cowdata.get(p_index); }
_FORCE_INLINE_ const char get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const char &p_elem) { _cowdata.set(p_index, p_elem); }
- _FORCE_INLINE_ const char &operator[](int p_index) const { return _cowdata.get(p_index); }
+ _FORCE_INLINE_ const char &operator[](int p_index) const {
+ if (unlikely(p_index == _cowdata.size()))
+ return _null;
+
+ return _cowdata.get(p_index);
+ }
_FORCE_INLINE_ CharProxy<char> operator[](int p_index) { return CharProxy<char>(p_index, _cowdata); }
_FORCE_INLINE_ CharString() {}
@@ -112,6 +122,7 @@ struct StrRange {
class String {
CowData<CharType> _cowdata;
+ static const CharType _null;
void copy_from(const char *p_cstr);
void copy_from(const CharType *p_cstr, const int p_clip_to = -1);
@@ -138,7 +149,12 @@ public:
_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 { return _cowdata.get(p_index); }
+ _FORCE_INLINE_ const CharType &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); }
bool operator==(const String &p_str) const;