Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to fully implement CharString #1150

Merged
merged 1 commit into from
Jul 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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