Skip to content

Commit

Permalink
Merge pull request godotengine#1150 from dsnopek/charstring-full
Browse files Browse the repository at this point in the history
Attempt to fully implement CharString
  • Loading branch information
dsnopek authored Jul 22, 2023
2 parents ef5a185 + 4df112c commit 3162be2
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 153 deletions.
8 changes: 7 additions & 1 deletion include/godot_cpp/templates/cowdata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
#define GODOT_COWDATA_HPP

#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/safe_refcount.hpp>

#include <cstring>
#include <new>

namespace godot {

Expand All @@ -48,6 +48,9 @@ class Vector;
template <class T, class V>
class VMap;

template <class T>
class CharStringT;

// Silence a false positive warning (see GH-52119).
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
Expand All @@ -62,6 +65,9 @@ class CowData {
template <class TV, class VV>
friend class VMap;

template <class TS>
friend class CharStringT;

private:
mutable T *_ptr = nullptr;

Expand Down
125 changes: 71 additions & 54 deletions include/godot_cpp/variant/char_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,83 +31,100 @@
#ifndef GODOT_CHAR_STRING_HPP
#define GODOT_CHAR_STRING_HPP

#include <godot_cpp/templates/cowdata.hpp>

#include <cstddef>
#include <cstdint>

namespace godot {

class CharString {
friend class String;

const char *_data = nullptr;
int _length = 0;

CharString(const char *str, int length);

public:
int length() const;
const char *get_data() const;

CharString(CharString &&p_str);
void operator=(CharString &&p_str);
CharString() {}
~CharString();
};
template <class T>
class CharStringT;

class Char16String {
friend class String;
template <class T>
class CharProxy {
template <class TS>
friend class CharStringT;

const char16_t *_data = nullptr;
int _length = 0;
const int _index;
CowData<T> &_cowdata;
static inline const T _null = 0;

Char16String(const char16_t *str, int length);
_FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
_index(p_index),
_cowdata(p_cowdata) {}

public:
int length() const;
const char16_t *get_data() const;

Char16String(Char16String &&p_str);
void operator=(Char16String &&p_str);
Char16String() {}
~Char16String();
};
_FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) :
_index(p_other._index),
_cowdata(p_other._cowdata) {}

class Char32String {
friend class String;
_FORCE_INLINE_ operator T() const {
if (unlikely(_index == _cowdata.size())) {
return _null;
}

const char32_t *_data = nullptr;
int _length = 0;
return _cowdata.get(_index);
}

Char32String(const char32_t *str, int length);
_FORCE_INLINE_ const T *operator&() const {
return _cowdata.ptr() + _index;
}

public:
int length() const;
const char32_t *get_data() const;
_FORCE_INLINE_ void operator=(const T &p_other) const {
_cowdata.set(_index, p_other);
}

Char32String(Char32String &&p_str);
void operator=(Char32String &&p_str);
Char32String() {}
~Char32String();
_FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const {
_cowdata.set(_index, p_other.operator T());
}
};

class CharWideString {
template <class T>
class CharStringT {
friend class String;

const wchar_t *_data = nullptr;
int _length = 0;

CharWideString(const wchar_t *str, int length);
CowData<T> _cowdata;
static inline const T _null = 0;

public:
int length() const;
const wchar_t *get_data() const;

CharWideString(CharWideString &&p_str);
void operator=(CharWideString &&p_str);
CharWideString() {}
~CharWideString();
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const 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_ T get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ const T &operator[](int p_index) const {
if (unlikely(p_index == _cowdata.size())) {
return _null;
}

return _cowdata.get(p_index);
}
_FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }

_FORCE_INLINE_ CharStringT() {}
_FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ void operator=(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); }

void operator=(const T *p_cstr);
bool operator<(const CharStringT<T> &p_right) const;
CharStringT<T> &operator+=(T p_char);
int length() const { return size() ? size() - 1 : 0; }
const T *get_data() const;
operator const T *() const { return get_data(); };

protected:
void copy_from(const T *p_cstr);
};

typedef CharStringT<char> CharString;
typedef CharStringT<char16_t> Char16String;
typedef CharStringT<char32_t> Char32String;
typedef CharStringT<wchar_t> CharWideString;

} // namespace godot

#endif // GODOT_CHAR_STRING_HPP
Loading

0 comments on commit 3162be2

Please sign in to comment.