#ifndef NONUT_CORE_PROPERTY_H #define NONUT_CORE_PROPERTY_H #include #include #include "Utils.h" #include "Class.h" namespace nonut { template T getProperty(const SQObject& object, const String& name) { HSQUIRRELVM vm = Sqrat::DefaultVM::Get(); const auto top = sq_gettop(vm); sq_pushobject(vm, object); sq_pushstring(vm, name.c_str(), name.length()); if constexpr (std::derived_from) { SQObject intermediateResult{}; if (SQ_SUCCEEDED(sq_get(vm, -2))) // pops property { sqGetValue(vm, -1, &intermediateResult); sq_pop(vm, 1); // pops result } sq_pop(vm, 1); // pops object sq_settop(vm, top); return T(intermediateResult); } else { T result{}; if (SQ_SUCCEEDED(sq_get(vm, -2))) // pops property { sqGetValue(vm, -1, &result); sq_pop(vm, 1); // pops result } sq_pop(vm, 1); // pops object sq_settop(vm, top); return result; } } template <> inline bool getProperty(const SQObject& object, const String& name) { return getProperty(object, name); } template <> inline String getProperty(const SQObject& object, const String& name) { HSQUIRRELVM vm = Sqrat::DefaultVM::Get(); const Int top = sq_gettop(vm); const SQChar* result{}; sq_pushobject(vm, object); sq_pushstring(vm, name.c_str(), name.length()); if (SQ_SUCCEEDED(sq_get(vm, -2))) // pops property { sq_getstring(vm, -1, &result); sq_pop(vm, 1); // pops result } sq_pop(vm, 1); // pops object sq_settop(vm, top); return result; } template void setProperty(SQObject& object, String& name, T value) { HSQUIRRELVM vm = Sqrat::DefaultVM::Get(); sq_pushobject(vm, object); sq_pushstring(vm, name.c_str(), name.length()); if constexpr (std::derived_from) { sqPushValue(vm, value.getInstance()); } else { sqPushValue(vm, value); } auto result = sq_set(vm, -3); // pops name and value sq_pop(vm, 1); // pops object } template class Property { public: Property(String propertyName, const SQObject object) : object(object), propertyName(std::move(propertyName)) { } Property& operator=(const T& other) noexcept { set(other); return *this; } operator T() { return this->get(); } [[nodiscard]] T get() const { return getProperty(object, propertyName); } void set(T value) { static_assert(!IsReadOnly, "Cannot set read-only property."); setProperty(object, propertyName, value); } private: SQObject object; String propertyName; }; } #endif // NONUT_CORE_PROPERTY_H