Cleaned up the reflection code a bit

* Renamed 'tag' variable to 'handler'
* Removed addAlias stuff, instead check for matching names with if statements
* Added after_reading function that is called by Reader after reading a complete object. This generalizes Packaged::validate, which is now also called via this mechanism.
* Removed some backwards compatibility with <0.3.0 for templates
This commit is contained in:
Twan van Laarhoven
2020-04-26 15:33:59 +02:00
parent 4bebd48786
commit 40d78edf0f
32 changed files with 248 additions and 281 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ IMPLEMENT_REFLECTION(Card) {
} else if (stylesheet_for_reading()) { } else if (stylesheet_for_reading()) {
REFLECT_IF_READING styling_data.init(stylesheet_for_reading()->styling_fields); REFLECT_IF_READING styling_data.init(stylesheet_for_reading()->styling_fields);
REFLECT(styling_data); REFLECT(styling_data);
} else if (tag.reading()) { } else if (Handler::isReading) {
has_styling = false; // We don't know the style, this can be because of copy/pasting has_styling = false; // We don't know the style, this can be because of copy/pasting
} }
} }
+6 -3
View File
@@ -47,7 +47,6 @@ IMPLEMENT_REFLECTION(Field) {
REFLECT(type); REFLECT(type);
} }
REFLECT(name); REFLECT(name);
REFLECT_IF_READING name = canonical_name_form(name);
REFLECT(caption); REFLECT(caption);
REFLECT(description); REFLECT(description);
REFLECT_N("icon", icon_filename); REFLECT_N("icon", icon_filename);
@@ -63,8 +62,12 @@ IMPLEMENT_REFLECTION(Field) {
REFLECT(card_list_name); REFLECT(card_list_name);
REFLECT(sort_script); REFLECT(sort_script);
REFLECT_N("card_list_alignment", card_list_align); REFLECT_N("card_list_alignment", card_list_align);
REFLECT_IF_READING if(caption.empty()) caption = name_to_caption(name); }
REFLECT_IF_READING if(card_list_name.empty()) card_list_name = capitalize(caption);
void Field::after_reading(Version ver) {
name = canonical_name_form(name);
if(caption.empty()) caption = name_to_caption(name);
if(card_list_name.empty()) card_list_name = capitalize(caption);
} }
template <> template <>
+9 -3
View File
@@ -74,6 +74,8 @@ class Field : public IntrusivePtrVirtualBase {
private: private:
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
virtual void after_reading(Version ver);
friend void after_reading(Field& s, Version ver);
}; };
template <> template <>
@@ -82,6 +84,10 @@ inline void update_index(FieldP& f, size_t index) {
f->index = index; f->index = index;
} }
inline void after_reading(Field& f, Version ver) {
f.after_reading(ver);
}
inline String type_name(const Field&) { inline String type_name(const Field&) {
return _TYPE_("field"); return _TYPE_("field");
} }
@@ -258,7 +264,7 @@ inline String type_name(const Value&) {
// ----------------------------------------------------------------------------- : Utilities // ----------------------------------------------------------------------------- : Utilities
#define DECLARE_FIELD_TYPE(Type) \ #define DECLARE_FIELD_TYPE(Type) \
DECLARE_REFLECTION(); public: \ DECLARE_REFLECTION_OVERRIDE(); public: \
virtual ValueP newValue(const FieldP& thisP) const; \ virtual ValueP newValue(const FieldP& thisP) const; \
virtual StyleP newStyle(const FieldP& thisP) const; \ virtual StyleP newStyle(const FieldP& thisP) const; \
virtual String typeName() const virtual String typeName() const
@@ -284,14 +290,14 @@ inline String type_name(const Value&) {
} }
#define DECLARE_STYLE_TYPE(Type) \ #define DECLARE_STYLE_TYPE(Type) \
DECLARE_REFLECTION(); public: \ DECLARE_REFLECTION_OVERRIDE(); public: \
DECLARE_HAS_FIELD(Type) \ DECLARE_HAS_FIELD(Type) \
virtual StyleP clone() const; \ virtual StyleP clone() const; \
virtual ValueViewerP makeViewer(DataViewer& parent, const StyleP& thisP); \ virtual ValueViewerP makeViewer(DataViewer& parent, const StyleP& thisP); \
virtual ValueViewerP makeEditor(DataEditor& parent, const StyleP& thisP) virtual ValueViewerP makeEditor(DataEditor& parent, const StyleP& thisP)
#define DECLARE_VALUE_TYPE(Type,ValueType_) \ #define DECLARE_VALUE_TYPE(Type,ValueType_) \
DECLARE_REFLECTION(); public: \ DECLARE_REFLECTION_OVERRIDE(); public: \
DECLARE_HAS_FIELD(Type) \ DECLARE_HAS_FIELD(Type) \
virtual ValueP clone() const; \ virtual ValueP clone() const; \
virtual String toString() const; \ virtual String toString() const; \
+25 -25
View File
@@ -34,13 +34,14 @@ IMPLEMENT_REFLECTION(ChoiceField) {
REFLECT_N("default", default_script); REFLECT_N("default", default_script);
REFLECT(initial); REFLECT(initial);
REFLECT(default_name); REFLECT(default_name);
REFLECT_IF_READING {
choices->initIds();
}
REFLECT(choice_colors); REFLECT(choice_colors);
REFLECT(choice_colors_cardlist); REFLECT(choice_colors_cardlist);
} }
void ChoiceField::after_reading(Version ver) {
Field::after_reading(ver);
choices->initIds();
}
// ----------------------------------------------------------------------------- : ChoiceField::Choice // ----------------------------------------------------------------------------- : ChoiceField::Choice
ChoiceField::Choice::Choice() ChoiceField::Choice::Choice()
@@ -142,7 +143,9 @@ IMPLEMENT_REFLECTION_ENUM(ChoiceChoiceType) {
} }
IMPLEMENT_REFLECTION(ChoiceField::Choice) { IMPLEMENT_REFLECTION(ChoiceField::Choice) {
if (isGroup() || line_below || enabled.isScripted() || tag.isComplex()) { REFLECT_IF_READING_SINGLE_VALUE {
REFLECT_NAMELESS(name);
} else {
// complex values are groups // complex values are groups
REFLECT(name); REFLECT(name);
REFLECT_N("group_choice", default_name); REFLECT_N("group_choice", default_name);
@@ -150,8 +153,6 @@ IMPLEMENT_REFLECTION(ChoiceField::Choice) {
REFLECT(line_below); REFLECT(line_below);
REFLECT(enabled); REFLECT(enabled);
REFLECT(type); REFLECT(type);
} else {
REFLECT_NAMELESS(name);
} }
} }
@@ -242,33 +243,32 @@ void ChoiceStyle::invalidate() {
} }
IMPLEMENT_REFLECTION_ENUM(ChoicePopupStyle) { IMPLEMENT_REFLECTION_ENUM(ChoicePopupStyle) {
VALUE_N("dropdown", POPUP_DROPDOWN); VALUE_N("dropdown", POPUP_DROPDOWN);
VALUE_N("menu", POPUP_MENU); VALUE_N("menu", POPUP_MENU);
VALUE_N("in place", POPUP_DROPDOWN_IN_PLACE); VALUE_N("in place", POPUP_DROPDOWN_IN_PLACE);
} }
IMPLEMENT_REFLECTION_ENUM(ChoiceRenderStyle) { IMPLEMENT_REFLECTION_ENUM(ChoiceRenderStyle) {
VALUE_N("text", RENDER_TEXT); VALUE_N("text", RENDER_TEXT);
VALUE_N("image", RENDER_IMAGE); VALUE_N("image", RENDER_IMAGE);
VALUE_N("both", RENDER_BOTH); VALUE_N("both", RENDER_BOTH);
VALUE_N("hidden", RENDER_HIDDEN); VALUE_N("hidden", RENDER_HIDDEN);
VALUE_N("image hidden", RENDER_HIDDEN_IMAGE); VALUE_N("image hidden", RENDER_HIDDEN_IMAGE);
VALUE_N("checklist", RENDER_TEXT_CHECKLIST); VALUE_N("checklist", RENDER_TEXT_CHECKLIST);
VALUE_N("image checklist", RENDER_IMAGE_CHECKLIST); VALUE_N("image checklist", RENDER_IMAGE_CHECKLIST);
VALUE_N("both checklist", RENDER_BOTH_CHECKLIST); VALUE_N("both checklist", RENDER_BOTH_CHECKLIST);
VALUE_N("text list", RENDER_TEXT_LIST); VALUE_N("text list", RENDER_TEXT_LIST);
VALUE_N("image list", RENDER_IMAGE_LIST); VALUE_N("image list", RENDER_IMAGE_LIST);
VALUE_N("both list", RENDER_BOTH_LIST); VALUE_N("both list", RENDER_BOTH_LIST);
} }
template <typename T> void reflect_content(T& tag, const ChoiceStyle& cs) {} template <typename T> void reflect_content(T& handler, const ChoiceStyle& cs) {}
template <> void reflect_content(GetMember& tag, const ChoiceStyle& cs) { template <> void reflect_content(GetMember& handler, const ChoiceStyle& cs) {
REFLECT_N("content_width", cs.content_width); REFLECT_N("content_width", cs.content_width);
REFLECT_N("content_height", cs.content_height); REFLECT_N("content_height", cs.content_height);
} }
IMPLEMENT_REFLECTION(ChoiceStyle) { IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT_ALIAS(300, "card_list_colors", "colors_card_list");
REFLECT_BASE(Style); REFLECT_BASE(Style);
REFLECT(popup_style); REFLECT(popup_style);
REFLECT(render_style); REFLECT(render_style);
@@ -277,7 +277,7 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT(font); REFLECT(font);
REFLECT(image); REFLECT(image);
REFLECT(choice_images); REFLECT(choice_images);
reflect_content(tag, *this); reflect_content(handler, *this);
} }
// ----------------------------------------------------------------------------- : ChoiceValue // ----------------------------------------------------------------------------- : ChoiceValue
@@ -301,7 +301,7 @@ bool ChoiceValue::update(Context& ctx) {
} }
IMPLEMENT_REFLECTION_NAMELESS(ChoiceValue) { IMPLEMENT_REFLECTION_NAMELESS(ChoiceValue) {
if (fieldP->save_value || tag.scripting() || tag.reading()) REFLECT_NAMELESS(value); if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(value);
} }
INSTANTIATE_REFLECTION_NAMELESS(ChoiceValue) INSTANTIATE_REFLECTION_NAMELESS(ChoiceValue)
+1
View File
@@ -42,6 +42,7 @@ class ChoiceField : public Field {
map<String,Color> choice_colors_cardlist; ///< Colors for the various choices, for in the card list map<String,Color> choice_colors_cardlist; ///< Colors for the various choices, for in the card list
virtual void initDependencies(Context&, const Dependency&) const; virtual void initDependencies(Context&, const Dependency&) const;
virtual void after_reading(Version ver);
}; };
+2 -2
View File
@@ -39,7 +39,7 @@ IMPLEMENT_REFLECTION(ColorField) {
// ----------------------------------------------------------------------------- : ColorField::Choice // ----------------------------------------------------------------------------- : ColorField::Choice
IMPLEMENT_REFLECTION(ColorField::Choice) { IMPLEMENT_REFLECTION(ColorField::Choice) {
if (tag.reading() && !tag.isComplex()) { REFLECT_IF_READING_SINGLE_VALUE {
REFLECT_NAMELESS(name); REFLECT_NAMELESS(name);
color = parse_color(name); color = parse_color(name);
} else { } else {
@@ -98,5 +98,5 @@ bool ColorValue::update(Context& ctx) {
} }
IMPLEMENT_REFLECTION_NAMELESS(ColorValue) { IMPLEMENT_REFLECTION_NAMELESS(ColorValue) {
if (fieldP->save_value || tag.scripting() || tag.reading()) REFLECT_NAMELESS(value); if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(value);
} }
+7 -7
View File
@@ -39,14 +39,14 @@ String ImageValue::toString() const {
// custom reflection: convert to ScriptImageP for scripting // custom reflection: convert to ScriptImageP for scripting
void ImageValue::reflect(Reader& tag) { void ImageValue::reflect(Reader& handler) {
tag.handle(filename); handler.handle(filename);
} }
void ImageValue::reflect(Writer& tag) { void ImageValue::reflect(Writer& handler) {
if (fieldP->save_value) tag.handle(filename); if (fieldP->save_value) handler.handle(filename);
} }
void ImageValue::reflect(GetMember& tag) {} void ImageValue::reflect(GetMember& handler) {}
void ImageValue::reflect(GetDefaultMember& tag) { void ImageValue::reflect(GetDefaultMember& handler) {
// convert to ScriptImageP for scripting // convert to ScriptImageP for scripting
tag.handle( (ScriptValueP)make_intrusive<ImageValueToImage>(filename, last_update) ); handler.handle( (ScriptValueP)make_intrusive<ImageValueToImage>(filename, last_update) );
} }
+3 -3
View File
@@ -67,13 +67,13 @@ bool PackageChoiceValue::update(Context& ctx) {
return change; return change;
} }
void PackageChoiceValue::reflect(Reader& tag) { void PackageChoiceValue::reflect(Reader& handler) {
REFLECT_NAMELESS(package_name); REFLECT_NAMELESS(package_name);
} }
void PackageChoiceValue::reflect(Writer& tag) { void PackageChoiceValue::reflect(Writer& handler) {
REFLECT_NAMELESS(package_name); REFLECT_NAMELESS(package_name);
} }
void PackageChoiceValue::reflect(GetDefaultMember& tag) { void PackageChoiceValue::reflect(GetDefaultMember& handler) {
if (package_name.empty()) { if (package_name.empty()) {
REFLECT_NAMELESS(package_name); REFLECT_NAMELESS(package_name);
} else if(package_name != field().initial) { } else if(package_name != field().initial) {
+1 -1
View File
@@ -52,5 +52,5 @@ String SymbolValue::toString() const {
} }
IMPLEMENT_REFLECTION_NAMELESS(SymbolValue) { IMPLEMENT_REFLECTION_NAMELESS(SymbolValue) {
if (fieldP->save_value || tag.scripting() || tag.reading()) REFLECT_NAMELESS(filename); if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(filename);
} }
+4 -4
View File
@@ -97,8 +97,8 @@ void TextStyle::checkContentDependencies(Context& ctx, const Dependency& dep) co
alignment.initDependencies(ctx, dep); alignment.initDependencies(ctx, dep);
} }
template <typename T> void reflect_content(T& tag, const TextStyle& ts) {} template <typename T> void reflect_content(T& handler, const TextStyle& ts) {}
template <> void reflect_content(GetMember& tag, const TextStyle& ts) { template <> void reflect_content(GetMember& handler, const TextStyle& ts) {
REFLECT_N("content_width", ts.content_width); REFLECT_N("content_width", ts.content_width);
REFLECT_N("content_height", ts.content_height); REFLECT_N("content_height", ts.content_height);
REFLECT_N("content_lines", ts.content_lines); REFLECT_N("content_lines", ts.content_lines);
@@ -127,7 +127,7 @@ IMPLEMENT_REFLECTION(TextStyle) {
REFLECT(line_height_line_max); REFLECT(line_height_line_max);
REFLECT(paragraph_height); REFLECT(paragraph_height);
REFLECT(direction); REFLECT(direction);
reflect_content(tag, *this); reflect_content(handler, *this);
} }
// ----------------------------------------------------------------------------- : TextValue // ----------------------------------------------------------------------------- : TextValue
@@ -147,7 +147,7 @@ bool TextValue::update(Context& ctx) {
} }
IMPLEMENT_REFLECTION_NAMELESS(TextValue) { IMPLEMENT_REFLECTION_NAMELESS(TextValue) {
if (fieldP->save_value || tag.scripting() || tag.reading()) REFLECT_NAMELESS(value); if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(value);
} }
// ----------------------------------------------------------------------------- : FakeTextValue // ----------------------------------------------------------------------------- : FakeTextValue
+1 -1
View File
@@ -51,7 +51,7 @@ IMPLEMENT_REFLECTION(Game) {
REFLECT_NO_SCRIPT(card_list_color_script); REFLECT_NO_SCRIPT(card_list_color_script);
REFLECT_NO_SCRIPT(statistics_dimensions); REFLECT_NO_SCRIPT(statistics_dimensions);
REFLECT_NO_SCRIPT(statistics_categories); REFLECT_NO_SCRIPT(statistics_categories);
REFLECT_ALIAS(308, "pack_item", "pack_type"); REFLECT_COMPAT(<308, "pack_item", pack_types);
REFLECT_NO_SCRIPT(pack_types); REFLECT_NO_SCRIPT(pack_types);
REFLECT_NO_SCRIPT(keyword_match_script); REFLECT_NO_SCRIPT(keyword_match_script);
REFLECT(has_keywords); REFLECT(has_keywords);
+1 -1
View File
@@ -76,7 +76,7 @@ class Game : public Packaged {
protected: protected:
virtual void validate(Version); virtual void validate(Version);
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
inline String type_name(const Game&) { inline String type_name(const Game&) {
+2 -3
View File
@@ -53,9 +53,8 @@ IMPLEMENT_REFLECTION(KeywordMode) {
// backwards compatability // backwards compatability
template <typename T> void read_compat(T&, const Keyword*) {} template <typename T> void read_compat(T&, const Keyword*) {}
void read_compat(Reader& tag, Keyword* k) { void read_compat(Reader& handler, Keyword* k) {
if (!k->match.empty()) return; if (!k->match.empty()) return;
if (tag.file_app_version >= 301) return; // only for versions < 0.3.1
String separator, parameter; String separator, parameter;
REFLECT(separator); REFLECT(separator);
REFLECT(parameter); REFLECT(parameter);
@@ -84,7 +83,7 @@ bool Keyword::contains(String const& query) const {
IMPLEMENT_REFLECTION(Keyword) { IMPLEMENT_REFLECTION(Keyword) {
REFLECT(keyword); REFLECT(keyword);
read_compat(tag, this); if (handler.formatVersion() < 301) read_compat(handler, this);
REFLECT(match); REFLECT(match);
REFLECT(reminder); REFLECT(reminder);
REFLECT(rules); REFLECT(rules);
+14 -14
View File
@@ -38,24 +38,24 @@ IMPLEMENT_REFLECTION(PackType) {
REFLECT(select); REFLECT(select);
REFLECT(filter); REFLECT(filter);
REFLECT(items); REFLECT(items);
REFLECT_IF_READING { }
if (select == SELECT_AUTO) { void after_reading(PackType& pt, Version) {
if (filter) select = SELECT_NO_REPLACE; if (pt.select == SELECT_AUTO) {
else if (!items.empty()) select = SELECT_ALL; if (pt.filter) pt.select = SELECT_NO_REPLACE;
} else if (!pt.items.empty()) pt.select = SELECT_ALL;
if (indeterminate(summary)) { }
if (filter) summary = true; if (indeterminate(pt.summary)) {
else if (!items.empty()) summary = false; if (pt.filter) pt.summary = true;
} else if (!pt.items.empty()) pt.summary = false;
if (indeterminate(selectable)) { }
if (filter) selectable = false; if (indeterminate(pt.selectable)) {
else if (!items.empty()) selectable = true; if (pt.filter) pt.selectable = false;
} else if (!pt.items.empty()) pt.selectable = true;
} }
} }
IMPLEMENT_REFLECTION(PackItem) { IMPLEMENT_REFLECTION(PackItem) {
if (!tag.isComplex()) { REFLECT_IF_READING_SINGLE_VALUE {
REFLECT_NAMELESS(name); REFLECT_NAMELESS(name);
} else { } else {
REFLECT(name); REFLECT(name);
+1
View File
@@ -56,6 +56,7 @@ class PackType : public IntrusivePtrBase<PackType> {
private: private:
DECLARE_REFLECTION(); DECLARE_REFLECTION();
}; };
void after_reading(PackType&, Version);
/// An item in a PackType /// An item in a PackType
class PackItem : public IntrusivePtrBase<PackItem> { class PackItem : public IntrusivePtrBase<PackItem> {
+10 -10
View File
@@ -167,8 +167,6 @@ void Set::validate(Version file_app_version) {
} }
IMPLEMENT_REFLECTION(Set) { IMPLEMENT_REFLECTION(Set) {
REFLECT_ALIAS(300, "style", "stylesheet"); // < 0.3.0 used style instead of stylesheet
REFLECT_ALIAS(300, "extra_set_info", "styling");
REFLECT(game); REFLECT(game);
if (game) { if (game) {
REFLECT_IF_READING { REFLECT_IF_READING {
@@ -176,29 +174,31 @@ IMPLEMENT_REFLECTION(Set) {
} }
WITH_DYNAMIC_ARG(game_for_reading, game.get()); WITH_DYNAMIC_ARG(game_for_reading, game.get());
REFLECT(stylesheet); REFLECT(stylesheet);
REFLECT_COMPAT(<300, "style", stylesheet);
WITH_DYNAMIC_ARG(stylesheet_for_reading, stylesheet.get()); WITH_DYNAMIC_ARG(stylesheet_for_reading, stylesheet.get());
REFLECT_N("set_info", data); REFLECT_N("set_info", data);
if (stylesheet) { if (stylesheet) {
REFLECT_COMPAT(<300, "extra_set_info", styling_data);
REFLECT_N("styling", styling_data); REFLECT_N("styling", styling_data);
} }
// Experimental: save each card to a different file // Experimental: save each card to a different file
reflect_cards(tag); reflect_cards(handler);
REFLECT(keywords); REFLECT(keywords);
REFLECT(pack_types); REFLECT(pack_types);
} }
reflect_set_info_get_member(tag,data); reflect_set_info_get_member(handler,data);
REFLECT_NO_SCRIPT_N("version_control", vcs); REFLECT_NO_SCRIPT_N("version_control", vcs);
REFLECT(apprentice_code); REFLECT(apprentice_code);
} }
// TODO: make this a more generic function to be used elsewhere // TODO: make this a more generic function to be used elsewhere
template <typename Tag> template <typename Handler>
void Set::reflect_cards (Tag& tag) { void Set::reflect_cards (Handler& handler) {
REFLECT(cards); REFLECT(cards);
} }
template <> template <>
void Set::reflect_cards<Writer> (Writer& tag) { void Set::reflect_cards<Writer> (Writer& handler) {
// When writing to a directory, we write each card in a separate file. // When writing to a directory, we write each card in a separate file.
// We don't do this in zipfiles because it leads to bloat. // We don't do this in zipfiles because it leads to bloat.
if (isZipfile()) { if (isZipfile()) {
@@ -251,9 +251,9 @@ void mark_dependency_member(const Set& set, const String& name, const Dependency
} }
// in scripts, set.something is read from the set_info // in scripts, set.something is read from the set_info
template <typename Tag> template <typename Handler>
void reflect_set_info_get_member(Tag& tag, const IndexMap<FieldP, ValueP>& data) {} void reflect_set_info_get_member(Handler& handler, const IndexMap<FieldP, ValueP>& data) {}
void reflect_set_info_get_member(GetMember& tag, const IndexMap<FieldP, ValueP>& data) { void reflect_set_info_get_member(GetMember& handler, const IndexMap<FieldP, ValueP>& data) {
REFLECT_NAMELESS(data); REFLECT_NAMELESS(data);
} }
+2 -2
View File
@@ -126,8 +126,8 @@ class Set : public Packaged {
private: private:
DECLARE_REFLECTION(); DECLARE_REFLECTION();
template <typename Tag> template <typename Handler>
void reflect_cards (Tag& tag); void reflect_cards(Handler& handler);
/// Object for managing and executing scripts /// Object for managing and executing scripts
unique_ptr<SetScriptManager> script_manager; unique_ptr<SetScriptManager> script_manager;
+1 -3
View File
@@ -242,8 +242,6 @@ String Settings::settingsFile() {
} }
IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) { IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) {
REFLECT_ALIAS(300, "style_settings", "stylesheet_settings");
REFLECT_ALIAS(300, "default_style_settings", "default_stylesheet_settings");
REFLECT(locale); REFLECT(locale);
REFLECT(recent_sets); REFLECT(recent_sets);
REFLECT(default_set_dir); REFLECT(default_set_dir);
@@ -264,7 +262,7 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) {
#if USE_OLD_STYLE_UPDATE_CHECKER #if USE_OLD_STYLE_UPDATE_CHECKER
REFLECT(updates_url); REFLECT(updates_url);
#else #else
REFLECT_IGNORE(306,"updates_url"); REFLECT_COMPAT_IGNORE(<306,"updates_url",String);
#endif #endif
REFLECT(package_versions_url); REFLECT(package_versions_url);
REFLECT(installer_list_url); REFLECT(installer_list_url);
-10
View File
@@ -91,16 +91,6 @@ void mark_dependency_value(const StyleSheet& stylesheet, const Dependency& dep)
IMPLEMENT_REFLECTION(StyleSheet) { IMPLEMENT_REFLECTION(StyleSheet) {
// < 0.3.0 didn't use card_ prefix
REFLECT_ALIAS(300, "width", "card_width");
REFLECT_ALIAS(300, "height", "card_height");
REFLECT_ALIAS(300, "dpi", "card_dpi");
REFLECT_ALIAS(300, "background", "card_background");
REFLECT_ALIAS(300, "info_style", "set_info_style");
REFLECT_ALIAS(300, "align", "alignment");
REFLECT_ALIAS(300, "extra_field", "styling_field");
REFLECT_ALIAS(300, "extra_style", "styling_style");
REFLECT(game); REFLECT(game);
REFLECT_BASE(Packaged); REFLECT_BASE(Packaged);
REFLECT(card_width); REFLECT(card_width);
+19 -23
View File
@@ -27,10 +27,10 @@ IMPLEMENT_REFLECTION(ControlPoint) {
REFLECT_N("position", pos); REFLECT_N("position", pos);
REFLECT_N("lock", lock); REFLECT_N("lock", lock);
REFLECT_N("line_after", segment_after); REFLECT_N("line_after", segment_after);
if (tag.reading() || segment_before == SEGMENT_CURVE) { if (Handler::isReading || segment_before == SEGMENT_CURVE) {
REFLECT_N("handle_before", delta_before); REFLECT_N("handle_before", delta_before);
} }
if (tag.reading() || segment_after == SEGMENT_CURVE) { if (Handler::isReading || segment_after == SEGMENT_CURVE) {
REFLECT_N("handle_after", delta_after); REFLECT_N("handle_after", delta_after);
} }
} }
@@ -155,32 +155,28 @@ IMPLEMENT_REFLECTION_ENUM(SymbolShapeCombine) {
VALUE_N("border", SYMBOL_COMBINE_BORDER); VALUE_N("border", SYMBOL_COMBINE_BORDER);
} }
template<typename T> void fix(const T&,SymbolShape&) {}
void fix(const Reader& reader, SymbolShape& shape) {
if (reader.file_app_version != Version()) return;
shape.updateBounds();
if (shape.bounds.max.x < 100 || shape.bounds.max.y < 100) return;
// this is a <= 0.1.2 symbol, points range [0...500] instead of [0...1]
// adjust it
FOR_EACH(p, shape.points) {
p->pos /= 500.0;
p->delta_before /= 500.0;
p->delta_after /= 500.0;
}
if (shape.name.empty()) shape.name = _("Shape");
shape.updateBounds();
}
IMPLEMENT_REFLECTION(SymbolShape) { IMPLEMENT_REFLECTION(SymbolShape) {
REFLECT_BASE(SymbolPart); REFLECT_BASE(SymbolPart);
REFLECT(combine); REFLECT(combine);
REFLECT(points); REFLECT(points);
}
void after_reading(SymbolShape& shape, Version version) {
// Fixes after reading // Fixes after reading
REFLECT_IF_READING { // enforce constraints
// enforce constraints shape.enforceConstraints();
enforceConstraints(); if (version == Version()) {
fix(tag,*this); // this is a <= 0.1.2 symbol, points range [0...500] instead of [0...1]
shape.updateBounds();
if (shape.bounds.max.x < 100 || shape.bounds.max.y < 100) return;
// adjust it
FOR_EACH(p, shape.points) {
p->pos /= 500.0;
p->delta_before /= 500.0;
p->delta_after /= 500.0;
}
if (shape.name.empty()) shape.name = _("Shape");
shape.updateBounds();
} }
} }
+5 -4
View File
@@ -220,8 +220,9 @@ class SymbolShape : public SymbolPart {
/// Calculate the position and size of the part using the given rotation matrix /// Calculate the position and size of the part using the given rotation matrix
virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity); virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity);
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
void after_reading(SymbolShape&, Version);
// ----------------------------------------------------------------------------- : SymbolGroup // ----------------------------------------------------------------------------- : SymbolGroup
@@ -242,7 +243,7 @@ class SymbolGroup : public SymbolPart {
virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity); virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity);
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
// ----------------------------------------------------------------------------- : SymbolSymmetry // ----------------------------------------------------------------------------- : SymbolSymmetry
@@ -273,7 +274,7 @@ class SymbolSymmetry : public SymbolGroup {
String expectedName() const; String expectedName() const;
virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity); virtual Bounds calculateBounds(const Vector2D& origin, const Matrix2D& m, bool is_identity);
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
// ----------------------------------------------------------------------------- : Symbol // ----------------------------------------------------------------------------- : Symbol
@@ -287,7 +288,7 @@ class Symbol : public SymbolGroup {
/// Determine the aspect ratio best suited for this symbol /// Determine the aspect ratio best suited for this symbol
double aspectRatio() const; double aspectRatio() const;
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
/// A default symbol: a square /// A default symbol: a square
+6 -7
View File
@@ -47,8 +47,6 @@ SymbolFontP SymbolFont::byName(const String& name) {
IMPLEMENT_REFLECTION(SymbolFont) { IMPLEMENT_REFLECTION(SymbolFont) {
REFLECT_BASE(Packaged); REFLECT_BASE(Packaged);
REFLECT_ALIAS(300, "text_align", "text_alignment");
REFLECT_N("image_font_size", img_size); REFLECT_N("image_font_size", img_size);
REFLECT_N("horizontal_space", spacing.width); REFLECT_N("horizontal_space", spacing.width);
REFLECT_N("vertical_space", spacing.height); REFLECT_N("vertical_space", spacing.height);
@@ -179,6 +177,7 @@ IMPLEMENT_REFLECTION(SymbolInFont) {
REFLECT(draw_text); REFLECT(draw_text);
REFLECT(text_font); REFLECT(text_font);
REFLECT(text_alignment); REFLECT(text_alignment);
REFLECT_COMPAT(<300,"text_align",text_alignment);
REFLECT(text_margin_left); REFLECT(text_margin_left);
REFLECT(text_margin_right); REFLECT(text_margin_right);
REFLECT(text_margin_top); REFLECT(text_margin_top);
@@ -525,18 +524,18 @@ IMPLEMENT_REFLECTION_ENUM(MenuItemType) {
VALUE_N("code", ITEM_CODE); VALUE_N("code", ITEM_CODE);
VALUE_N("custom", ITEM_CUSTOM); VALUE_N("custom", ITEM_CUSTOM);
VALUE_N("line", ITEM_LINE); VALUE_N("line", ITEM_LINE);
VALUE_N("submenu", ITEM_SUBMENU); VALUE_N("submenu", ITEM_SUBMENU);
} }
IMPLEMENT_REFLECTION_NO_GET_MEMBER(InsertSymbolMenu) { IMPLEMENT_REFLECTION_NO_GET_MEMBER(InsertSymbolMenu) {
if (!items.empty() || (tag.reading() && tag.isComplex())) { REFLECT_IF_READING_SINGLE_VALUE_AND(items.empty()) {
REFLECT_NAMELESS(name);
} else {
// complex values are groups // complex values are groups
REFLECT(type); REFLECT(type);
REFLECT(name); REFLECT(name);
REFLECT(items); REFLECT(items);
if (!items.empty()) type = ITEM_SUBMENU; if (Handler::isReading && !items.empty()) type = ITEM_SUBMENU;
} else {
REFLECT_NAMELESS(name);
} }
} }
template <> void GetDefaultMember::handle(const InsertSymbolMenu& m) { template <> void GetDefaultMember::handle(const InsertSymbolMenu& m) {
+1 -1
View File
@@ -17,7 +17,7 @@ WordListWord::WordListWord()
{} {}
IMPLEMENT_REFLECTION_NO_SCRIPT(WordListWord) { IMPLEMENT_REFLECTION_NO_SCRIPT(WordListWord) {
if (line_below || is_prefix || isGroup() || script || (tag.reading() && tag.isComplex())) { REFLECT_IF_READING_SINGLE_VALUE {
// complex value // complex value
REFLECT(name); REFLECT(name);
REFLECT(line_below); REFLECT(line_below);
+3 -3
View File
@@ -67,7 +67,7 @@ class SolidFillSymbolFilter : public SymbolFilter {
virtual bool operator == (const SymbolFilter& that) const; virtual bool operator == (const SymbolFilter& that) const;
private: private:
Color fill_color, border_color; Color fill_color, border_color;
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
/// Symbol filter that returns some gradient /// Symbol filter that returns some gradient
@@ -85,7 +85,7 @@ class GradientSymbolFilter : public SymbolFilter {
Color color(double x, double y, SymbolSet point, const T* t) const; Color color(double x, double y, SymbolSet point, const T* t) const;
bool equal(const GradientSymbolFilter& that) const; bool equal(const GradientSymbolFilter& that) const;
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
/// Symbol filter that returns a linear gradient /// Symbol filter that returns a linear gradient
@@ -106,7 +106,7 @@ class LinearGradientSymbolFilter : public GradientSymbolFilter {
double center_x, center_y; double center_x, center_y;
double end_x, end_y; double end_x, end_y;
mutable double len; mutable double len;
DECLARE_REFLECTION(); DECLARE_REFLECTION_OVERRIDE();
}; };
/// Symbol filter that returns a radial gradient /// Symbol filter that returns a radial gradient
+1 -1
View File
@@ -36,7 +36,7 @@ GetMember::GetMember(const String& name)
: target_name(name) : target_name(name)
{} {}
// caused by the pattern: if (!tag.isComplex()) { REFLECT_NAMELESS(stuff) } // caused by the pattern: if (!handler.isCompound()) { REFLECT_NAMELESS(stuff) }
template <> void GetMember::handle(const String& v) { template <> void GetMember::handle(const String& v) {
throw InternalError(_("GetDefaultMember::handle")); throw InternalError(_("GetDefaultMember::handle"));
} }
+25 -25
View File
@@ -22,13 +22,13 @@ template <typename T> class Scriptable;
/// Find a member without a name using reflection /// Find a member without a name using reflection
/** The member is wrapped in a ScriptValue */ /** The member is wrapped in a ScriptValue */
class GetDefaultMember { class GetDefaultMember {
public: public:
/// Tell the reflection code we are not reading /// Tell the reflection code we are not looking at members
inline bool reading() const { return false; } static constexpr bool isReading = false;
inline bool scripting() const { return true; } static constexpr bool isWriting = false;
inline bool isComplex() const { return false; } static constexpr bool isScripting = false;
inline void addAlias(int, const Char*, const Char*) {} inline bool isCompound() const { return true; }
inline void handleIgnore(int, const Char*) {} inline Version formatVersion() const { return app_version; }
/// The result, or script_nil if the member was not found /// The result, or script_nil if the member was not found
inline ScriptValueP result() { return value; } inline ScriptValueP result() { return value; }
@@ -57,25 +57,25 @@ class GetDefaultMember {
template <typename T> void handle(const intrusive_ptr<T>& p) { value = to_script(p); } template <typename T> void handle(const intrusive_ptr<T>& p) { value = to_script(p); }
void handle(const ScriptValueP&); void handle(const ScriptValueP&);
void handle(const ScriptP&); void handle(const ScriptP&);
private: private:
ScriptValueP value; ///< The value we found (if any) ScriptValueP value; ///< The value we found (if any)
}; };
// ----------------------------------------------------------------------------- : GetMember // ----------------------------------------------------------------------------- : GetMember
/// Find a member with a specific name using reflection /// Find a member with a specific name using reflection
/** The member is wrapped in a ScriptValue */ /** The member is wrapped in a ScriptValue */
class GetMember : private GetDefaultMember { class GetMember {
public: public:
/// Construct a member getter that looks for the given name /// Construct a member getter that looks for the given name
GetMember(const String& name); GetMember(const String& name);
/// Tell the reflection code we are not reading /// Tell the reflection code we are getting a member for scripting purposes
inline bool reading() const { return false; } static constexpr bool isReading = true;
inline bool scripting() const { return true; } static constexpr bool isWriting = false;
inline bool isComplex() const { return true; } static constexpr bool isScripting = false;
inline void addAlias(int, const Char*, const Char*) {} inline bool isCompound() const { return true; }
inline void handleIgnore(int, const Char*) {} inline Version formatVersion() const { return app_version; }
/// The result, or script_nil if the member was not found /// The result, or script_nil if the member was not found
inline ScriptValueP result() { return gdm.result(); } inline ScriptValueP result() { return gdm.result(); }
@@ -120,17 +120,17 @@ class GetMember : private GetDefaultMember {
#define REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetDefaultMember) #define REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetDefaultMember)
#define REFLECT_OBJECT_GET_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetMember) #define REFLECT_OBJECT_GET_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetMember)
#define REFLECT_WRITE_YES(Cls, Tag) \ #define REFLECT_WRITE_YES(Cls, Handler) \
template<> void Tag::handle<Cls>(const Cls& object) { \ template<> void Handler::handle<Cls>(const Cls& object) { \
const_cast<Cls&>(object).reflect(*this); \ const_cast<Cls&>(object).reflect(*this); \
} \ } \
void Cls::reflect(Tag& tag) { \ void Cls::reflect(Handler& handler) { \
reflect_impl(tag); \ reflect_impl(handler); \
} }
#define REFLECT_WRITE_NO(Cls, Tag) \ #define REFLECT_WRITE_NO(Cls, Handler) \
template<> void Tag::handle<Cls>(const Cls& object) {} \ template<> void Handler::handle<Cls>(const Cls& object) {} \
void Cls::reflect(Tag& tag) {} void Cls::reflect(Handler& handler) {}
// ----------------------------------------------------------------------------- : Reflection for enumerations // ----------------------------------------------------------------------------- : Reflection for enumerations
@@ -141,7 +141,7 @@ class GetMember : private GetDefaultMember {
reflect_ ## Enum(const_cast<Enum&>(enum_), egm); \ reflect_ ## Enum(const_cast<Enum&>(enum_), egm); \
} }
/// 'Tag' to be used when reflecting enumerations for GetMember /// Handler to be used when reflecting enumerations for GetMember
class EnumGetMember { class EnumGetMember {
public: public:
inline EnumGetMember(GetDefaultMember& gdm) inline EnumGetMember(GetDefaultMember& gdm)
+2 -4
View File
@@ -458,7 +458,7 @@ DateTime Package::modificationTime(const pair<String, FileInfo>& fi) const {
// ----------------------------------------------------------------------------- : Packaged // ----------------------------------------------------------------------------- : Packaged
template <> void Reader::handle(PackageDependency& dep) { template <> void Reader::handle(PackageDependency& dep) {
if (!isComplex()) { if (!isCompound()) {
handle(dep.package); handle(dep.package);
size_t pos = dep.package.find_first_of(_(' ')); size_t pos = dep.package.find_first_of(_(' '));
if (pos != String::npos) { if (pos != String::npos) {
@@ -504,7 +504,7 @@ unique_ptr<wxInputStream> Packaged::openIconFile() {
} }
} }
// proxy object, that reads just WITHOUT using the overloaded behaviour // proxy object, that reads just the package header WITHOUT using the overloaded behaviour
struct JustAsPackageProxy { struct JustAsPackageProxy {
JustAsPackageProxy(Packaged* that) : that(that) {} JustAsPackageProxy(Packaged* that) : that(that) {}
Packaged* that; Packaged* that;
@@ -524,7 +524,6 @@ void Packaged::open(const String& package, bool just_header) {
try { try {
JustAsPackageProxy proxy(this); JustAsPackageProxy proxy(this);
reader.handle_greedy(proxy); reader.handle_greedy(proxy);
Packaged::validate(reader.file_app_version);
} catch (const ParseError& err) { } catch (const ParseError& err) {
throw FileParseError(err.what(), absoluteFilename() + _("/") + typeName()); // more detailed message throw FileParseError(err.what(), absoluteFilename() + _("/") + typeName()); // more detailed message
} }
@@ -539,7 +538,6 @@ void Packaged::loadFully() {
Reader reader(*stream, this, absoluteFilename() + _("/") + typeName()); Reader reader(*stream, this, absoluteFilename() + _("/") + typeName());
try { try {
reader.handle_greedy(*this); reader.handle_greedy(*this);
validate(reader.file_app_version);
fully_loaded = true; // only after loading and validating succeeded, be careful with recursion! fully_loaded = true; // only after loading and validating succeeded, be careful with recursion!
} catch (const ParseError& err) { } catch (const ParseError& err) {
throw FileParseError(err.what(), absoluteFilename() + _("/") + typeName()); // more detailed message throw FileParseError(err.what(), absoluteFilename() + _("/") + typeName()); // more detailed message
+5
View File
@@ -255,6 +255,7 @@ class Packaged : public Package {
virtual Version fileVersion() const = 0; virtual Version fileVersion() const = 0;
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
friend void after_reading(Packaged& p, Version file_app_version);
private: private:
bool fully_loaded; ///< Is the package fully loaded? bool fully_loaded; ///< Is the package fully loaded?
@@ -262,6 +263,10 @@ class Packaged : public Package {
friend class Installer; friend class Installer;
}; };
inline void after_reading(Packaged& p, Version file_app_version) {
p.validate(file_app_version);
}
// ----------------------------------------------------------------------------- : IncludePackage // ----------------------------------------------------------------------------- : IncludePackage
/// A package that just contains a bunch of files that are used from other packages /// A package that just contains a bunch of files that are used from other packages
-26
View File
@@ -37,12 +37,6 @@ unique_ptr<wxInputStream> Reader::openIncludedFile() {
return package_manager.openFileFromPackage(package, value); return package_manager.openFileFromPackage(package, value);
} }
void Reader::addAlias(Version end_version, const Char* a, const Char* b) {
Alias& alias = aliasses[a];
alias.new_key = b;
alias.end_version = end_version;
}
void Reader::handleIgnore(int end_version, const Char* a) { void Reader::handleIgnore(int end_version, const Char* a) {
if (file_app_version < end_version) { if (file_app_version < end_version) {
if (enterBlock(a)) exitBlock(); if (enterBlock(a)) exitBlock();
@@ -243,26 +237,6 @@ void Reader::unknownKey() {
} while (indent > expected_indent); } while (indent > expected_indent);
return; return;
} }
// aliasses?
map<String,Alias>::const_iterator it = aliasses.find(key);
if (it != aliasses.end()) {
if (aliasses.find(it->second.new_key) != aliasses.end()) {
// alias points to another alias, don't follow it, there is the risk of infinite loops
} else if (it->second.end_version <= file_app_version) {
// alias not used for this version, use in warning
if (indent == expected_indent) {
warning(_("Unexpected key: '") + key + _("' use '") + it->second.new_key + _("'"), 0, false);
do {
moveNext();
} while (indent > expected_indent);
return;
}
} else {
// try this key instead
key = it->second.new_key;
return;
}
}
if (indent >= expected_indent) { if (indent >= expected_indent) {
warning(_("Unexpected key: '") + key + _("'"), 0, false); warning(_("Unexpected key: '") + key + _("'"), 0, false);
do { do {
+21 -22
View File
@@ -28,30 +28,25 @@ class Packaged;
* object that was just read. * object that was just read.
*/ */
class Reader { class Reader {
private:
/// Construct a reader that reads a file in a package
/** Used for "include file" keys.
* package can be nullptr
*/
//Reader(Reader* parent, Packaged* package, const String& filename, bool ignore_invalid = false);
public: public:
/// Construct a reader that reads from the given input stream /// Construct a reader that reads from the given input stream
/** filename is used only for error messages /** filename is used only for error messages
* package is used for looking up included files.
*/ */
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false); Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
~Reader() { showWarnings(); } ~Reader() { showWarnings(); }
/// Tell the reflection code we are reading /// Tell the reflection code we are reading
inline bool reading() const { return true; } static constexpr bool isReading = true;
/// Tell the reflection code we are not related to scripting static constexpr bool isWriting = false;
inline bool scripting() const { return false; } static constexpr bool isScripting = false;
/// Is the thing currently being read 'complex', i.e. does it have children /// Is the thing currently being read 'complex', i.e. does it have children
inline bool isComplex() const { return indent != expected_indent - 1 || value.empty(); } inline bool isCompound() const { return indent != expected_indent - 1 || value.empty(); }
/// Add a as an alias for b, all keys a will be replaced with b, only if file_app_version < end_version
void addAlias(Version end_version, const Char* a, const Char* b);
/// Ignore old keys /// Ignore old keys
void handleIgnore(int, const Char*); void handleIgnore(int, const Char*);
/// Get the version of the format we are reading
inline Version formatVersion() const { return file_app_version; }
/// Read and check the application version /// Read and check the application version
void handleAppVersion(); void handleAppVersion();
@@ -70,6 +65,7 @@ class Reader {
if (state != HANDLED) unknownKey(object); if (state != HANDLED) unknownKey(object);
state = OUTSIDE; state = OUTSIDE;
} while (indent >= expected_indent); } while (indent >= expected_indent);
after_reading(object, file_app_version);
} }
/// Handle an object: read it if it's name matches /// Handle an object: read it if it's name matches
@@ -112,10 +108,10 @@ class Reader {
/// The package being read from /// The package being read from
inline Packaged* getPackage() const { return package; } inline Packaged* getPackage() const { return package; }
private:
// --------------------------------------------------- : Data // --------------------------------------------------- : Data
/// App version this file was made with /// App version this file was made with
Version file_app_version; Version file_app_version;
private:
/// The line we read /// The line we read
String line; String line;
/// The key and value of the last line we read /// The key and value of the last line we read
@@ -133,13 +129,6 @@ private:
HANDLED, ///< We have handled a value, and moved to the next line, previous_value is the value we just handled HANDLED, ///< We have handled a value, and moved to the next line, previous_value is the value we just handled
UNHANDLED, ///< Something has been 'unhandled()' UNHANDLED, ///< Something has been 'unhandled()'
} state; } state;
/// Aliasses for compatability
struct Alias {
String new_key;
Version end_version;
};
/// Aliasses for compatability
map<String, Alias> aliasses;
/// Should all invalid keys be ignored? /// Should all invalid keys be ignored?
bool ignore_invalid; bool ignore_invalid;
@@ -194,6 +183,16 @@ private:
unique_ptr<wxInputStream> openIncludedFile(); unique_ptr<wxInputStream> openIncludedFile();
}; };
// ----------------------------------------------------------------------------- : After reading hook
// Overload to perform extra stuff after reading
template <typename T> inline void after_reading(T&, Version) {}
template <typename T>
inline void after_reading(intrusive_ptr<T>& x, Version ver) {
after_reading(*x, ver);
}
// ----------------------------------------------------------------------------- : Container types // ----------------------------------------------------------------------------- : Container types
/// Construct a new type, possibly reading something in the process. /// Construct a new type, possibly reading something in the process.
@@ -266,10 +265,10 @@ void Reader::handle(IndexMap<K,V>& m) {
reader.errorIfNotDone(); \ reader.errorIfNotDone(); \
} }
/// 'Tag' to be used when reflecting enumerations for Reader /// 'Handler' to be used when reflecting enumerations for Reader
class EnumReader { class EnumReader {
public: public:
inline EnumReader(String read) inline EnumReader(String const& read)
: read(read), first(nullptr), done(false) {} : read(read), first(nullptr), done(false) {}
/// Handle a possible value for the enum, if the name matches the name in the input /// Handle a possible value for the enum, if the name matches the name in the input
+6 -6
View File
@@ -25,11 +25,11 @@ class Writer {
Writer(OutputStream& output, Version file_app_version); Writer(OutputStream& output, Version file_app_version);
/// Tell the reflection code we are not reading /// Tell the reflection code we are not reading
inline bool reading() const { return false; } static constexpr bool isReading = false;
inline bool scripting() const { return false; } static constexpr bool isWriting = true;
inline bool isComplex() const { return true; } static constexpr bool isScripting = false;
inline void addAlias(int, const Char*, const Char*) {} inline bool isCompound() const { return true; }
inline void handleIgnore(int, const Char*) {} inline Version formatVersion() const { return app_version; }
// --------------------------------------------------- : Handling objects // --------------------------------------------------- : Handling objects
/// Handle an object: write it under the given name /// Handle an object: write it under the given name
@@ -145,7 +145,7 @@ void Writer::handle(const IndexMap<K,V>& m) {
reflect_ ## Enum(const_cast<Enum&>(enum_), writer); \ reflect_ ## Enum(const_cast<Enum&>(enum_), writer); \
} }
/// 'Tag' to be used when reflecting enumerations for Writer /// Handler to be used when reflecting enumerations for Writer
class EnumWriter { class EnumWriter {
public: public:
inline EnumWriter(Writer& writer) inline EnumWriter(Writer& writer)
+44 -47
View File
@@ -22,32 +22,24 @@
/// Declare that a class supports reflection /// Declare that a class supports reflection
/** Reflection allows the member variables of a class to be inspected at runtime. /** Reflection allows the member variables of a class to be inspected at runtime.
*/ */
#define DECLARE_REFLECTION() \ #define DECLARE_REFLECTION_PREFIX(PREFIX,SUFFIX) \
protected: \ protected: \
template<class Tag> void reflect_impl(Tag& tag); \ template<class Handler> void reflect_impl(Handler&); \
friend class Reader; \ friend class Reader; \
friend class Writer; \ friend class Writer; \
friend class GetDefaultMember; \ friend class GetDefaultMember; \
friend class GetMember; \ friend class GetMember; \
void reflect(Reader& reader); \ PREFIX void reflect(Reader& reader) SUFFIX; \
void reflect(Writer& writer); \ PREFIX void reflect(Writer& writer) SUFFIX; \
void reflect(GetDefaultMember& gdm); \ PREFIX void reflect(GetDefaultMember& gdm) SUFFIX; \
void reflect(GetMember& gm) PREFIX void reflect(GetMember& gm) SUFFIX
#define DECLARE_REFLECTION() DECLARE_REFLECTION_PREFIX(,)
/// Declare that a class supports reflection, which can be overridden in derived classes /// Declare that a class supports reflection, which can be overridden in derived classes
#define DECLARE_REFLECTION_VIRTUAL() \ #define DECLARE_REFLECTION_VIRTUAL() DECLARE_REFLECTION_PREFIX(virtual,)
protected: \
template<class Tag> void reflect_impl(Tag& tag); \ #define DECLARE_REFLECTION_OVERRIDE() DECLARE_REFLECTION_PREFIX(,override)
friend class Reader; \
friend class Writer; \
friend class GetDefaultMember; \
friend class GetMember; \
/* extra level of indirection between Tag::handle \
* and reflect_impl, to allow for virtual */ \
virtual void reflect(Reader& reader); \
virtual void reflect(Writer& writer); \
virtual void reflect(GetDefaultMember& gdm); \
virtual void reflect(GetMember& gm)
// ----------------------------------------------------------------------------- : Implementing reflection // ----------------------------------------------------------------------------- : Implementing reflection
@@ -71,8 +63,8 @@
REFLECT_OBJECT_WRITER(Cls) \ REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \ REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \
REFLECT_OBJECT_GET_MEMBER(Cls) \ REFLECT_OBJECT_GET_MEMBER(Cls) \
template <class Tag> \ template <class Handler> \
void Cls::reflect_impl(Tag& tag) void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls that only uses REFLECT_NAMELESS /// Implement the refelection of a class type Cls that only uses REFLECT_NAMELESS
#define IMPLEMENT_REFLECTION_NAMELESS(Cls) \ #define IMPLEMENT_REFLECTION_NAMELESS(Cls) \
@@ -80,16 +72,16 @@
REFLECT_OBJECT_WRITER(Cls) \ REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER(Cls) \ REFLECT_OBJECT_GET_DEFAULT_MEMBER(Cls) \
REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \ REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \
template <class Tag> \ template <class Handler> \
void Cls::reflect_impl(Tag& tag) void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls, but only for Reader and Writer, /// Implement the refelection of a class type Cls, but only for Reader and Writer,
/** There is custom code for GetMember and GetDefaultMember */ /** There is custom code for GetMember and GetDefaultMember */
#define IMPLEMENT_REFLECTION_NO_GET_MEMBER(Cls) \ #define IMPLEMENT_REFLECTION_NO_GET_MEMBER(Cls) \
REFLECT_OBJECT_READER(Cls) \ REFLECT_OBJECT_READER(Cls) \
REFLECT_OBJECT_WRITER(Cls) \ REFLECT_OBJECT_WRITER(Cls) \
template <class Tag> \ template <class Handler> \
void Cls::reflect_impl(Tag& tag) void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls, but only for Reader and Writer /// Implement the refelection of a class type Cls, but only for Reader and Writer
/** There is no code for GetMember and GetDefaultMember */ /** There is no code for GetMember and GetDefaultMember */
@@ -98,18 +90,18 @@
REFLECT_OBJECT_WRITER(Cls) \ REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \ REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \
REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \ REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \
template <class Tag> \ template <class Handler> \
void Cls::reflect_impl(Tag& tag) void Cls::reflect_impl(Handler& handler)
/// Reflect a variable /// Reflect a variable
#define REFLECT(var) tag.handle(_(#var), var) #define REFLECT(var) handler.handle(_(#var), var)
/// Reflect a variable under the given name /// Reflect a variable under the given name
#define REFLECT_N(name, var) tag.handle(_(name), var) #define REFLECT_N(name, var) handler.handle(_(name), var)
/// Reflect a variable without a name, should be used only once per class /// Reflect a variable without a name, should be used only once per class
#define REFLECT_NAMELESS(var) tag.handle(var) #define REFLECT_NAMELESS(var) handler.handle(var)
/// Declare that the variables of a base class should also be reflected /// Declare that the variables of a base class should also be reflected
#define REFLECT_BASE(Base) Base::reflect_impl(tag) #define REFLECT_BASE(Base) Base::reflect_impl(handler)
/// Reflect a group of declarations only when reading /// Reflect a group of declarations only when reading
/** Usage: /** Usage:
@@ -119,7 +111,7 @@
* } * }
* @endcode * @endcode
*/ */
#define REFLECT_IF_READING if (tag.reading()) #define REFLECT_IF_READING if (Handler::isReading)
/// Reflect a group of declarations only when *not* reading /// Reflect a group of declarations only when *not* reading
/** Usage: /** Usage:
@@ -129,24 +121,29 @@
* } * }
* @endcode * @endcode
*/ */
#define REFLECT_IF_NOT_READING if (!tag.reading()) #define REFLECT_IF_NOT_READING if (!Handler::isReading)
/// Add an alias for backwards compatability /// Reflect a group of declarations only when reading and when the value is a single line value
/** If a key 'old' is encountered in the input file, it is interpreted as 'new' for versions < version #define REFLECT_IF_READING_SINGLE_VALUE if (Handler::isReading && !handler.isCompound())
#define REFLECT_IF_READING_SINGLE_VALUE_AND(cond) if (Handler::isReading && !handler.isCompound() && cond)
/// Add an alias for backwards compatibility
/** If a key 'name' is encountered in the input file, it is interpreted as 'var' for versions < version
* Example: * Example:
* @code * @code
* REFLECT_ALIAS(300, "style", "stylesheet") // prior to 0.3.0 style was used instead of stylesheet * REFLECT_COMPAT(<300, "style", stylesheet) // prior to 0.3.0 style was used instead of stylesheet
* @encode * @encode
*/ */
#define REFLECT_ALIAS(version, old, new) tag.addAlias(version, _(old), _(new)) #define REFLECT_COMPAT(cond, name, var) if (handler.formatVersion() cond) REFLECT_N(name,var)
/// Ignore things for backwards compatability for versions < 'version' /// Ignore things for backwards compatibility for versions < 'version'
#define REFLECT_IGNORE(version, old) tag.handleIgnore(version, _(old)) #define REFLECT_COMPAT_IGNORE(cond, name, Type) if (reflector.formatVersion() cond) {Type ignored; REFLECT_N(name,ignored);}
/// Reflect a variable, ignores the variable for scripting /// Reflect a variable, ignores the variable for scripting
#define REFLECT_NO_SCRIPT(var) tag.handleNoScript(_(#var), var) #define REFLECT_NO_SCRIPT(var) handler.handleNoScript(_(#var), var)
/// Reflect a variable under the given name /// Reflect a variable under the given name
#define REFLECT_NO_SCRIPT_N(name, var) tag.handleNoScript(_(name), var) #define REFLECT_NO_SCRIPT_N(name, var) handler.handleNoScript(_(name), var)
/// Explicitly instantiate reflection; this is occasionally required. /// Explicitly instantiate reflection; this is occasionally required.
#define INSTANTIATE_REFLECTION(Class) \ #define INSTANTIATE_REFLECTION(Class) \
@@ -178,17 +175,17 @@
* - GetDefaultMember::handle(const Enum&) * - GetDefaultMember::handle(const Enum&)
*/ */
#define IMPLEMENT_REFLECTION_ENUM(Enum) \ #define IMPLEMENT_REFLECTION_ENUM(Enum) \
template <class Tag> \ template <class Handler> \
void reflect_ ## Enum (Enum& enum_, Tag& tag); \ void reflect_ ## Enum (Enum& enum_, Handler& handler); \
REFLECT_ENUM_READER(Enum) \ REFLECT_ENUM_READER(Enum) \
REFLECT_ENUM_WRITER(Enum) \ REFLECT_ENUM_WRITER(Enum) \
REFLECT_ENUM_GET_MEMBER(Enum) \ REFLECT_ENUM_GET_MEMBER(Enum) \
template <class Tag> \ template <class Handler> \
void reflect_ ## Enum (Enum& enum_, Tag& tag) void reflect_ ## Enum (Enum& enum_, Handler& handler)
/// Declare a possible value of an enum /// Declare a possible value of an enum
#define VALUE(val) tag.handle(_(#val), val, enum_) #define VALUE(val) handler.handle(_(#val), val, enum_)
/// Declare a possible value of an enum under the given name /// Declare a possible value of an enum under the given name
#define VALUE_N(name, val) tag.handle(_(name), val, enum_) #define VALUE_N(name, val) handler.handle(_(name), val, enum_)