From b9d57483d8a469eb1a6d5c208acbb2188800db5e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 17 Oct 2017 19:19:41 +0200 Subject: [PATCH] perglue.cpp - use static_cast instead of dynamic_cast if possible, use switch instead of plenty of ifs, export clone to Perl XS. --- xs/src/libslic3r/Fill/FillBase.cpp | 2 +- xs/src/perlglue.cpp | 312 ++++++++++++++--------------- xs/xsp/my.map | 1 + xs/xsp/typemap.xspt | 1 + 4 files changed, 150 insertions(+), 166 deletions(-) diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/xs/src/libslic3r/Fill/FillBase.cpp index 8ed6408d1..2fa237e5f 100644 --- a/xs/src/libslic3r/Fill/FillBase.cpp +++ b/xs/src/libslic3r/Fill/FillBase.cpp @@ -38,7 +38,7 @@ Fill* Fill::new_from_type(const InfillPattern type) Fill* Fill::new_from_type(const std::string &type) { - static t_config_enum_values enum_keys_map = ConfigOptionEnum::get_enum_values(); + const t_config_enum_values &enum_keys_map = ConfigOptionEnum::get_enum_values(); t_config_enum_values::const_iterator it = enum_keys_map.find(type); return (it == enum_keys_map.end()) ? nullptr : new_from_type(InfillPattern(it->second)); } diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index e7f03d1f5..19ec59dd7 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -61,135 +61,132 @@ REGISTER_CLASS(Preset, "GUI::Preset"); REGISTER_CLASS(PresetCollection, "GUI::PresetCollection"); REGISTER_CLASS(PresetBundle, "GUI::PresetBundle"); -SV* -ConfigBase__as_hash(ConfigBase* THIS) { - HV* hv = newHV(); - - t_config_option_keys opt_keys = THIS->keys(); - for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it) - (void)hv_store( hv, it->c_str(), it->length(), ConfigBase__get(THIS, *it), 0 ); - +SV* ConfigBase__as_hash(ConfigBase* THIS) +{ + HV* hv = newHV(); + for (auto &key : THIS->keys()) + (void)hv_store(hv, key.c_str(), key.length(), ConfigBase__get(THIS, *it), 0); return newRV_noinc((SV*)hv); } -SV* -ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) { +SV* ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) +{ ConfigOption* opt = THIS->option(opt_key); - if (opt == NULL) return &PL_sv_undef; - - const ConfigOptionDef* def = THIS->def()->get(opt_key); - return ConfigOption_to_SV(*opt, *def); + return (opt == nullptr) ? + &PL_sv_undef : + ConfigOption_to_SV(*opt, *THIS->def->get(opt_key)); } -SV* -ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) { - if (def.type == coFloat) { - const ConfigOptionFloat* optv = dynamic_cast(&opt); - return newSVnv(optv->value); - } else if (def.type == coFloats) { - const ConfigOptionFloats* optv = dynamic_cast(&opt); - AV* av = newAV(); - av_fill(av, optv->values.size()-1); - for (std::vector::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it) - av_store(av, it - optv->values.begin(), newSVnv(*it)); - return newRV_noinc((SV*)av); - } else if (def.type == coPercent) { - const ConfigOptionPercent* optv = dynamic_cast(&opt); - return newSVnv(optv->value); - } else if (def.type == coPercents) { - const ConfigOptionPercents* optv = dynamic_cast(&opt); +SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) +{ + switch (def.type) { + case coFloat: + case coPercent: + return newSVnv(static_cast(&opt)->value); + case coFloats: + case coPercents: + { + auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); for (const double &v : optv->values) - av_store(av, &v - &optv->values.front(), newSVnv(v)); + av_store(av, &v - optv->values.data(), newSVnv(v)); return newRV_noinc((SV*)av); - } else if (def.type == coInt) { - const ConfigOptionInt* optv = dynamic_cast(&opt); - return newSViv(optv->value); - } else if (def.type == coInts) { - const ConfigOptionInts* optv = dynamic_cast(&opt); + } + case coInt: + return newSViv(static_cast(&opt)->value); + case coInts: + { + auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); - for (std::vector::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it) - av_store(av, it - optv->values.begin(), newSViv(*it)); + for (const int &v : optv->values) + av_store(av, &v - optv->values.data(), newSViv(v)); return newRV_noinc((SV*)av); - } else if (def.type == coString) { - const ConfigOptionString* optv = dynamic_cast(&opt); + } + case coString: + { + auto optv = static_cast(&opt); // we don't serialize() because that would escape newlines return newSVpvn_utf8(optv->value.c_str(), optv->value.length(), true); - } else if (def.type == coStrings) { - const ConfigOptionStrings* optv = dynamic_cast(&opt); + } + case coStrings: + { + auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); - for (std::vector::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it) - av_store(av, it - optv->values.begin(), newSVpvn_utf8(it->c_str(), it->length(), true)); + for (const std::string &v : optv->values) + av_store(av, &v - optv->values.data(), newSVpvn_utf8(v.c_str(), v.length(), true)); return newRV_noinc((SV*)av); - } else if (def.type == coPoint) { - const ConfigOptionPoint* optv = dynamic_cast(&opt); - return perl_to_SV_clone_ref(optv->value); - } else if (def.type == coPoints) { - const ConfigOptionPoints* optv = dynamic_cast(&opt); + } + case coPoint: + return perl_to_SV_clone_ref(static_cast(&opt)->value); + case coPoints: + { + auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); - for (Pointfs::const_iterator it = optv->values.begin(); it != optv->values.end(); ++it) - av_store(av, it - optv->values.begin(), perl_to_SV_clone_ref(*it)); + for (const Pointf &v : optv->values) + av_store(av, &v - optv->values.data(), perl_to_SV_clone_ref(v)); return newRV_noinc((SV*)av); - } else if (def.type == coBool) { - const ConfigOptionBool* optv = dynamic_cast(&opt); - return newSViv(optv->value ? 1 : 0); - } else if (def.type == coBools) { - const ConfigOptionBools* optv = dynamic_cast(&opt); + } + case coBool: + return newSViv(static_cast(&opt)->value ? 1 : 0); + case coBools: + { + auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); for (size_t i = 0; i < optv->values.size(); ++ i) av_store(av, i, newSViv(optv->values[i] ? 1 : 0)); return newRV_noinc((SV*)av); - } else { + } + default: std::string serialized = opt.serialize(); return newSVpvn_utf8(serialized.c_str(), serialized.length(), true); } } -SV* -ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i) { +SV* ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t i) +{ ConfigOption* opt = THIS->option(opt_key); if (opt == NULL) return &PL_sv_undef; - const ConfigOptionDef* def = THIS->def()->get(opt_key); - if (def->type == coFloats || def->type == coPercents) { - ConfigOptionFloats* optv = dynamic_cast(opt); - return newSVnv(optv->get_at(i)); - } else if (def->type == coInts) { - ConfigOptionInts* optv = dynamic_cast(opt); - return newSViv(optv->get_at(i)); - } else if (def->type == coStrings) { - ConfigOptionStrings* optv = dynamic_cast(opt); + const ConfigOptionDef* def = THIS->def->get(opt_key); + switch (def->type) { + case coFloats: + case coPercents: + return newSVnv(static_cast(opt)->get_at(i)); + case coInts: + return newSViv(static_cast(opt)->get_at(i)); + case coStrings: + { // we don't serialize() because that would escape newlines - std::string val = optv->get_at(i); + const std::string &val = static_cast(opt)->get_at(i); return newSVpvn_utf8(val.c_str(), val.length(), true); - } else if (def->type == coPoints) { - ConfigOptionPoints* optv = dynamic_cast(opt); - return perl_to_SV_clone_ref(optv->get_at(i)); - } else if (def->type == coBools) { - ConfigOptionBools* optv = dynamic_cast(opt); - return newSViv(optv->get_at(i) ? 1 : 0); - } else { + } + case coPoints: + return perl_to_SV_clone_ref(static_cast(opt)->get_at(i)); + case coBools: + return newSViv(static_cast(opt)->get_at(i) ? 1 : 0); + default: return &PL_sv_undef; } } -bool -ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) { +bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) +{ ConfigOption* opt = THIS->option(opt_key, true); if (opt == NULL) CONFESS("Trying to set non-existing option"); - const ConfigOptionDef* def = THIS->def()->get(opt_key); - if (def->type == coFloat) { - if (!looks_like_number(value)) return false; - ConfigOptionFloat* optv = dynamic_cast(opt); - optv->value = SvNV(value); - } else if (def->type == coFloats) { - ConfigOptionFloats* optv = dynamic_cast(opt); + const ConfigOptionDef* def = THIS->def->get(opt_key); + case coFloat: + if (!looks_like_number(value)) + return false; + static_cast(opt)->value = SvNV(value); + break; + case coFloats: + { std::vector values; AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; @@ -198,9 +195,11 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) if (elem == NULL || !looks_like_number(*elem)) return false; values.push_back(SvNV(*elem)); } - optv->values = values; - } else if (def->type == coPercents) { - ConfigOptionPercents* optv = dynamic_cast(opt); + static_cast(opt)->values = std::move(values); + break; + } + case coPercents: + { std::vector values; AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; @@ -209,13 +208,15 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) if (elem == NULL || !looks_like_number(*elem)) return false; values.push_back(SvNV(*elem)); } - optv->values = values; - } else if (def->type == coInt) { + static_cast(opt)->values = std::move(values); + break; + } + case coInt: if (!looks_like_number(value)) return false; - ConfigOptionInt* optv = dynamic_cast(opt); - optv->value = SvIV(value); - } else if (def->type == coInts) { - ConfigOptionInts* optv = dynamic_cast(opt); + static_cast(opt)->value = SvIV(value); + break; + case coInts: + { std::vector values; AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; @@ -224,25 +225,30 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) if (elem == NULL || !looks_like_number(*elem)) return false; values.push_back(SvIV(*elem)); } - optv->values = values; - } else if (def->type == coString) { - ConfigOptionString* optv = dynamic_cast(opt); - optv->value = std::string(SvPV_nolen(value), SvCUR(value)); - } else if (def->type == coStrings) { - ConfigOptionStrings* optv = dynamic_cast(opt); + static_cast(opt)->values = std::move(values); + break; + } + case coString: + static_cast(opt)->value = std::string(SvPV_nolen(value), SvCUR(value)); + break; + case coStrings: + { + auto optv = static_cast(opt); optv->values.clear(); AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; + optv->values.reserve(len); for (size_t i = 0; i < len; i++) { SV** elem = av_fetch(av, i, 0); if (elem == NULL) return false; - optv->values.push_back(std::string(SvPV_nolen(*elem), SvCUR(*elem))); + optv->values.emplace_back(std::string(SvPV_nolen(*elem), SvCUR(*elem))); } - } else if (def->type == coPoint) { - ConfigOptionPoint* optv = dynamic_cast(opt); - return from_SV_check(value, &optv->value); - } else if (def->type == coPoints) { - ConfigOptionPoints* optv = dynamic_cast(opt); + break; + } + case coPoint: + return from_SV_check(value, &static_cast(opt)->value); + case coPoints: + { std::vector values; AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; @@ -252,60 +258,62 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) if (elem == NULL || !from_SV_check(*elem, &point)) return false; values.push_back(point); } - optv->values = values; - } else if (def->type == coBool) { - ConfigOptionBool* optv = dynamic_cast(opt); - optv->value = SvTRUE(value); - } else if (def->type == coBools) { - ConfigOptionBools* optv = dynamic_cast(opt); + static_cast(opt)->values = std::move(values); + break; + } + case coBool: + static_cast(opt)->value = SvTRUE(value); + break; + case coBools: + { + auto optv = static_cast(opt); optv->values.clear(); AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; + optv->values.reserve(len); for (size_t i = 0; i < len; i++) { SV** elem = av_fetch(av, i, 0); if (elem == NULL) return false; - optv->values.push_back(SvTRUE(*elem)); + optv->values.emplace_back(SvTRUE(*elem)); } - } else { - if (!opt->deserialize( std::string(SvPV_nolen(value)) )) return false; + break; + } + default: + if (! opt->deserialize(std::string(SvPV_nolen(value)))) + return false; } return true; } /* This method is implemented as a workaround for this typemap bug: https://rt.cpan.org/Public/Bug/Display.html?id=94110 */ -bool -ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str) { +bool ConfigBase__set_deserialize(ConfigBase* THIS, const t_config_option_key &opt_key, SV* str) +{ size_t len; const char * c = SvPV(str, len); std::string value(c, len); - return THIS->set_deserialize(opt_key, value); } -void -ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize) +void ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value, bool deserialize) { - if (!THIS->has(opt_key)) { - if (deserialize) { - ConfigBase__set_deserialize(THIS, opt_key, value); - } else { - ConfigBase__set(THIS, opt_key, value); - } - } + if (THIS->has(opt_key)) + return; + if (deserialize) + ConfigBase__set_deserialize(THIS, opt_key, value); + else + ConfigBase__set(THIS, opt_key, value); } -bool -StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) { - const ConfigOptionDef* optdef = THIS->def()->get(opt_key); - if (!optdef->shortcut.empty()) { - for (std::vector::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) { - if (!StaticConfig__set(THIS, *it, value)) return false; - } - return true; - } - - return ConfigBase__set(THIS, opt_key, value); +bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) +{ + const ConfigOptionDef* optdef = THIS->def->get(opt_key); + if (optdef->shortcut.empty()) + return ConfigBase__set(THIS, opt_key, value); + for (const t_config_option_key &key : optdef->shortcut) + if (! StaticConfig__set(THIS, key, value)) + return false; + return true; } SV* to_AV(ExPolygon* expolygon) @@ -535,31 +543,5 @@ SV* to_SV(TriangleMesh* THIS) return sv; } -SV* -polynode_children_2_perl(const ClipperLib::PolyNode& node) -{ - AV* av = newAV(); - const int len = node.ChildCount(); - if (len > 0) av_extend(av, len-1); - for (int i = 0; i < len; ++i) { - av_store(av, i, polynode2perl(*node.Childs[i])); - } - return (SV*)newRV_noinc((SV*)av); -} - -SV* -polynode2perl(const ClipperLib::PolyNode& node) -{ - HV* hv = newHV(); - Slic3r::Polygon p = ClipperPath_to_Slic3rPolygon(node.Contour); - if (node.IsHole()) { - (void)hv_stores( hv, "hole", Slic3r::perl_to_SV_clone_ref(p) ); - } else { - (void)hv_stores( hv, "outer", Slic3r::perl_to_SV_clone_ref(p) ); - } - (void)hv_stores( hv, "children", polynode_children_2_perl(node) ); - return (SV*)newRV_noinc((SV*)hv); -} - } #endif diff --git a/xs/xsp/my.map b/xs/xsp/my.map index db94cd15f..50073d87d 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -31,6 +31,7 @@ Clone O_OBJECT_SLIC3R_T DynamicPrintConfig* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T +Clone O_OBJECT_SLIC3R_T StaticPrintConfig* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 87595415d..d9d547b2b 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -39,6 +39,7 @@ %typemap{Clone}{simple}; %typemap{DynamicPrintConfig*}; %typemap{Ref}{simple}; +%typemap{Clone}{simple}; %typemap{StaticPrintConfig*}; %typemap{Ref}{simple}; %typemap{PrintObjectConfig*};