diff --git a/core/resource.cpp b/core/resource.cpp index 44b82e6..e129405 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -1,10 +1,84 @@ #include "resource.h" +#include + #if DATABASES_ENABLED #include "core/database/database.h" #include "core/database/database_manager.h" #endif +//For properties + +typedef std::string String; +typedef std::vector IntVector; +typedef std::vector FloatVector; +typedef std::vector StringVector; +typedef std::vector BoolVector; +typedef std::vector > ResourceVector; + +#define RESOURCE_PROPERTY_GET_IMPL(property_type, type_enum, default_value, func_name) \ + ResourcePropertyBase *p = _property_map[property]; \ + \ + if (!p) { \ + printf("ERROR Resource:: func_name property can't be found! %s\n", property.c_str()); \ + \ + return default_value; \ + } \ + \ + if (p->type != type_enum) { \ + /*If this happens property binding code in this class is incorrect*/ \ + printf("ERROR Resource:: func_name property's type is not property_type! %s\n", property.c_str()); \ + \ + return default_value; \ + } \ + \ + ResourceProperty, std::function > *pp = static_cast, std::function > *>(p); \ + \ + if (!pp) { \ + printf("ERROR Resource:: func_name dynamic cast failed! %s\n", property.c_str()); \ + \ + return default_value; \ + } \ + \ + return pp->getter(this); + +#define RESOURCE_PROPERTY_SET_IMPL(property_type, type_enum, func_name) \ + ResourcePropertyBase *p = _property_map[property]; \ + \ + if (!p) { \ + printf("ERROR Resource:: func_name property can't be found! %s\n", property.c_str()); \ + \ + return; \ + } \ + \ + if (p->type != type_enum) { \ + /*If this happens property binding code in this class is incorrect*/ \ + printf("ERROR Resource:: func_name property's type is not property_type! %s\n", property.c_str()); \ + \ + return; \ + } \ + \ + ResourceProperty, std::function > *pp = static_cast, std::function > *>(p); \ + \ + if (!pp) { \ + printf("ERROR Resource:: func_name dynamic cast failed! %s\n", property.c_str()); \ + \ + return; \ + } \ + \ + return pp->setter(this, data); + +#define RESOURCE_PROPERTY_ADD_IMPL(property_type, type_enum) \ + ResourceProperty, std::function > *prop = new ResourceProperty, std::function >(); \ + \ + prop->type = type_enum; \ + prop->getter = getter; \ + prop->setter = setter; \ + \ + _property_map[name] = prop; + +//Properties stuff end + int Resource::get_id() { return _id; } @@ -106,11 +180,125 @@ std::string Resource::to_json(rapidjson::Document *document) { void Resource::from_json(const std::string &data) { } +//properties + +int Resource::get_int(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(int, TYPE_INT, 0, get_int); +} +float Resource::get_float(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(float, TYPE_FLOAT, 0, get_float); +} +std::string Resource::get_string(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(String, TYPE_STRING, "", get_string); +} +bool Resource::get_bool(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(bool, TYPE_BOOL, 0, get_bool); +} +Ref Resource::get_resource(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(Ref, TYPE_RESOURCE, Ref(), get_resource); +} + +std::vector Resource::get_int_vector(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(IntVector, TYPE_VECTOR_INT, IntVector(), get_int_vector); +} +std::vector Resource::get_float_vector(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(FloatVector, TYPE_VECTOR_FLOAT, FloatVector(), get_float_vector); +} +std::vector Resource::get_string_vector(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(StringVector, TYPE_VECTOR_STRING, StringVector(), get_string_vector); +} +std::vector Resource::get_bool_vector(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(BoolVector, TYPE_VECTOR_BOOL, BoolVector(), get_bool_vector); +} +std::vector > Resource::get_resource_vector(const std::string &property) { + RESOURCE_PROPERTY_GET_IMPL(ResourceVector, TYPE_VECTOR_RESOURCE, ResourceVector(), get_resource_vector); +} + +void Resource::set_int(const std::string &property, const int data) { + RESOURCE_PROPERTY_SET_IMPL(int, TYPE_INT, set_int); +} +void Resource::set_float(const std::string &property, const float data) { + RESOURCE_PROPERTY_SET_IMPL(float, TYPE_FLOAT, get_float); +} +void Resource::set_string(const std::string &property, const std::string &data) { + RESOURCE_PROPERTY_SET_IMPL(String, TYPE_STRING, get_string); +} +void Resource::set_bool(const std::string &property, const bool data) { + RESOURCE_PROPERTY_SET_IMPL(bool, TYPE_BOOL, get_bool); +} +void Resource::set_resource(const std::string &property, const Ref &data) { + RESOURCE_PROPERTY_SET_IMPL(Ref, TYPE_RESOURCE, get_resource); +} + +void Resource::set_int_vector(const std::string &property, const std::vector &data) { + RESOURCE_PROPERTY_SET_IMPL(IntVector, TYPE_VECTOR_INT, get_int_vector); +} + +void Resource::set_float_vector(const std::string &property, const std::vector &data) { + RESOURCE_PROPERTY_SET_IMPL(FloatVector, TYPE_VECTOR_FLOAT, get_float_vector); +} +void Resource::set_string_vector(const std::string &property, const std::vector &data) { + RESOURCE_PROPERTY_SET_IMPL(StringVector, TYPE_VECTOR_STRING, get_string_vector); +} +void Resource::set_bool_vector(const std::string &property, const std::vector &data) { + RESOURCE_PROPERTY_SET_IMPL(BoolVector, TYPE_VECTOR_BOOL, get_bool_vector); +} +void Resource::set_resource_vector(const std::string &property, const std::vector > &data) { + RESOURCE_PROPERTY_SET_IMPL(ResourceVector, TYPE_VECTOR_RESOURCE, get_resource_vector); +} + +void Resource::add_property_int(const std::string &name, std::function getter, std::function setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(int, TYPE_INT); +} +void Resource::add_property_float(const std::string &name, std::function getter, std::function setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(float, TYPE_FLOAT); +} +void Resource::add_property_string(const std::string &name, std::function getter, std::function setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(String, TYPE_STRING); +} +void Resource::add_property_bool(const std::string &name, std::function getter, std::function setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(bool, TYPE_BOOL); +} +void Resource::add_property_resource(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(Ref, TYPE_RESOURCE); +} + +void Resource::add_property_int_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(IntVector, TYPE_VECTOR_INT); +} +void Resource::add_property_float_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(FloatVector, TYPE_VECTOR_FLOAT); +} +void Resource::add_property_string_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(StringVector, TYPE_VECTOR_STRING); +} +void Resource::add_property_bool_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(BoolVector, TYPE_VECTOR_BOOL); +} +void Resource::add_property_resource_vector(const std::string &name, std::function >(Resource *)> getter, std::function >)> setter, const int property_flags) { + RESOURCE_PROPERTY_ADD_IMPL(ResourceVector, TYPE_VECTOR_RESOURCE); +} + +void Resource::register_properties() { + add_property_int("id", &Resource::get_id, &Resource::set_id); +} + Resource::Resource() { _id = 0; _dirty = false; _resource_name = get_class(); + + register_properties(); } Resource::~Resource() { + std::map::iterator it; + + for (it = _property_map.begin(); it != _property_map.end(); it++) { + ResourcePropertyBase *p = it->second; + + if (p) { + delete p; + } + } } \ No newline at end of file diff --git a/core/resource.h b/core/resource.h index 62709d4..3e4275a 100644 --- a/core/resource.h +++ b/core/resource.h @@ -1,6 +1,8 @@ #ifndef RESOURCE_H #define RESOURCE_H +#include +#include #include #include "libs/rapidjson/document.h" @@ -13,6 +15,17 @@ class Database; class Resource : public Reference { RCPP_OBJECT(Resource, Reference); +public: + enum ResourcePropertyFlags { + PROPERTY_FLAG_NONE = 0, + PROPERTY_FLAG_SQL_EXCAPE = 1 << 0, + PROPERTY_FLAG_SANITIZE_HTML_SPECIAL_CHARS = 1 << 1, + PROPERTY_FLAG_DONT_SERIALIZE = 1 << 2, + + PROPERTY_FLAG_USER_INPUT = PROPERTY_FLAG_SQL_EXCAPE, + PROPERTY_FLAG_VISIBLE_INPUT = PROPERTY_FLAG_SQL_EXCAPE | PROPERTY_FLAG_SANITIZE_HTML_SPECIAL_CHARS, + }; + public: int get_id(); void set_id(const int value); @@ -51,11 +64,79 @@ public: std::string to_json(rapidjson::Document *document = nullptr); void from_json(const std::string &data); - //todo properties + //todo add a variant like class. (Or variant itself from godot.) + int get_int(const std::string &property); + float get_float(const std::string &property); + std::string get_string(const std::string &property); + bool get_bool(const std::string &property); + Ref get_resource(const std::string &property); + + std::vector get_int_vector(const std::string &property); + std::vector get_float_vector(const std::string &property); + std::vector get_string_vector(const std::string &property); + std::vector get_bool_vector(const std::string &property); + std::vector > get_resource_vector(const std::string &property); + + void set_int(const std::string &property, const int data); + void set_float(const std::string &property, const float data); + void set_string(const std::string &property, const std::string &data); + void set_bool(const std::string &property, const bool data); + void set_resource(const std::string &property, const Ref &data); + + void set_int_vector(const std::string &property, const std::vector &data); + void set_float_vector(const std::string &property, const std::vector &data); + void set_string_vector(const std::string &property, const std::vector &data); + void set_bool_vector(const std::string &property, const std::vector &data); + void set_resource_vector(const std::string &property, const std::vector > &data); + + void add_property_int(const std::string &name, std::function getter, std::function setter, const int property_flags = 0); + void add_property_float(const std::string &name, std::function getter, std::function setter, const int property_flags = 0); + void add_property_string(const std::string &name, std::function getter, std::function setter, const int property_flags = 0); + void add_property_bool(const std::string &name, std::function getter, std::function setter, const int property_flags = 0); + void add_property_resource(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags = 0); + + void add_property_int_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags = 0); + void add_property_float_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags = 0); + void add_property_string_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags = 0); + void add_property_bool_vector(const std::string &name, std::function(Resource *)> getter, std::function)> setter, const int property_flags = 0); + void add_property_resource_vector(const std::string &name, std::function >(Resource *)> getter, std::function >)> setter, const int property_flags = 0); + + virtual void register_properties(); Resource(); ~Resource(); +protected: + enum ResourcePropertyType { + TYPE_NULL = 0, + TYPE_INT, + TYPE_FLOAT, + TYPE_STRING, + TYPE_BOOL, + TYPE_RESOURCE, + TYPE_VECTOR_INT, + TYPE_VECTOR_FLOAT, + TYPE_VECTOR_STRING, + TYPE_VECTOR_BOOL, + TYPE_VECTOR_RESOURCE, + }; + + struct ResourcePropertyBase { + ResourcePropertyType type; + + ResourcePropertyBase() { + type = TYPE_NULL; + } + }; + + template + struct ResourceProperty : public ResourcePropertyBase { + G getter; + S setter; + }; + + std::map _property_map; + private: int _id; bool _dirty;