refactor(datatypes): generified types allowing a parameter to be specified for enum type and instance type. Also made deserialization fallible
This commit is contained in:
parent
5149e34723
commit
10d69ce7ac
28 changed files with 232 additions and 124 deletions
|
@ -174,6 +174,25 @@ static bool hasMethod(CXCursor cur, std::string methodName) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasGenericMethod(CXCursor cur, std::string methodName) {
|
||||||
|
bool found = false;
|
||||||
|
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||||
|
CXCursorKind kind = clang_getCursorKind(cur);
|
||||||
|
if (kind != CXCursor_CXXMethod) return CXChildVisit_Continue;
|
||||||
|
|
||||||
|
if (x_clang_toString(clang_getCursorSpelling(cur)) != methodName) return CXChildVisit_Continue;
|
||||||
|
|
||||||
|
int numArgs = clang_Cursor_getNumArguments(cur);
|
||||||
|
CXCursor lastParam = clang_Cursor_getArgument(cur, numArgs - 1);
|
||||||
|
std::string lastParamType = x_clang_toString(clang_getTypeSpelling(clang_getCursorType(lastParam)));
|
||||||
|
if (lastParamType != "const TypeMeta") return CXChildVisit_Continue;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
return CXChildVisit_Break;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||||
ClassAnalysis anly;
|
ClassAnalysis anly;
|
||||||
|
|
||||||
|
@ -184,6 +203,8 @@ static void processClass(CXCursor cur, AnalysisState* state, std::string classNa
|
||||||
anly.serializedName = result["name"];
|
anly.serializedName = result["name"];
|
||||||
anly.hasFromString = hasMethod(cur, "FromString");
|
anly.hasFromString = hasMethod(cur, "FromString");
|
||||||
anly.isSerializable = hasMethod(cur, "Serialize") && hasMethod(cur, "Deserialize");
|
anly.isSerializable = hasMethod(cur, "Serialize") && hasMethod(cur, "Deserialize");
|
||||||
|
anly.hasGenericDeserializer = hasGenericMethod(cur, "Deserialize");
|
||||||
|
anly.hasGenericFromString = hasGenericMethod(cur, "FromString");
|
||||||
|
|
||||||
if (anly.serializedName == "")
|
if (anly.serializedName == "")
|
||||||
anly.serializedName = className;
|
anly.serializedName = className;
|
||||||
|
|
|
@ -37,6 +37,8 @@ struct ClassAnalysis {
|
||||||
std::string headerPath;
|
std::string headerPath;
|
||||||
bool hasFromString;
|
bool hasFromString;
|
||||||
bool isSerializable;
|
bool isSerializable;
|
||||||
|
bool hasGenericDeserializer;
|
||||||
|
bool hasGenericFromString;
|
||||||
std::vector<PropertyAnalysis> properties;
|
std::vector<PropertyAnalysis> properties;
|
||||||
std::vector<MethodAnalysis> methods;
|
std::vector<MethodAnalysis> methods;
|
||||||
std::vector<PropertyAnalysis> staticProperties;
|
std::vector<PropertyAnalysis> staticProperties;
|
||||||
|
|
|
@ -238,13 +238,13 @@ static void writeLuaMethodImpls(std::ofstream& out, ClassAnalysis& state) {
|
||||||
static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
std::string fqn = state.name;
|
std::string fqn = state.name;
|
||||||
|
|
||||||
out << "static int data_gc(lua_State*);\n"
|
out << "static int data_" << state.name << "_gc(lua_State*);\n"
|
||||||
"static int data_index(lua_State*);\n"
|
"static int data_" << state.name << "_index(lua_State*);\n"
|
||||||
"static int data_tostring(lua_State*);\n"
|
"static int data_" << state.name << "_tostring(lua_State*);\n"
|
||||||
"static const struct luaL_Reg metatable [] = {\n"
|
"static const struct luaL_Reg " << state.name << "_metatable [] = {\n"
|
||||||
" {\"__gc\", data_gc},\n"
|
" {\"__gc\", data_" << state.name << "_gc},\n"
|
||||||
" {\"__index\", data_index},\n"
|
" {\"__index\", data_" << state.name << "_index},\n"
|
||||||
" {\"__tostring\", data_tostring},\n"
|
" {\"__tostring\", data_" << state.name << "_tostring},\n"
|
||||||
" {NULL, NULL} /* end of array */\n"
|
" {NULL, NULL} /* end of array */\n"
|
||||||
"};\n\n";
|
"};\n\n";
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
|
|
||||||
" // Create the library's metatable\n"
|
" // Create the library's metatable\n"
|
||||||
" luaL_newmetatable(L, \"__mt_" << state.name << "\");\n"
|
" luaL_newmetatable(L, \"__mt_" << state.name << "\");\n"
|
||||||
" luaL_register(L, NULL, metatable);\n"
|
" luaL_register(L, NULL, " << state.name << "_metatable);\n"
|
||||||
|
|
||||||
" lua_setmetatable(L, n+1);\n"
|
" lua_setmetatable(L, n+1);\n"
|
||||||
"}\n\n";
|
"}\n\n";
|
||||||
|
@ -271,7 +271,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
|
|
||||||
// Indexing methods and properties
|
// Indexing methods and properties
|
||||||
|
|
||||||
out << "static int data_index(lua_State* L) {\n"
|
out << "static int data_" << state.name << "_index(lua_State* L) {\n"
|
||||||
" " << fqn << "* this_ = *(" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
" " << fqn << "* this_ = *(" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
||||||
"\n"
|
"\n"
|
||||||
" std::string key(lua_tostring(L, 2));\n"
|
" std::string key(lua_tostring(L, 2));\n"
|
||||||
|
@ -323,7 +323,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
|
|
||||||
// ToString
|
// ToString
|
||||||
|
|
||||||
out << "\nint data_tostring(lua_State* L) {\n"
|
out << "\nint data_" << state.name << "_tostring(lua_State* L) {\n"
|
||||||
" " << fqn << "* this_ = *(" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
" " << fqn << "* this_ = *(" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
||||||
" lua_pushstring(L, std::string(this_->ToString()).c_str());\n"
|
" lua_pushstring(L, std::string(this_->ToString()).c_str());\n"
|
||||||
" return 1;\n"
|
" return 1;\n"
|
||||||
|
@ -331,7 +331,7 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
|
|
||||||
out << "\nint data_gc(lua_State* L) {\n"
|
out << "\nint data_" << state.name << "_gc(lua_State* L) {\n"
|
||||||
" " << fqn << "** userdata = (" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
" " << fqn << "** userdata = (" << fqn << "**)luaL_checkudata(L, 1, \"__mt_" << state.name << "\");\n"
|
||||||
" delete *userdata;\n"
|
" delete *userdata;\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
|
@ -341,9 +341,12 @@ static void writeLuaValueGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) {
|
static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
std::string fqn = state.name;
|
std::string fqn = state.name;
|
||||||
|
|
||||||
out << "static int lib_index(lua_State*);\n"
|
// If there are no static methods or properties, no need to create a library
|
||||||
"static const struct luaL_Reg lib_metatable [] = {\n"
|
if (state.staticMethods.size() == 0 && state.staticProperties.size() == 0) return;
|
||||||
" {\"__index\", lib_index},\n"
|
|
||||||
|
out << "static int lib_" << state.name << "_index(lua_State*);\n"
|
||||||
|
"static const struct luaL_Reg lib_" << state.name << "_metatable [] = {\n"
|
||||||
|
" {\"__index\", lib_" << state.name << "_index},\n"
|
||||||
" {NULL, NULL} /* end of array */\n"
|
" {NULL, NULL} /* end of array */\n"
|
||||||
"};\n\n";
|
"};\n\n";
|
||||||
|
|
||||||
|
@ -355,7 +358,7 @@ static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
"\n"
|
"\n"
|
||||||
" // Create the library's metatable\n"
|
" // Create the library's metatable\n"
|
||||||
" luaL_newmetatable(L, \"__mt_lib_" << state.name << "\");\n"
|
" luaL_newmetatable(L, \"__mt_lib_" << state.name << "\");\n"
|
||||||
" luaL_register(L, NULL, lib_metatable);\n"
|
" luaL_register(L, NULL, lib_" << state.name << "_metatable);\n"
|
||||||
" lua_setmetatable(L, -2);\n"
|
" lua_setmetatable(L, -2);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" lua_rawset(L, -3);\n"
|
" lua_rawset(L, -3);\n"
|
||||||
|
@ -364,7 +367,7 @@ static void writeLuaLibraryGenerator(std::ofstream& out, ClassAnalysis& state) {
|
||||||
|
|
||||||
// Indexing methods and properties
|
// Indexing methods and properties
|
||||||
|
|
||||||
out << "static int lib_index(lua_State* L) {\n"
|
out << "static int lib_" << state.name << "_index(lua_State* L) {\n"
|
||||||
" std::string key(lua_tostring(L, 2));\n"
|
" std::string key(lua_tostring(L, 2));\n"
|
||||||
" lua_pop(L, 2);\n"
|
" lua_pop(L, 2);\n"
|
||||||
"\n";
|
"\n";
|
||||||
|
@ -418,14 +421,24 @@ void data::writeCodeForClass(std::ofstream& out, std::string headerPath, ClassAn
|
||||||
out << "#include \"datatypes/variant.h\"\n";
|
out << "#include \"datatypes/variant.h\"\n";
|
||||||
out << "#include <pugixml.hpp>\n";
|
out << "#include <pugixml.hpp>\n";
|
||||||
out << "#include \"lua.h\"\n\n";
|
out << "#include \"lua.h\"\n\n";
|
||||||
out << "const TypeDescriptor " << state.name << "::TYPE = {\n"
|
out << "const TypeDesc " << state.name << "::TYPE = {\n"
|
||||||
<< " .name = \"" << state.serializedName << "\",\n"
|
<< " .name = \"" << state.serializedName << "\",\n";
|
||||||
<< " .serializer = toVariantFunction(&" << state.name << "::Serialize),"
|
if (state.isSerializable) {
|
||||||
<< " .deserializer = toVariantGenerator(&" << state.name << "::Deserialize),\n"
|
out << " .serialize = toVariantFunction(&" << state.name << "::Serialize),";
|
||||||
<< " .toString = toVariantFunction(&" << state.name << "::ToString),";
|
if (state.hasGenericDeserializer)
|
||||||
if (state.hasFromString) out << " .fromString = &" << state.name << "::FromString,\n";
|
out << " .deserialize = toVariantGenerator(&" << state.name << "::Deserialize),\n";
|
||||||
|
else
|
||||||
|
out << " .deserialize = toVariantGeneratorNoMeta(&" << state.name << "::Deserialize),\n";
|
||||||
|
}
|
||||||
|
out << " .toString = toVariantFunction(&" << state.name << "::ToString),";
|
||||||
|
if (state.hasFromString) {
|
||||||
|
if (state.hasGenericFromString)
|
||||||
|
out << " .fromString = toVariantGenerator(&" << state.name << "::FromString),\n";
|
||||||
|
else
|
||||||
|
out << " .fromString = toVariantGeneratorNoMeta(&" << state.name << "::FromString),\n";
|
||||||
|
}
|
||||||
out << " .pushLuaValue = toVariantFunction(&" << state.name << "::PushLuaValue),"
|
out << " .pushLuaValue = toVariantFunction(&" << state.name << "::PushLuaValue),"
|
||||||
<< " .fromLuaValue = &" << state.name << "::FromLuaValue,\n"
|
<< " .fromLuaValue = toVariantGenerator(&" << state.name << "::FromLuaValue),\n"
|
||||||
<< "};\n\n";
|
<< "};\n\n";
|
||||||
|
|
||||||
writeLuaMethodImpls(out, state);
|
writeLuaMethodImpls(out, state);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#define AUTOGEN_PREAMBLE_DATA \
|
#define AUTOGEN_PREAMBLE_DATA \
|
||||||
public: \
|
public: \
|
||||||
static const TypeDescriptor TYPE; \
|
static const TypeDesc TYPE; \
|
||||||
virtual void PushLuaValue(lua_State*) const; \
|
virtual void PushLuaValue(lua_State*) const; \
|
||||||
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx); \
|
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx); \
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -11,17 +11,20 @@ extern "C" { typedef struct lua_State lua_State; }
|
||||||
namespace pugi { class xml_node; };
|
namespace pugi { class xml_node; };
|
||||||
|
|
||||||
class Variant;
|
class Variant;
|
||||||
typedef std::function<void(Variant, pugi::xml_node)> Serializer;
|
struct TypeMeta;
|
||||||
typedef std::function<Variant(pugi::xml_node)> Deserializer;
|
|
||||||
|
typedef std::function<void(Variant, pugi::xml_node)> Serialize;
|
||||||
|
typedef std::function<result<Variant, DataParseError>(pugi::xml_node, const TypeMeta)> Deserialize;
|
||||||
typedef std::function<std::string(Variant)> ToString;
|
typedef std::function<std::string(Variant)> ToString;
|
||||||
typedef std::function<std::optional<Variant>(std::string)> FromString;
|
typedef std::function<result<Variant, DataParseError>(std::string, const TypeMeta)> FromString;
|
||||||
typedef std::function<result<Variant, LuaCastError>(lua_State*, int idx)> FromLuaValue;
|
typedef std::function<result<Variant, LuaCastError>(lua_State*, int idx)> FromLuaValue;
|
||||||
typedef std::function<void(Variant self, lua_State*)> PushLuaValue;
|
typedef std::function<void(Variant self, lua_State*)> PushLuaValue;
|
||||||
|
|
||||||
struct TypeDescriptor {
|
// Describes a concrete type
|
||||||
|
struct TypeDesc {
|
||||||
std::string name;
|
std::string name;
|
||||||
Serializer serializer;
|
Serialize serialize;
|
||||||
Deserializer deserializer;
|
Deserialize deserialize;
|
||||||
ToString toString;
|
ToString toString;
|
||||||
FromString fromString;
|
FromString fromString;
|
||||||
PushLuaValue pushLuaValue;
|
PushLuaValue pushLuaValue;
|
||||||
|
@ -29,11 +32,17 @@ struct TypeDescriptor {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Enum;
|
class Enum;
|
||||||
|
struct InstanceType;
|
||||||
|
|
||||||
struct TypeInfo {
|
// Describes a meta-type, which consists of a concrete type, and some generic argument.
|
||||||
const TypeDescriptor* descriptor;
|
struct TypeMeta {
|
||||||
Enum* enum_;
|
const TypeDesc* descriptor;
|
||||||
|
union {
|
||||||
|
Enum* enum_; // Applicable for EnumItem
|
||||||
|
InstanceType* instType; // Applicable for InstanceRef
|
||||||
|
};
|
||||||
|
|
||||||
inline TypeInfo(const TypeDescriptor* descriptor) : descriptor(descriptor) {}
|
inline TypeMeta(const TypeDesc* descriptor) : descriptor(descriptor) {}
|
||||||
TypeInfo(Enum*);
|
TypeMeta(Enum*);
|
||||||
|
TypeMeta(InstanceType*);
|
||||||
};
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
#include "cframe.h"
|
#include "cframe.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "physics/util.h"
|
#include "physics/util.h"
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
#include <glm/gtc/matrix_inverse.hpp>
|
#include <glm/gtc/matrix_inverse.hpp>
|
||||||
|
@ -134,7 +135,7 @@ void CFrame::Serialize(pugi::xml_node node) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CFrame CFrame::Deserialize(pugi::xml_node node) {
|
result<CFrame, DataParseError> CFrame::Deserialize(pugi::xml_node node) {
|
||||||
return CFrame(
|
return CFrame(
|
||||||
node.child("X").text().as_float(),
|
node.child("X").text().as_float(),
|
||||||
node.child("Y").text().as_float(),
|
node.child("Y").text().as_float(),
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
#include "datatypes/annotation.h"
|
#include "datatypes/annotation.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include <glm/ext/quaternion_float.hpp>
|
#include <glm/ext/quaternion_float.hpp>
|
||||||
#include <glm/gtc/matrix_access.hpp>
|
#include <glm/gtc/matrix_access.hpp>
|
||||||
#include <glm/matrix.hpp>
|
#include <glm/matrix.hpp>
|
||||||
|
@ -40,7 +41,7 @@ public:
|
||||||
|
|
||||||
virtual const std::string ToString() const;
|
virtual const std::string ToString() const;
|
||||||
virtual void Serialize(pugi::xml_node parent) const;
|
virtual void Serialize(pugi::xml_node parent) const;
|
||||||
static CFrame Deserialize(pugi::xml_node node);
|
static result<CFrame, DataParseError> Deserialize(pugi::xml_node node);
|
||||||
|
|
||||||
static void PushLuaLibrary(lua_State*);
|
static void PushLuaLibrary(lua_State*);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "color3.h"
|
#include "color3.h"
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -39,6 +40,6 @@ void Color3::Serialize(pugi::xml_node node) const {
|
||||||
node.text().set(this->ToHex());
|
node.text().set(this->ToHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 Color3::Deserialize(pugi::xml_node node) {
|
result<Color3, DataParseError> Color3::Deserialize(pugi::xml_node node) {
|
||||||
return Color3::FromHex(node.text().get());
|
return Color3::FromHex(node.text().get());
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
#include "datatypes/annotation.h"
|
#include "datatypes/annotation.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include <glm/ext/vector_float3.hpp>
|
#include <glm/ext/vector_float3.hpp>
|
||||||
|
|
||||||
class DEF_DATA Color3 {
|
class DEF_DATA Color3 {
|
||||||
|
@ -21,7 +22,7 @@ public:
|
||||||
virtual const std::string ToString() const;
|
virtual const std::string ToString() const;
|
||||||
DEF_DATA_METHOD std::string ToHex() const;
|
DEF_DATA_METHOD std::string ToHex() const;
|
||||||
virtual void Serialize(pugi::xml_node node) const;
|
virtual void Serialize(pugi::xml_node node) const;
|
||||||
static Color3 Deserialize(pugi::xml_node node);
|
static result<Color3, DataParseError> Deserialize(pugi::xml_node node);
|
||||||
|
|
||||||
static void PushLuaLibrary(lua_State*);
|
static void PushLuaLibrary(lua_State*);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include "enum.h"
|
#include "enum.h"
|
||||||
#include "datatypes/base.h"
|
#include "datatypes/base.h"
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
|
#include "error/data.h"
|
||||||
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
TypeInfo::TypeInfo(Enum* enum_) : enum_(enum_), descriptor(&EnumItem::TYPE) {}
|
TypeMeta::TypeMeta(Enum* enum_) : enum_(enum_), descriptor(&EnumItem::TYPE) {}
|
||||||
|
|
||||||
Enum::Enum(_EnumData* data) : data(data) {}
|
Enum::Enum(_EnumData* data) : data(data) {}
|
||||||
|
|
||||||
|
@ -36,24 +38,29 @@ EnumItem::EnumItem(_EnumData* parentData, std::string name, int value) : parentD
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
std::string Enum::ToString() {
|
std::string Enum::ToString() const {
|
||||||
return "Enum." + this->data->name;
|
return "Enum." + this->data->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enum::PushLuaValue(lua_State*) {
|
//
|
||||||
|
|
||||||
|
std::string EnumItem::ToString() const {
|
||||||
|
return "Enum." + parentData->name + "." + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Enum::FromLuaValue(lua_State*, int) {
|
void EnumItem::Serialize(pugi::xml_node node) const {
|
||||||
|
node.set_name("token");
|
||||||
|
node.text().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor Enum::TYPE {
|
result<EnumItem, DataParseError> EnumItem::Deserialize(pugi::xml_node node, const TypeMeta info) {
|
||||||
.name = "Enum",
|
auto result = info.enum_->FromValue(node.text().as_int());
|
||||||
.toString = toVariantFunction(&Enum::ToString),
|
if (result.has_value()) return result.value();
|
||||||
// .fromString = Enum_FromString,
|
return DataParseError(node.text().as_string(), "EnumItem");
|
||||||
// .pushLuaValue = &Enum_PushLuaValue,
|
}
|
||||||
.fromLuaValue = toVariantGenerator(Enum::FromLuaValue),
|
|
||||||
// .serializer = Enum_Serialize,
|
result<EnumItem, DataParseError> EnumItem::FromString(std::string string, const TypeMeta info) {
|
||||||
// .deserializer = Enum_Deserialize,
|
auto result = info.enum_->FromName(string);
|
||||||
};
|
if (result.has_value()) return result.value();
|
||||||
|
return DataParseError(string, "EnumItem");
|
||||||
|
}
|
|
@ -4,6 +4,8 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "datatypes/annotation.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
struct _EnumData {
|
struct _EnumData {
|
||||||
|
@ -14,33 +16,40 @@ struct _EnumData {
|
||||||
|
|
||||||
class EnumItem;
|
class EnumItem;
|
||||||
|
|
||||||
class Enum {
|
class DEF_DATA Enum {
|
||||||
_EnumData* data;
|
_EnumData* data;
|
||||||
public:
|
public:
|
||||||
Enum(_EnumData*);
|
Enum(_EnumData*);
|
||||||
|
|
||||||
static const TypeDescriptor TYPE;
|
static const TypeDesc TYPE;
|
||||||
|
|
||||||
inline _EnumData* InternalType() const { return this->data; };
|
inline _EnumData* InternalType() const { return this->data; };
|
||||||
std::vector<EnumItem> GetEnumItems() const;
|
std::vector<EnumItem> GetEnumItems() const;
|
||||||
std::optional<EnumItem> FromName(std::string) const;
|
std::optional<EnumItem> FromName(std::string) const;
|
||||||
std::optional<EnumItem> FromValue(int) const;
|
std::optional<EnumItem> FromValue(int) const;
|
||||||
|
|
||||||
std::string ToString();
|
std::string ToString() const;
|
||||||
void PushLuaValue(lua_State*);
|
void PushLuaValue(lua_State*) const;
|
||||||
static Variant FromLuaValue(lua_State*, int);
|
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EnumItem {
|
class DEF_DATA EnumItem {
|
||||||
_EnumData* parentData;
|
_EnumData* parentData;
|
||||||
std::string name;
|
std::string name;
|
||||||
int value;
|
int value;
|
||||||
public:
|
public:
|
||||||
EnumItem(_EnumData*, std::string, int);
|
EnumItem(_EnumData*, std::string, int);
|
||||||
|
|
||||||
static const TypeDescriptor TYPE;
|
static const TypeDesc TYPE;
|
||||||
|
|
||||||
inline std::string Name() const { return this->name; }
|
inline std::string Name() const { return this->name; }
|
||||||
inline int Value() const { return this->value; }
|
inline int Value() const { return this->value; }
|
||||||
inline Enum EnumType() const { return Enum(this->parentData); }
|
inline Enum EnumType() const { return Enum(this->parentData); }
|
||||||
|
|
||||||
|
static result<EnumItem, DataParseError> FromString(std::string, const TypeMeta);
|
||||||
|
std::string ToString() const;
|
||||||
|
void Serialize(pugi::xml_node) const;
|
||||||
|
static result<EnumItem, DataParseError> Deserialize(pugi::xml_node, const TypeMeta);
|
||||||
|
void PushLuaValue(lua_State*) const;
|
||||||
|
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int);
|
||||||
};
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
#include "primitives.h"
|
#include "primitives.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
@ -10,7 +11,7 @@ void Null_Serialize(Variant self, pugi::xml_node node) {
|
||||||
node.text().set("null");
|
node.text().set("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Null_Deserialize(pugi::xml_node node) {
|
result<Variant, DataParseError> Null_Deserialize(pugi::xml_node node, const TypeMeta) {
|
||||||
return std::monostate();
|
return std::monostate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ const std::string Null_ToString(Variant self) {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<Variant> Null_FromString(std::string str) {
|
result<Variant, DataParseError> Null_FromString(std::string string, const TypeMeta) {
|
||||||
return std::monostate();
|
return std::monostate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ result<Variant, LuaCastError> Null_FromLuaValue(lua_State* L, int idx) {
|
||||||
return Variant(std::monostate());
|
return Variant(std::monostate());
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor NULL_TYPE {
|
const TypeDesc NULL_TYPE {
|
||||||
"null",
|
"null",
|
||||||
Null_Serialize,
|
Null_Serialize,
|
||||||
Null_Deserialize,
|
Null_Deserialize,
|
||||||
|
@ -48,7 +49,7 @@ void Bool_Serialize(Variant self, pugi::xml_node node) {
|
||||||
node.text().set(self.get<bool>() ? "true" : "false");
|
node.text().set(self.get<bool>() ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Bool_Deserialize(pugi::xml_node node) {
|
result<Variant, DataParseError> Bool_Deserialize(pugi::xml_node node, const TypeMeta) {
|
||||||
return node.text().as_bool();
|
return node.text().as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ const std::string Bool_ToString(Variant self) {
|
||||||
return self.get<bool>() ? "true" : "false";
|
return self.get<bool>() ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<Variant> Bool_FromString(std::string string) {
|
result<Variant, DataParseError> Bool_FromString(std::string string, const TypeMeta) {
|
||||||
return string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y';
|
return string[0] == 't' || string[0] == 'T' || string[0] == '1' || string[0] == 'y' || string[0] == 'Y';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ result<Variant, LuaCastError> Bool_FromLuaValue(lua_State* L, int idx) {
|
||||||
return Variant(lua_toboolean(L, idx));
|
return Variant(lua_toboolean(L, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor BOOL_TYPE {
|
const TypeDesc BOOL_TYPE {
|
||||||
"bool",
|
"bool",
|
||||||
Bool_Serialize,
|
Bool_Serialize,
|
||||||
Bool_Deserialize,
|
Bool_Deserialize,
|
||||||
|
@ -88,7 +89,7 @@ void Int_Serialize(Variant self, pugi::xml_node node) {
|
||||||
node.text().set(self.get<int>());
|
node.text().set(self.get<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Int_Deserialize(pugi::xml_node node) {
|
result<Variant, DataParseError> Int_Deserialize(pugi::xml_node node, const TypeMeta) {
|
||||||
return node.text().as_int();
|
return node.text().as_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,10 +97,10 @@ const std::string Int_ToString(Variant self) {
|
||||||
return std::to_string(self.get<int>());
|
return std::to_string(self.get<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<Variant> Int_FromString(std::string string) {
|
result<Variant, DataParseError> Int_FromString(std::string string, const TypeMeta) {
|
||||||
char* endPos;
|
char* endPos;
|
||||||
int value = (int)std::strtol(string.c_str(), &endPos, 10);
|
int value = (int)std::strtol(string.c_str(), &endPos, 10);
|
||||||
if (endPos == string.c_str()) return std::nullopt;
|
if (endPos == string.c_str()) return DataParseError(string, "int");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ result<Variant, LuaCastError> Int_FromLuaValue(lua_State* L, int idx) {
|
||||||
return Variant((int)lua_tonumber(L, idx));
|
return Variant((int)lua_tonumber(L, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor INT_TYPE {
|
const TypeDesc INT_TYPE {
|
||||||
"int",
|
"int",
|
||||||
Int_Serialize,
|
Int_Serialize,
|
||||||
Int_Deserialize,
|
Int_Deserialize,
|
||||||
|
@ -131,7 +132,7 @@ void Float_Serialize(Variant self, pugi::xml_node node) {
|
||||||
node.text().set(self.get<float>());
|
node.text().set(self.get<float>());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Float_Deserialize(pugi::xml_node node) {
|
result<Variant, DataParseError> Float_Deserialize(pugi::xml_node node, const TypeMeta) {
|
||||||
return node.text().as_float();
|
return node.text().as_float();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,10 +142,10 @@ const std::string Float_ToString(Variant self) {
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<Variant> Float_FromString(std::string string) {
|
result<Variant, DataParseError> Float_FromString(std::string string, const TypeMeta) {
|
||||||
char* endPos;
|
char* endPos;
|
||||||
float value = std::strtof(string.c_str(), &endPos);
|
float value = std::strtof(string.c_str(), &endPos);
|
||||||
if (endPos == string.c_str()) return std::nullopt;
|
if (endPos == string.c_str()) return DataParseError(string, "float");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +159,7 @@ result<Variant, LuaCastError> Float_FromLuaValue(lua_State* L, int idx) {
|
||||||
return Variant((float)lua_tonumber(L, idx));
|
return Variant((float)lua_tonumber(L, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor FLOAT_TYPE {
|
const TypeDesc FLOAT_TYPE {
|
||||||
"float",
|
"float",
|
||||||
Float_Serialize,
|
Float_Serialize,
|
||||||
Float_Deserialize,
|
Float_Deserialize,
|
||||||
|
@ -176,7 +177,7 @@ void String_Serialize(Variant self, pugi::xml_node node) {
|
||||||
node.text().set(self.get<std::string>());
|
node.text().set(self.get<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant String_Deserialize(pugi::xml_node node) {
|
result<Variant, DataParseError> String_Deserialize(pugi::xml_node node, const TypeMeta) {
|
||||||
return node.text().as_string();
|
return node.text().as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +185,7 @@ const std::string String_ToString(Variant self) {
|
||||||
return self.get<std::string>();
|
return self.get<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<Variant> String_FromString(std::string string) {
|
result<Variant, DataParseError> String_FromString(std::string string, const TypeMeta) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +199,7 @@ result<Variant, LuaCastError> String_FromLuaValue(lua_State* L, int idx) {
|
||||||
return Variant(lua_tostring(L, idx));
|
return Variant(lua_tostring(L, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor STRING_TYPE {
|
const TypeDesc STRING_TYPE {
|
||||||
"string",
|
"string",
|
||||||
String_Serialize,
|
String_Serialize,
|
||||||
String_Deserialize,
|
String_Deserialize,
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
|
||||||
extern const TypeDescriptor NULL_TYPE;
|
extern const TypeDesc NULL_TYPE;
|
||||||
extern const TypeDescriptor BOOL_TYPE;
|
extern const TypeDesc BOOL_TYPE;
|
||||||
extern const TypeDescriptor INT_TYPE;
|
extern const TypeDesc INT_TYPE;
|
||||||
extern const TypeDescriptor FLOAT_TYPE;
|
extern const TypeDesc FLOAT_TYPE;
|
||||||
extern const TypeDescriptor STRING_TYPE;
|
extern const TypeDesc STRING_TYPE;
|
|
@ -10,14 +10,16 @@
|
||||||
#include "objects/base/member.h"
|
#include "objects/base/member.h"
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
|
TypeMeta::TypeMeta(InstanceType* instType) : instType(instType), descriptor(&InstanceRef::TYPE) {}
|
||||||
|
|
||||||
InstanceRef::InstanceRef() {};
|
InstanceRef::InstanceRef() {};
|
||||||
InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {};
|
InstanceRef::InstanceRef(std::weak_ptr<Instance> instance) : ref(instance) {};
|
||||||
InstanceRef::~InstanceRef() = default;
|
InstanceRef::~InstanceRef() = default;
|
||||||
|
|
||||||
const TypeDescriptor InstanceRef::TYPE = {
|
const TypeDesc InstanceRef::TYPE = {
|
||||||
.name = "Ref",
|
.name = "Ref",
|
||||||
.serializer = toVariantFunction(&InstanceRef::Serialize),
|
.serialize = toVariantFunction(&InstanceRef::Serialize),
|
||||||
.deserializer = &InstanceRef::Deserialize,
|
.deserialize = toVariantGeneratorNoMeta(&InstanceRef::Deserialize),
|
||||||
.toString = toVariantFunction(&InstanceRef::ToString),
|
.toString = toVariantFunction(&InstanceRef::ToString),
|
||||||
.fromString = nullptr,
|
.fromString = nullptr,
|
||||||
.pushLuaValue = toVariantFunction(&InstanceRef::PushLuaValue),
|
.pushLuaValue = toVariantFunction(&InstanceRef::PushLuaValue),
|
||||||
|
@ -39,7 +41,7 @@ void InstanceRef::Serialize(pugi::xml_node node) const {
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceRef InstanceRef::Deserialize(pugi::xml_node node) {
|
result<InstanceRef, DataParseError> InstanceRef::Deserialize(pugi::xml_node node) {
|
||||||
// Handled by Instance
|
// Handled by Instance
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ public:
|
||||||
InstanceRef(std::weak_ptr<Instance>);
|
InstanceRef(std::weak_ptr<Instance>);
|
||||||
~InstanceRef();
|
~InstanceRef();
|
||||||
|
|
||||||
static const TypeDescriptor TYPE;
|
static const TypeDesc TYPE;
|
||||||
|
|
||||||
operator std::weak_ptr<Instance>();
|
operator std::weak_ptr<Instance>();
|
||||||
|
|
||||||
virtual const std::string ToString() const;
|
virtual const std::string ToString() const;
|
||||||
virtual void Serialize(pugi::xml_node node) const;
|
virtual void Serialize(pugi::xml_node node) const;
|
||||||
virtual void PushLuaValue(lua_State*) const;
|
virtual void PushLuaValue(lua_State*) const;
|
||||||
static InstanceRef Deserialize(pugi::xml_node node);
|
static result<InstanceRef, DataParseError> Deserialize(pugi::xml_node node);
|
||||||
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
static result<Variant, LuaCastError> FromLuaValue(lua_State*, int idx);
|
||||||
};
|
};
|
|
@ -225,7 +225,7 @@ static const struct luaL_Reg signal_metatable [] = {
|
||||||
SignalRef::SignalRef(std::weak_ptr<Signal> ref) : signal(ref) {}
|
SignalRef::SignalRef(std::weak_ptr<Signal> ref) : signal(ref) {}
|
||||||
SignalRef::~SignalRef() = default;
|
SignalRef::~SignalRef() = default;
|
||||||
|
|
||||||
const TypeDescriptor SignalRef::TYPE = {
|
const TypeDesc SignalRef::TYPE = {
|
||||||
.name = "Signal",
|
.name = "Signal",
|
||||||
.toString = toVariantFunction(&SignalRef::ToString),
|
.toString = toVariantFunction(&SignalRef::ToString),
|
||||||
.pushLuaValue = toVariantFunction(&SignalRef::PushLuaValue),
|
.pushLuaValue = toVariantFunction(&SignalRef::PushLuaValue),
|
||||||
|
@ -346,7 +346,7 @@ static const struct luaL_Reg signalconnection_metatable [] = {
|
||||||
SignalConnectionRef::SignalConnectionRef(std::weak_ptr<SignalConnection> ref) : signalConnection(ref) {}
|
SignalConnectionRef::SignalConnectionRef(std::weak_ptr<SignalConnection> ref) : signalConnection(ref) {}
|
||||||
SignalConnectionRef::~SignalConnectionRef() = default;
|
SignalConnectionRef::~SignalConnectionRef() = default;
|
||||||
|
|
||||||
const TypeDescriptor SignalConnectionRef::TYPE = {
|
const TypeDesc SignalConnectionRef::TYPE = {
|
||||||
.name = "Signal",
|
.name = "Signal",
|
||||||
.toString = toVariantFunction(&SignalConnectionRef::ToString),
|
.toString = toVariantFunction(&SignalConnectionRef::ToString),
|
||||||
.pushLuaValue = toVariantFunction(&SignalConnectionRef::PushLuaValue),
|
.pushLuaValue = toVariantFunction(&SignalConnectionRef::PushLuaValue),
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
SignalRef(std::weak_ptr<Signal>);
|
SignalRef(std::weak_ptr<Signal>);
|
||||||
~SignalRef();
|
~SignalRef();
|
||||||
|
|
||||||
static const TypeDescriptor TYPE;
|
static const TypeDesc TYPE;
|
||||||
|
|
||||||
operator std::weak_ptr<Signal>();
|
operator std::weak_ptr<Signal>();
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ public:
|
||||||
SignalConnectionRef(std::weak_ptr<SignalConnection>);
|
SignalConnectionRef(std::weak_ptr<SignalConnection>);
|
||||||
~SignalConnectionRef();
|
~SignalConnectionRef();
|
||||||
|
|
||||||
static const TypeDescriptor TYPE;
|
static const TypeDesc TYPE;
|
||||||
|
|
||||||
operator std::weak_ptr<SignalConnection>();
|
operator std::weak_ptr<SignalConnection>();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "datatypes/ref.h"
|
#include "datatypes/ref.h"
|
||||||
#include "datatypes/signal.h"
|
#include "datatypes/signal.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor* VARIANT_TYPES[] {
|
const TypeDesc* VARIANT_TYPES[] {
|
||||||
&NULL_TYPE,
|
&NULL_TYPE,
|
||||||
&BOOL_TYPE,
|
&BOOL_TYPE,
|
||||||
&INT_TYPE,
|
&INT_TYPE,
|
||||||
|
@ -32,15 +33,15 @@ const TypeDescriptor* VARIANT_TYPES[] {
|
||||||
&InstanceRef::TYPE,
|
&InstanceRef::TYPE,
|
||||||
&SignalRef::TYPE,
|
&SignalRef::TYPE,
|
||||||
&SignalConnectionRef::TYPE,
|
&SignalConnectionRef::TYPE,
|
||||||
// &Enum::TYPE,
|
&Enum::TYPE,
|
||||||
// &EnumItem::TYPE,
|
&EnumItem::TYPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TypeInfo Variant::GetTypeInfo() const {
|
const TypeMeta Variant::GetTypeMeta() const {
|
||||||
return VARIANT_TYPES[wrapped.index()];
|
return VARIANT_TYPES[wrapped.index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeDescriptor* Variant::GetType() const {
|
const TypeDesc* Variant::GetType() const {
|
||||||
return VARIANT_TYPES[wrapped.index()];
|
return VARIANT_TYPES[wrapped.index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ void Variant::Serialize(pugi::xml_node node) const {
|
||||||
if (!VARIANT_TYPES[wrapped.index()]->pushLuaValue) {
|
if (!VARIANT_TYPES[wrapped.index()]->pushLuaValue) {
|
||||||
Logger::fatalErrorf("Data type %s does not implement serializer", VARIANT_TYPES[wrapped.index()]->name.c_str());
|
Logger::fatalErrorf("Data type %s does not implement serializer", VARIANT_TYPES[wrapped.index()]->name.c_str());
|
||||||
}
|
}
|
||||||
VARIANT_TYPES[wrapped.index()]->serializer(*this, node);
|
VARIANT_TYPES[wrapped.index()]->serialize(*this, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Variant::PushLuaValue(lua_State* state) const {
|
void Variant::PushLuaValue(lua_State* state) const {
|
||||||
|
@ -65,14 +66,15 @@ void Variant::PushLuaValue(lua_State* state) const {
|
||||||
VARIANT_TYPES[wrapped.index()]->pushLuaValue(*this, state);
|
VARIANT_TYPES[wrapped.index()]->pushLuaValue(*this, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant Variant::Deserialize(pugi::xml_node node, const TypeInfo type) {
|
result<Variant, DataParseError> Variant::Deserialize(pugi::xml_node node, const TypeMeta type) {
|
||||||
if (!type.descriptor->deserializer) {
|
if (!type.descriptor->deserialize) {
|
||||||
Logger::fatalErrorf("Data type %s does not implement deserialize", type.descriptor->name.c_str());
|
Logger::fatalErrorf("Data type %s does not implement deserialize", type.descriptor->name.c_str());
|
||||||
|
return DataParseError(node.text().as_string(), type.descriptor->name);
|
||||||
}
|
}
|
||||||
return type.descriptor->deserializer(node);
|
return type.descriptor->deserialize(node, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, const TypeDescriptor*> TYPE_MAP = {
|
std::map<std::string, const TypeDesc*> TYPE_MAP = {
|
||||||
{ "null", &NULL_TYPE },
|
{ "null", &NULL_TYPE },
|
||||||
{ "bool", &BOOL_TYPE },
|
{ "bool", &BOOL_TYPE },
|
||||||
{ "int", &INT_TYPE },
|
{ "int", &INT_TYPE },
|
||||||
|
@ -82,4 +84,5 @@ std::map<std::string, const TypeDescriptor*> TYPE_MAP = {
|
||||||
{ "CoordinateFrame", &CFrame::TYPE },
|
{ "CoordinateFrame", &CFrame::TYPE },
|
||||||
{ "Color3", &Color3::TYPE },
|
{ "Color3", &Color3::TYPE },
|
||||||
{ "Ref", &InstanceRef::TYPE },
|
{ "Ref", &InstanceRef::TYPE },
|
||||||
|
{ "token", &EnumItem::TYPE },
|
||||||
};
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
#include "datatypes/enum.h"
|
#include "datatypes/enum.h"
|
||||||
#include "datatypes/ref.h"
|
#include "datatypes/ref.h"
|
||||||
#include "datatypes/signal.h"
|
#include "datatypes/signal.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "cframe.h"
|
#include "cframe.h"
|
||||||
|
|
||||||
|
@ -37,16 +39,16 @@ typedef std::variant<
|
||||||
class Variant {
|
class Variant {
|
||||||
__VARIANT_TYPE wrapped;
|
__VARIANT_TYPE wrapped;
|
||||||
public:
|
public:
|
||||||
template <typename T> Variant(T obj) : wrapped(obj) {}
|
template <typename T, std::enable_if_t<std::is_constructible_v<__VARIANT_TYPE, T>, int> = 0> Variant(T obj) : wrapped(obj) {}
|
||||||
template <typename T> T get() { return std::get<T>(wrapped); }
|
template <typename T, std::enable_if_t<std::is_constructible_v<__VARIANT_TYPE, T>, int> = 0> T get() { return std::get<T>(wrapped); }
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
const TypeInfo GetTypeInfo() const;
|
const TypeMeta GetTypeMeta() const;
|
||||||
const TypeDescriptor* GetType() const;
|
const TypeDesc* GetType() const;
|
||||||
|
|
||||||
void Serialize(pugi::xml_node node) const;
|
void Serialize(pugi::xml_node node) const;
|
||||||
void PushLuaValue(lua_State* state) const;
|
void PushLuaValue(lua_State* state) const;
|
||||||
static Variant Deserialize(pugi::xml_node node, const TypeInfo);
|
static result<Variant, DataParseError> Deserialize(pugi::xml_node node, const TypeMeta);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename R, typename ...Args>
|
template <typename T, typename R, typename ...Args>
|
||||||
|
@ -70,5 +72,23 @@ std::function<Variant(Args...)> toVariantGenerator(T(f)(Args...)) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename ...Args, typename ...E>
|
||||||
|
std::function<result<Variant, E...>(Args...)> toVariantGenerator(result<T, E...>(f)(Args...)) {
|
||||||
|
return [f](Args... args) -> result<Variant, E...> {
|
||||||
|
auto result = f(args...);
|
||||||
|
if (result.isSuccess()) return (Variant)(result.success().value());
|
||||||
|
return result.error().value();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename ...Args, typename ...E>
|
||||||
|
std::function<result<Variant, E...>(Args..., const TypeMeta)> toVariantGeneratorNoMeta(result<T, E...>(f)(Args...)) {
|
||||||
|
return [f](Args... args, const TypeMeta) -> result<Variant, E...> {
|
||||||
|
auto result = f(args...);
|
||||||
|
if (result.isSuccess()) return (Variant)(result.success().value());
|
||||||
|
return result.error().value();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Map of all data types to their type names
|
// Map of all data types to their type names
|
||||||
extern std::map<std::string, const TypeDescriptor*> TYPE_MAP;
|
extern std::map<std::string, const TypeDesc*> TYPE_MAP;
|
|
@ -8,6 +8,7 @@
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#include "datatypes/base.h"
|
#include "datatypes/base.h"
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace rp = reactphysics3d;
|
namespace rp = reactphysics3d;
|
||||||
|
@ -87,15 +88,15 @@ void Vector3::Serialize(pugi::xml_node node) const {
|
||||||
node.append_child("Z").text().set(std::to_string(this->Z()));
|
node.append_child("Z").text().set(std::to_string(this->Z()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::Deserialize(pugi::xml_node node) {
|
result<Vector3, DataParseError> Vector3::Deserialize(pugi::xml_node node) {
|
||||||
return Vector3(node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float());
|
return Vector3(node.child("X").text().as_float(), node.child("Y").text().as_float(), node.child("Z").text().as_float());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Variant> Vector3::FromString(std::string string) {
|
result<Vector3, DataParseError> Vector3::FromString(std::string string) {
|
||||||
float components[3];
|
float components[3];
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (string.length() == 0) return std::nullopt;
|
if (string.length() == 0) return DataParseError(string, "Vector3");
|
||||||
while (string[0] == ' ' && string.length() > 0) string.erase(0, 1);
|
while (string[0] == ' ' && string.length() > 0) string.erase(0, 1);
|
||||||
size_t nextPos = string.find(",");
|
size_t nextPos = string.find(",");
|
||||||
if (nextPos == -1) nextPos = string.length();
|
if (nextPos == -1) nextPos = string.length();
|
||||||
|
@ -104,7 +105,7 @@ std::optional<Variant> Vector3::FromString(std::string string) {
|
||||||
|
|
||||||
char* cpos;
|
char* cpos;
|
||||||
float value = std::strtof(term.c_str(), &cpos);
|
float value = std::strtof(term.c_str(), &cpos);
|
||||||
if (cpos == term.c_str()) return std::nullopt;
|
if (cpos == term.c_str()) return DataParseError(string, "Vector3");
|
||||||
|
|
||||||
components[i] = value;
|
components[i] = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
#include "datatypes/annotation.h"
|
#include "datatypes/annotation.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include <glm/ext/vector_float3.hpp>
|
#include <glm/ext/vector_float3.hpp>
|
||||||
#include <glm/geometric.hpp>
|
#include <glm/geometric.hpp>
|
||||||
|
|
||||||
|
@ -24,8 +25,8 @@ public:
|
||||||
virtual const std::string ToString() const;
|
virtual const std::string ToString() const;
|
||||||
virtual void Serialize(pugi::xml_node node) const;
|
virtual void Serialize(pugi::xml_node node) const;
|
||||||
|
|
||||||
static Vector3 Deserialize(pugi::xml_node node);
|
static result<Vector3, DataParseError> Deserialize(pugi::xml_node node);
|
||||||
static std::optional<Variant> FromString(std::string);
|
static result<Vector3, DataParseError> FromString(std::string);
|
||||||
|
|
||||||
static void PushLuaLibrary(lua_State*);
|
static void PushLuaLibrary(lua_State*);
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,10 @@
|
||||||
|
|
||||||
class LuaCastError : public Error {
|
class LuaCastError : public Error {
|
||||||
public:
|
public:
|
||||||
inline LuaCastError(std::string sourceType, std::string targetType) : Error("InstanceCastError", "Attempt to cast " + sourceType + " to " + targetType) {}
|
inline LuaCastError(std::string sourceType, std::string targetType) : Error("LuaCastError", "Attempt to cast " + sourceType + " to " + targetType) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataParseError : public Error {
|
||||||
|
public:
|
||||||
|
inline DataParseError(std::string parsedString, std::string targetType) : Error("DataParseError", "Failed to parse '" + parsedString + "' into value of type " + targetType) {}
|
||||||
};
|
};
|
|
@ -24,6 +24,8 @@ class [[nodiscard]] result {
|
||||||
|
|
||||||
std::variant<success_state, error_state> value;
|
std::variant<success_state, error_state> value;
|
||||||
public:
|
public:
|
||||||
|
// Helper for std::variant, etc.
|
||||||
|
template <typename ...T_Args, std::enable_if_t<std::is_constructible_v<T_Result, T_Args...>, int> = 0> result(T_Args... args) : value(success_state { T_Result(args...) }) {}
|
||||||
result(T_Result success) : value(success_state { success }) {}
|
result(T_Result success) : value(success_state { success }) {}
|
||||||
result(std::variant<T_Errors...> error) : value(error_state { error }) {}
|
result(std::variant<T_Errors...> error) : value(error_state { error }) {}
|
||||||
template <typename T_Error, std::enable_if_t<std::disjunction_v<std::is_same<T_Error, T_Errors>...>, int> = 0>
|
template <typename T_Error, std::enable_if_t<std::disjunction_v<std::is_same<T_Error, T_Errors>...>, int> = 0>
|
||||||
|
@ -61,7 +63,7 @@ public:
|
||||||
|
|
||||||
// Equivalent to .success
|
// Equivalent to .success
|
||||||
operator std::optional<T_Result>() { return success(); }
|
operator std::optional<T_Result>() { return success(); }
|
||||||
operator bool() { return isSuccess(); }
|
explicit operator bool() const { return isSuccess(); } // Explicity is necessary to prevent auto-casting from result to Variant, for instance
|
||||||
bool operator !() { return isError(); }
|
bool operator !() { return isError(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -354,7 +354,12 @@ result<std::shared_ptr<Instance>, NoSuchInstance> Instance::Deserialize(pugi::xm
|
||||||
object->SetPropertyValue(propertyName, InstanceRef()).expect();
|
object->SetPropertyValue(propertyName, InstanceRef()).expect();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Variant value = Variant::Deserialize(propertyNode, meta.type);
|
auto valueResult = Variant::Deserialize(propertyNode, meta.type);
|
||||||
|
if (valueResult.isError()) {
|
||||||
|
valueResult.logError();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto value = valueResult.expect();
|
||||||
object->SetPropertyValue(propertyName, value).expect("Declared property was missing");
|
object->SetPropertyValue(propertyName, value).expect("Declared property was missing");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ enum PropertyCategory {
|
||||||
const int PROPERTY_CATEGORY_MAX = PROP_CATEGORY_SURFACE_INPUT;
|
const int PROPERTY_CATEGORY_MAX = PROP_CATEGORY_SURFACE_INPUT;
|
||||||
|
|
||||||
struct PropertyMeta {
|
struct PropertyMeta {
|
||||||
const TypeInfo type;
|
const TypeMeta type;
|
||||||
PropertyFlags flags;
|
PropertyFlags flags;
|
||||||
PropertyCategory category = PROP_CATEGORY_DATA;
|
PropertyCategory category = PROP_CATEGORY_DATA;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "error/data.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "datatypes/base.h"
|
#include "datatypes/base.h"
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
#include "datatypes/primitives.h"
|
#include "datatypes/primitives.h"
|
||||||
|
#include "error/data.h"
|
||||||
#include "objects/base/member.h"
|
#include "objects/base/member.h"
|
||||||
|
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
|
@ -213,11 +214,12 @@ public:
|
||||||
} else if (meta.type.descriptor->fromString) {
|
} else if (meta.type.descriptor->fromString) {
|
||||||
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
QLineEdit* lineEdit = dynamic_cast<QLineEdit*>(editor);
|
||||||
|
|
||||||
std::optional<Variant> parsedResult = meta.type.descriptor->fromString(lineEdit->text().toStdString());
|
result<Variant, DataParseError> parsedResult = meta.type.descriptor->fromString(lineEdit->text().toStdString(), meta.type);
|
||||||
if (!parsedResult) return;
|
if (!parsedResult) return;
|
||||||
inst->SetPropertyValue(propertyName, parsedResult.value()).expect();
|
Variant parsedValue = parsedResult.expect();
|
||||||
model->setData(index, QString::fromStdString(parsedResult.value().ToString()));
|
inst->SetPropertyValue(propertyName, parsedValue).expect();
|
||||||
view->rebuildCompositeProperty(view->itemFromIndex(index), meta.type.descriptor, parsedResult.value());
|
model->setData(index, QString::fromStdString(parsedValue.ToString()));
|
||||||
|
view->rebuildCompositeProperty(view->itemFromIndex(index), meta.type.descriptor, parsedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -358,7 +360,7 @@ void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const TypeDescriptor* type, Variant value) {
|
void PropertiesView::rebuildCompositeProperty(QTreeWidgetItem *item, const TypeDesc* type, Variant value) {
|
||||||
if (type == &Vector3::TYPE) {
|
if (type == &Vector3::TYPE) {
|
||||||
// https://forum.qt.io/post/266837
|
// https://forum.qt.io/post/266837
|
||||||
foreach(auto i, item->takeChildren()) delete i;
|
foreach(auto i, item->takeChildren()) delete i;
|
||||||
|
|
|
@ -15,7 +15,7 @@ class PropertiesView : public QTreeWidget {
|
||||||
std::weak_ptr<Instance> currentInstance;
|
std::weak_ptr<Instance> currentInstance;
|
||||||
void propertyChanged(QTreeWidgetItem *item, int column);
|
void propertyChanged(QTreeWidgetItem *item, int column);
|
||||||
void activateProperty(QTreeWidgetItem *item, int column);
|
void activateProperty(QTreeWidgetItem *item, int column);
|
||||||
void rebuildCompositeProperty(QTreeWidgetItem *item, const TypeDescriptor*, Variant);
|
void rebuildCompositeProperty(QTreeWidgetItem *item, const TypeDesc*, Variant);
|
||||||
void onPropertyUpdated(std::shared_ptr<Instance> instance, std::string property, Variant newValue);
|
void onPropertyUpdated(std::shared_ptr<Instance> instance, std::string property, Variant newValue);
|
||||||
|
|
||||||
friend PropertiesItemDelegate;
|
friend PropertiesItemDelegate;
|
||||||
|
|
Loading…
Add table
Reference in a new issue