This commit is contained in:
altalk23 2023-12-23 17:28:45 +03:00
commit d83f2825f7
7 changed files with 93 additions and 89 deletions

View file

@ -2,7 +2,7 @@
#include <Geode/platform/platform.hpp> #include <Geode/platform/platform.hpp>
#include "string-base.hpp" #include "string.hpp"
#if defined(GEODE_IS_WINDOWS) #if defined(GEODE_IS_WINDOWS)
#include "msvcstl.hpp" #include "msvcstl.hpp"

View file

@ -7,12 +7,12 @@
#include <compare> #include <compare>
namespace geode::stl { namespace geode::stl {
class StringImplAdapter; class StringImpl;
struct StringImpl; struct StringData;
#if defined(GEODE_IS_WINDOWS) #if defined(GEODE_IS_WINDOWS)
struct StringImpl { struct StringData {
union { union {
std::array<char, 16> m_smallStorage; std::array<char, 16> m_smallStorage;
char* m_bigStorage; char* m_bigStorage;
@ -22,7 +22,7 @@ namespace geode::stl {
size_t m_capacity; size_t m_capacity;
}; };
#elif defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID) #elif defined(GEODE_IS_MACOS) || defined(GEODE_IS_ANDROID)
struct StringImpl { struct StringData {
struct Internal { struct Internal {
size_t m_size; size_t m_size;
size_t m_capacity; size_t m_capacity;
@ -31,7 +31,7 @@ namespace geode::stl {
Internal* m_data = nullptr; Internal* m_data = nullptr;
}; };
#elif defined(GEODE_IS_IOS) #elif defined(GEODE_IS_IOS)
struct StringImpl { struct StringData {
struct Short { struct Short {
uint8_t sizex2; uint8_t sizex2;
std::array<char, 23> shortStorage; std::array<char, 23> shortStorage;
@ -48,15 +48,13 @@ namespace geode::stl {
Long m_long; Long m_long;
}; };
}; };
#else
using StringImpl = void;
#endif #endif
} }
namespace gd { namespace gd {
class GEODE_DLL string { class GEODE_DLL string {
geode::stl::StringImpl m_impl; geode::stl::StringData m_data;
friend geode::stl::StringImplAdapter; friend geode::stl::StringImpl;
public: public:
string(); string();
string(string const&); string(string const&);

View file

@ -2,10 +2,10 @@
#include <Geode/c++stl/gdstdlib.hpp> #include <Geode/c++stl/gdstdlib.hpp>
namespace geode::stl { namespace geode::stl {
struct StringImplAdapter { struct StringImpl {
StringImpl& impl; StringData& data;
// clear but assumes the existing impl is uninit, // clear but assumes the existing data is uninit,
// so basically a default ctor // so basically a default ctor
void setEmpty(); void setEmpty();

View file

@ -1,5 +1,5 @@
#include <Geode/c++stl/gdstdlib.hpp> #include <Geode/c++stl/gdstdlib.hpp>
#include "string-adapter.hpp" #include "string-impl.hpp"
#include <string_view> #include <string_view>
#include <string> #include <string>
#include <compare> #include <compare>
@ -9,33 +9,33 @@ Type& intoMutRef(const Type& x) {
return const_cast<Type&>(x); return const_cast<Type&>(x);
} }
using geode::stl::StringImplAdapter; using geode::stl::StringImpl;
#define getAdap(x) StringImplAdapter{intoMutRef(x)} #define implFor(x) StringImpl{intoMutRef(x.m_data)}
#define adap getAdap(m_impl) #define impl implFor((*this))
namespace gd { namespace gd {
string::string() { string::string() {
adap.setEmpty(); impl.setEmpty();
} }
string::string(string const& str) { string::string(string const& str) {
adap.setStorage(str); impl.setStorage(str);
} }
// string::string(string&& other) { // string::string(string&& other) {
// // TODO: do this better :-) // // TODO: do this better :-)
// adap.setStorage(other); // impl.setStorage(other);
// getAdap(other.m_impl).free(); // implFor(other).free();
// getAdap(other.m_impl).setEmpty(); // implFor(other).setEmpty();
// } // }
string::string(char const* str) { string::string(char const* str) {
adap.setStorage(str); impl.setStorage(str);
} }
string::string(std::string const& str) { string::string(std::string const& str) {
adap.setStorage(str); impl.setStorage(str);
} }
string::~string() { string::~string() {
@ -44,53 +44,53 @@ namespace gd {
string& string::operator=(string const& other) { string& string::operator=(string const& other) {
if (this != &other) { if (this != &other) {
adap.free(); impl.free();
adap.setStorage(other); impl.setStorage(other);
} }
return *this; return *this;
} }
string& string::operator=(string&& other) { string& string::operator=(string&& other) {
// TODO: do this better :-) // TODO: do this better :-)
adap.free(); impl.free();
adap.setStorage(other); impl.setStorage(other);
getAdap(other.m_impl).free(); implFor(other).free();
getAdap(other.m_impl).setEmpty(); implFor(other).setEmpty();
return *this; return *this;
} }
string& string::operator=(char const* other) { string& string::operator=(char const* other) {
adap.free(); impl.free();
adap.setStorage(other); impl.setStorage(other);
return *this; return *this;
} }
string& string::operator=(std::string const& other) { string& string::operator=(std::string const& other) {
adap.free(); impl.free();
adap.setStorage(other); impl.setStorage(other);
return *this; return *this;
} }
void string::clear() { void string::clear() {
adap.free(); impl.free();
adap.setEmpty(); impl.setEmpty();
} }
char& string::at(size_t pos) { char& string::at(size_t pos) {
if (pos >= this->size()) if (pos >= this->size())
throw std::out_of_range("gd::string::at"); throw std::out_of_range("gd::string::at");
return adap.getStorage()[pos]; return impl.getStorage()[pos];
} }
char const& string::at(size_t pos) const { char const& string::at(size_t pos) const {
return const_cast<string*>(this)->at(pos); return const_cast<string*>(this)->at(pos);
} }
char& string::operator[](size_t pos) { return adap.getStorage()[pos]; } char& string::operator[](size_t pos) { return impl.getStorage()[pos]; }
char const& string::operator[](size_t pos) const { return adap.getStorage()[pos]; } char const& string::operator[](size_t pos) const { return impl.getStorage()[pos]; }
char* string::data() { return adap.getStorage(); } char* string::data() { return impl.getStorage(); }
char const* string::data() const { return adap.getStorage(); } char const* string::data() const { return impl.getStorage(); }
char const* string::c_str() const { return this->data(); } char const* string::c_str() const { return this->data(); }
size_t string::size() const { return adap.getSize(); } size_t string::size() const { return impl.getSize(); }
size_t string::capacity() const { return adap.getCapacity(); } size_t string::capacity() const { return impl.getCapacity(); }
bool string::empty() const { return this->size() == 0; } bool string::empty() const { return this->size() == 0; }
bool string::operator==(string const& other) const { bool string::operator==(string const& other) const {

View file

@ -1,5 +1,5 @@
#include <Geode/c++stl/gdstdlib.hpp> #include <Geode/c++stl/gdstdlib.hpp>
#include "../../c++stl/string-adapter.hpp" #include "../../c++stl/string-impl.hpp"
#ifdef GEODE_IS_ANDROID32 #ifdef GEODE_IS_ANDROID32
@ -16,27 +16,29 @@ namespace geode::base {
namespace geode::stl { namespace geode::stl {
static inline auto emptyInternalString() { static inline auto emptyInternalString() {
return reinterpret_cast<StringImpl::Internal*>( return reinterpret_cast<StringData::Internal*>(
geode::base::get() + (0xaa1c3c - 0x10000) + sizeof(StringImpl::Internal) geode::base::get() + (0xaa1c3c - 0x10000) + sizeof(StringData::Internal)
); );
} }
void StringImplAdapter::setEmpty() { void StringImpl::setEmpty() {
impl.m_data = emptyInternalString(); data.m_data = emptyInternalString();
} }
void StringImplAdapter::free() { void StringImpl::free() {
if (impl.m_data == nullptr || impl.m_data == emptyInternalString()) return; if (data.m_data == nullptr || data.m_data == emptyInternalString()) return;
// TODO: reimplement this // TODO: reimplement this
reinterpret_cast<void (*)(StringImpl*)>(geode::base::get() + (0x7514c8 - 0x10000) + 1)(&impl); reinterpret_cast<void (*)(StringData*)>(geode::base::get() + (0x7514c8 - 0x10000) + 1)(&data);
} }
char* StringImplAdapter::getStorage() { char* StringImpl::getStorage() {
return reinterpret_cast<char*>(impl.m_data); return reinterpret_cast<char*>(data.m_data);
} }
void StringImplAdapter::setStorage(const std::string_view str) { // TODO: add a copyFrom(string const&) to take advantage
// of gnustl refcounted strings
void StringImpl::setStorage(const std::string_view str) {
this->free(); this->free();
if (str.size() == 0) { if (str.size() == 0) {
@ -45,33 +47,36 @@ namespace geode::stl {
} }
// TODO: should be using (char*, size_t) at the very least, or yknow, just reimplement it :-) // TODO: should be using (char*, size_t) at the very least, or yknow, just reimplement it :-)
reinterpret_cast<void (*)(StringImpl*, char const*)>(geode::base::get() + (0x753a44 - 0x10000) + 1)(&impl, str.data()); reinterpret_cast<void (*)(StringData*, char const*)>(geode::base::get() + (0x753a44 - 0x10000) + 1)(&data, str.data());
return; return;
StringImpl::Internal internal; // TODO: this crashes because we need to use gd's operator new...
#if 0
StringData::Internal internal;
internal.m_size = str.size(); internal.m_size = str.size();
internal.m_capacity = str.size(); internal.m_capacity = str.size();
internal.m_refcount = 0; internal.m_refcount = 0;
auto* data = static_cast<char*>(operator new(str.size() + 1 + sizeof(internal))); auto* buffer = static_cast<char*>(operator new(str.size() + 1 + sizeof(internal)));
std::memcpy(data, &internal, sizeof(internal)); std::memcpy(buffer, &internal, sizeof(internal));
std::memcpy(data + sizeof(internal), str.data(), str.size()); std::memcpy(buffer + sizeof(internal), str.data(), str.size());
data[sizeof(internal) + str.size()] = 0; buffer[sizeof(internal) + str.size()] = 0;
impl.m_data = reinterpret_cast<StringImpl::Internal*>(data + sizeof(internal)); data.m_data = reinterpret_cast<StringData::Internal*>(buffer + sizeof(internal));
#endif
} }
size_t StringImplAdapter::getSize() { size_t StringImpl::getSize() {
return impl.m_data[-1].m_size; return data.m_data[-1].m_size;
} }
void StringImplAdapter::setSize(size_t size) { void StringImpl::setSize(size_t size) {
// TODO: implement this, remember its copy-on-write... // TODO: implement this, remember its copy-on-write...
} }
size_t StringImplAdapter::getCapacity() { size_t StringImpl::getCapacity() {
return impl.m_data[-1].m_capacity; return data.m_data[-1].m_capacity;
} }
void StringImplAdapter::setCapacity(size_t cap) { void StringImpl::setCapacity(size_t cap) {
// TODO: implement this, remember its copy-on-write... // TODO: implement this, remember its copy-on-write...
} }
} }

View file

@ -1,46 +1,46 @@
#include "../../c++stl/string-adapter.hpp" #include "../../c++stl/string-impl.hpp"
#ifdef GEODE_IS_WINDOWS #ifdef GEODE_IS_WINDOWS
namespace geode::stl { namespace geode::stl {
void StringImplAdapter::setEmpty() { void StringImpl::setEmpty() {
impl.m_size = 0; data.m_size = 0;
impl.m_capacity = 15; data.m_capacity = 15;
impl.m_smallStorage[0] = 0; data.m_smallStorage[0] = 0;
} }
void StringImplAdapter::free() { void StringImpl::free() {
if (impl.m_capacity > 15) { if (data.m_capacity > 15) {
delete impl.m_bigStorage; delete data.m_bigStorage;
} }
} }
char* StringImplAdapter::getStorage() { char* StringImpl::getStorage() {
return impl.m_capacity <= 15 ? impl.m_smallStorage.data() : impl.m_bigStorage; return data.m_capacity <= 15 ? data.m_smallStorage.data() : data.m_bigStorage;
} }
void StringImplAdapter::setStorage(const std::string_view str) { void StringImpl::setStorage(const std::string_view str) {
impl.m_size = impl.m_capacity = str.size(); data.m_size = data.m_capacity = str.size();
if (str.size() <= 15) { if (str.size() <= 15) {
impl.m_capacity = 15; data.m_capacity = 15;
} else { } else {
impl.m_bigStorage = static_cast<char*>(operator new(str.size() + 1)); data.m_bigStorage = static_cast<char*>(operator new(str.size() + 1));
} }
std::memcpy(getStorage(), str.data(), str.size()); std::memcpy(getStorage(), str.data(), str.size());
getStorage()[str.size()] = 0; getStorage()[str.size()] = 0;
} }
size_t StringImplAdapter::getSize() { size_t StringImpl::getSize() {
return impl.m_size; return data.m_size;
} }
void StringImplAdapter::setSize(size_t size) { void StringImpl::setSize(size_t size) {
impl.m_size = size; data.m_size = size;
} }
size_t StringImplAdapter::getCapacity() { size_t StringImpl::getCapacity() {
return impl.m_capacity; return data.m_capacity;
} }
void StringImplAdapter::setCapacity(size_t cap) { void StringImpl::setCapacity(size_t cap) {
impl.m_capacity = cap; data.m_capacity = cap;
} }
} }

View file

@ -504,6 +504,7 @@ void ModListLayer::reloadList(bool keepScroll, std::optional<ModListQuery> const
m_listLabel->setVisible(true); m_listLabel->setVisible(true);
m_listLabel->setString("Updating index..."); m_listLabel->setString("Updating index...");
if (!m_loadingCircle) { if (!m_loadingCircle) {
// TODO: mat
m_loadingCircle = LoadingCircle::create(); m_loadingCircle = LoadingCircle::create();
m_loadingCircle->setPosition(.0f, -40.f); m_loadingCircle->setPosition(.0f, -40.f);