diff --git a/Analysis/Tutorials/include/Analysis/configurableCut.h b/Analysis/Tutorials/include/Analysis/configurableCut.h index 0e9deef256856..446db71958217 100644 --- a/Analysis/Tutorials/include/Analysis/configurableCut.h +++ b/Analysis/Tutorials/include/Analysis/configurableCut.h @@ -18,8 +18,8 @@ class configurableCut { public: - configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector bins_ = {0.5, 1.5, 2.5}) - : cut{cut_}, state{state_}, option{option_}, bins{bins_} + configurableCut(float cut_ = 2., int state_ = 1, bool option_ = true, std::vector bins_ = {0.5, 1.5, 2.5}, std::vector labels_ = {"l1", "l2", "l3"}) + : cut{cut_}, state{state_}, option{option_}, bins{bins_}, labels{labels_} { } @@ -37,11 +37,15 @@ class configurableCut void setBins(std::vector bins_); std::vector getBins() const; + void setLabels(std::vector labels_); + std::vector getLabels() const; + private: float cut; int state; bool option; std::vector bins; + std::vector labels; ClassDef(configurableCut, 4); }; diff --git a/Analysis/Tutorials/src/configurableCut.cxx b/Analysis/Tutorials/src/configurableCut.cxx index c43b34293e178..eac596e038de1 100644 --- a/Analysis/Tutorials/src/configurableCut.cxx +++ b/Analysis/Tutorials/src/configurableCut.cxx @@ -60,3 +60,13 @@ std::vector configurableCut::getBins() const { return bins; }; + +void configurableCut::setLabels(std::vector labels_) +{ + labels = labels_; +} + +std::vector configurableCut::getLabels() const +{ + return labels; +} diff --git a/Analysis/Tutorials/src/configurableObjects.cxx b/Analysis/Tutorials/src/configurableObjects.cxx index 6058336feca4e..bc99060e065d5 100644 --- a/Analysis/Tutorials/src/configurableObjects.cxx +++ b/Analysis/Tutorials/src/configurableObjects.cxx @@ -50,6 +50,7 @@ struct ConfigurableObjectDemo { { LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut); LOGF(INFO, "Cut1 bins: %s; Cut2 bins: %s", printArray(cut->getBins()), printArray(mutable_cut->getBins())); + LOGF(INFO, "Cut1 labels: %s; Cut2 labels: %s", printArray(cut->getLabels()), printArray(mutable_cut->getLabels())); auto vec = (std::vector)array; LOGF(INFO, "Array: %s", printArray(vec).c_str()); for (auto& track : tracks) { diff --git a/Framework/Core/include/Framework/ConfigParamsHelper.h b/Framework/Core/include/Framework/ConfigParamsHelper.h index b48fb0291b1e1..02b9c9a56a4c3 100644 --- a/Framework/Core/include/Framework/ConfigParamsHelper.h +++ b/Framework/Core/include/Framework/ConfigParamsHelper.h @@ -118,7 +118,8 @@ struct ConfigParamsHelper { } else if constexpr (V == VariantType::ArrayInt || V == VariantType::ArrayFloat || V == VariantType::ArrayDouble || - V == VariantType::ArrayBool) { + V == VariantType::ArrayBool || + V == VariantType::ArrayString) { auto value = boost::program_options::value(); value = value->default_value(spec.defaultValue.asString()); if constexpr (V != VariantType::String) { diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index 7622ef09571c9..20f711987d505 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -36,6 +36,7 @@ enum class VariantType : int { Int = 0, ArrayFloat, ArrayDouble, ArrayBool, + ArrayString, Empty, Unknown }; @@ -66,11 +67,13 @@ DECLARE_VARIANT_TRAIT(int*, ArrayInt); DECLARE_VARIANT_TRAIT(float*, ArrayFloat); DECLARE_VARIANT_TRAIT(double*, ArrayDouble); DECLARE_VARIANT_TRAIT(bool*, ArrayBool); +DECLARE_VARIANT_TRAIT(std::string*, ArrayString); DECLARE_VARIANT_TRAIT(std::vector, ArrayInt); DECLARE_VARIANT_TRAIT(std::vector, ArrayFloat); DECLARE_VARIANT_TRAIT(std::vector, ArrayDouble); DECLARE_VARIANT_TRAIT(std::vector, ArrayBool); +DECLARE_VARIANT_TRAIT(std::vector, ArrayString); template struct variant_array_symbol { @@ -97,6 +100,11 @@ struct variant_array_symbol { constexpr static char symbol = 'b'; }; +template <> +struct variant_array_symbol { + constexpr static char symbol = 's'; +}; + template inline constexpr VariantType variant_trait_v = variant_trait::value; @@ -121,6 +129,7 @@ DECLARE_VARIANT_TYPE(int*, ArrayInt); DECLARE_VARIANT_TYPE(float*, ArrayFloat); DECLARE_VARIANT_TYPE(double*, ArrayDouble); DECLARE_VARIANT_TYPE(bool*, ArrayBool); +DECLARE_VARIANT_TYPE(std::string*, ArrayString); template struct variant_helper { @@ -217,6 +226,10 @@ class Variant mSize = other.mSize; variant_helper::set(&mStore, other.get(), mSize); return; + case variant_trait_v: + mSize = other.mSize; + variant_helper::set(&mStore, other.get(), mSize); + return; default: mStore = other.mStore; mSize = other.mSize; @@ -243,6 +256,8 @@ class Variant case variant_trait_v: *reinterpret_cast(&(other.mStore)) = nullptr; return; + case variant_trait_v: + *reinterpret_cast(&(other.mStore)) = nullptr; default: return; } @@ -258,6 +273,7 @@ class Variant case variant_trait_v: case variant_trait_v: case variant_trait_v: + case variant_trait_v: if (reinterpret_cast(&mStore) != nullptr) { free(*reinterpret_cast(&mStore)); } @@ -290,6 +306,10 @@ class Variant mSize = other.mSize; variant_helper::set(&mStore, other.get(), mSize); return; + case variant_trait_v: + mSize = other.mSize; + variant_helper::set(&mStore, other.get(), mSize); + return; default: mStore = other.mStore; mSize = other.mSize; diff --git a/Framework/Core/src/BoostOptionsRetriever.cxx b/Framework/Core/src/BoostOptionsRetriever.cxx index b966c48098511..efe4f85e933fe 100644 --- a/Framework/Core/src/BoostOptionsRetriever.cxx +++ b/Framework/Core/src/BoostOptionsRetriever.cxx @@ -30,9 +30,9 @@ namespace o2::framework BoostOptionsRetriever::BoostOptionsRetriever(bool ignoreUnknown, int argc, char** argv) : mDescription{std::make_unique("ALICE O2 Framework - Available options")}, - mIgnoreUnknown{ignoreUnknown}, mArgc{argc}, - mArgv{argv} + mArgv{argv}, + mIgnoreUnknown{ignoreUnknown} { } @@ -68,7 +68,8 @@ void BoostOptionsRetriever::update(std::vector const& specs, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: - options = options(name, bpo::value()->default_value(spec.defaultValue.asString(), help)); + case VariantType::ArrayString: + options = options(name, bpo::value()->default_value(spec.defaultValue.asString()), help); break; case VariantType::Unknown: case VariantType::Empty: diff --git a/Framework/Core/src/ConfigParamsHelper.cxx b/Framework/Core/src/ConfigParamsHelper.cxx index 225505734bd4b..a6c29c35e5f9f 100644 --- a/Framework/Core/src/ConfigParamsHelper.cxx +++ b/Framework/Core/src/ConfigParamsHelper.cxx @@ -69,6 +69,9 @@ void ConfigParamsHelper::populateBoostProgramOptions( case VariantType::ArrayBool: addConfigSpecOption(spec, options); break; + case VariantType::ArrayString: + addConfigSpecOption(spec, options); + break; case VariantType::Unknown: case VariantType::Empty: break; diff --git a/Framework/Core/src/PropertyTreeHelpers.cxx b/Framework/Core/src/PropertyTreeHelpers.cxx index 71b8e0fc10303..0860744dd55dd 100644 --- a/Framework/Core/src/PropertyTreeHelpers.cxx +++ b/Framework/Core/src/PropertyTreeHelpers.cxx @@ -74,6 +74,9 @@ void PropertyTreeHelpers::populateDefaults(std::vector const& s case VariantType::ArrayBool: addBranch(key, spec.defaultValue.get(), spec.defaultValue.size()); break; + case VariantType::ArrayString: + addBranch(key, spec.defaultValue.get(), spec.defaultValue.size()); + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -106,6 +109,21 @@ std::vector toVector(std::string const& input) } return result; } + +template <> +std::vector toVector(std::string const& input) +{ + std::vector result; + //check if the array string has correct array type symbol + assert(input[0] == variant_array_symbol::symbol); + std::regex smatch(R"((?:(?!=,)|(?!=\[))\w+(?=,|\]))"); + auto end = std::sregex_iterator(); + auto values = std::sregex_iterator(input.begin(), input.end(), smatch); + for (auto v = values; v != end; ++v) { + result.push_back(v->str()); + } + return result; +} } // namespace void PropertyTreeHelpers::populate(std::vector const& schema, @@ -171,6 +189,11 @@ void PropertyTreeHelpers::populate(std::vector const& schema, addBranch(key, v); }; break; + case VariantType::ArrayString: { + auto v = toVector(vmap[key].as()); + addBranch(key, v); + }; + break; case VariantType::Unknown: case VariantType::Empty: default: @@ -224,6 +247,7 @@ void PropertyTreeHelpers::populate(std::vector const& schema, case VariantType::ArrayFloat: case VariantType::ArrayDouble: case VariantType::ArrayBool: + case VariantType::ArrayString: pt.put_child(key, *it); break; case VariantType::Unknown: diff --git a/Framework/Core/src/RootConfigParamHelpers.cxx b/Framework/Core/src/RootConfigParamHelpers.cxx index 81b6851fd283f..c73c594782c2b 100644 --- a/Framework/Core/src/RootConfigParamHelpers.cxx +++ b/Framework/Core/src/RootConfigParamHelpers.cxx @@ -115,8 +115,13 @@ void ptreeToMember(boost::property_tree::ptree const& value, *static_cast*>(ptr) = extractVector(value); return; case compile_time_hash("vector"): + throw std::runtime_error("Bool arrays are not implemented yet"); + case compile_time_hash("vector"): + case compile_time_hash("vector"): + *static_cast*>(ptr) = extractVector(value); + return; default: - throw std::runtime_error("Not and int/float/double/bool vector"); + throw std::runtime_error("Not an int/float/double/bool vector"); } } auto dt = dm->GetDataType(); @@ -205,8 +210,11 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void case compile_time_hash("vector"): throw std::runtime_error("bool vector not supported yet"); // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast*>(ptr), {"No help"}}; + case compile_time_hash("vector"): + case compile_time_hash("vector"): + return ConfigParamSpec{tname, VariantType::ArrayString, *static_cast*>(ptr), {"No help"}}; default: - throw std::runtime_error("Not and int/float/double/bool vector"); + throw std::runtime_error("Not an int/float/double/bool vector"); } } auto dt = dm->GetDataType(); diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index c1f9708bed46b..5f9c60217ffb0 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -63,6 +63,9 @@ std::ostream& operator<<(std::ostream& oss, Variant const& val) case VariantType::ArrayBool: printArray(oss, val.get(), val.size()); break; + case VariantType::ArrayString: + printArray(oss, val.get(), val.size()); + break; case VariantType::Empty: break; default: diff --git a/Framework/Core/test/test_Variants.cxx b/Framework/Core/test/test_Variants.cxx index 0b34a853f8713..11a42487c759b 100644 --- a/Framework/Core/test/test_Variants.cxx +++ b/Framework/Core/test/test_Variants.cxx @@ -105,4 +105,28 @@ BOOST_AUTO_TEST_CASE(VariantTest) for (auto i = 0u; i < fd.size(); ++i) { BOOST_CHECK(farr[i] == (fd.get())[i]); } + + std::vector vstrings{"s1", "s2", "s3"}; + std::string strings[] = {"l1", "l2", "l3"}; + Variant vstr(strings, 3); + Variant vvstr(vstrings); + + BOOST_CHECK(vstr.size() == 3); + BOOST_CHECK(vvstr.size() == 3); + for (auto i = 0u; i < vstr.size(); ++i) { + BOOST_CHECK(strings[i] == (vstr.get())[i]); + } + for (auto i = 0u; i < vvstr.size(); ++i) { + BOOST_CHECK(vstrings[i] == (vvstr.get())[i]); + } + + Variant vsc(vstr); // Copy constructor + Variant vsm(std::move(vstr)); // Move constructor + Variant vscc = vsm; // Copy assignment + for (auto i = 0u; i < vsm.size(); ++i) { + BOOST_CHECK(strings[i] == (vsm.get())[i]); + } + for (auto i = 0u; i < vscc.size(); ++i) { + BOOST_CHECK(strings[i] == (vscc.get())[i]); + } }