return option().defaultValuesAsStrings();
}
+std::vector<Variant> OptionInfo::normalizeValues(const std::vector<Variant> &values) const
+{
+ return option().normalizeValues(values);
+}
+
} // namespace gmx
* assigned.
*/
std::vector<std::string> defaultValuesAsStrings() const;
+ /*! \brief
+ * Converts given values to native representation for this option.
+ *
+ * For example, strings are parsed to the type that is actually used to
+ * store the options.
+ *
+ * The return value only depends on the option type, not on the current
+ * value of the option, and the current value in the option is not
+ * changed.
+ */
+ std::vector<Variant> normalizeValues(const std::vector<Variant> &values) const;
protected:
/*! \cond libapi */
virtual std::vector<Variant> defaultValues() const = 0;
//! \copydoc OptionInfo::defaultValuesAsStrings()
virtual std::vector<std::string> defaultValuesAsStrings() const = 0;
+ //! \copydoc OptionInfo::normalizeValues()
+ virtual std::vector<Variant> normalizeValues(const std::vector<Variant> &values) const = 0;
/*! \brief
* Starts adding values from a new source for the option.
converter->addCastConversion<float>();
}
-double DoubleOptionStorage::processValue(const double &value)
+double DoubleOptionStorage::processValue(const double &value) const
{
// TODO: Consider testing for overflow when scaling with factor_.
return value * factor_;
converter->addCastConversion<double>();
}
-float FloatOptionStorage::processValue(const float &value)
+float FloatOptionStorage::processValue(const float &value) const
{
// TODO: Consider testing for overflow when scaling with factor_.
return value * factor_;
{
}
-std::string StringOptionStorage::processValue(const std::string &value)
+std::string StringOptionStorage::processValue(const std::string &value) const
{
if (allowed_.size() > 0)
{
private:
virtual void initConverter(ConverterType *converter);
- virtual double processValue(const double &value);
+ virtual double processValue(const double &value) const;
virtual void processSetValues(ValueList *values);
DoubleOptionInfo info_;
private:
virtual void initConverter(ConverterType *converter);
- virtual float processValue(const float &value);
+ virtual float processValue(const float &value) const;
virtual void processSetValues(ValueList *values);
FloatOptionInfo info_;
private:
virtual void initConverter(ConverterType *converter);
- virtual std::string processValue(const std::string &value);
+ virtual std::string processValue(const std::string &value) const;
StringOptionInfo info_;
ValueList allowed_;
{
}
-std::string FileNameOptionStorage::processValue(const std::string &value)
+std::string FileNameOptionStorage::processValue(const std::string &value) const
{
if (manager_ != NULL)
{
private:
virtual void initConverter(ConverterType *converter);
- virtual std::string processValue(const std::string &value);
+ virtual std::string processValue(const std::string &value) const;
virtual void processAll();
FileNameOptionInfo info_;
{
}
+ virtual std::vector<Variant>
+ normalizeValues(const std::vector<Variant> &values) const
+ {
+ const_cast<MyBase *>(this)->ensureConverterInitialized();
+ std::vector<Variant> result;
+ for (const auto &value : values)
+ {
+ result.push_back(
+ Variant::create<T>(
+ processValue(converter_.convert(value))));
+ }
+ return result;
+ }
+
/*! \brief
* Specifies how different types are converted.
*
*
* The default implementation only provides an identity mapping.
*/
- virtual T processValue(const T &value)
+ virtual T processValue(const T &value) const
{
return value;
}
private:
virtual void convertValue(const Variant &variant)
+ {
+ ensureConverterInitialized();
+ this->addValue(processValue(converter_.convert(variant)));
+ }
+ void ensureConverterInitialized()
{
if (!initialized_)
{
initConverter(&converter_);
initialized_ = true;
}
- this->addValue(processValue(converter_.convert(variant)));
}
ConverterType converter_;
{
return "";
}
+ virtual std::vector<gmx::Variant>
+ normalizeValues(const std::vector<gmx::Variant> &values) const
+ {
+ return values;
+ }
virtual void convertValue(const gmx::Variant &value)
{
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Object Name="Input">
+ <String Name="a">2</String>
+ </Object>
+ <Object Name="Output">
+ <Int Name="a">2</Int>
+ </Object>
+</ReferenceData>
runTest();
}
+TEST_F(TreeValueSupportAdjustTest, NormalizesValues)
+{
+ options_.addOption(gmx::IntegerOption("a"));
+ builder_.rootObject().addValue<std::string>("a", "2");
+ runTest();
+}
+
TEST_F(TreeValueSupportAdjustTest, MergesDefaultValues)
{
builder_.rootObject().addValue<int>("b", 1);
}
else
{
- currentObjectBuilder_.addRawValue(name, KeyValueTreeValue((*currentSourceObject_)[name]));
+ const KeyValueTreeValue &value = (*currentSourceObject_)[name];
+ GMX_RELEASE_ASSERT(!value.isObject(), "Value objects not supported in this context");
+ std::vector<Variant> values;
+ if (value.isArray())
+ {
+ for (const auto &arrayValue : value.asArray().values())
+ {
+ GMX_RELEASE_ASSERT(!value.isObject() && !value.isArray(),
+ "Complex values not supported in this context");
+ values.push_back(arrayValue.asVariant());
+ }
+ }
+ else
+ {
+ values.push_back(value.asVariant());
+ }
+ values = option.normalizeValues(values);
+ if (values.empty())
+ {
+ }
+ else if (values.size() == 1)
+ {
+ currentObjectBuilder_.addRawValue(name, std::move(values[0]));
+ }
+ else
+ {
+ auto array = currentObjectBuilder_.addArray(name);
+ for (auto &arrayValue : values)
+ {
+ array.addRawValue(std::move(arrayValue));
+ }
+ }
}
}
*
* Assumes that all values in the input KeyValueTreeObject are valid values for
* the options. The output has all the values in the input, but in the order
- * they are in the options. For any option that does not have a corresponding
- * value in the input, the output has it with a default value (if one exists
- * for the option).
+ * they are in the options. Values are also converted to the native type for
+ * the underlying option (e.g., strings are parsed to integers if the option
+ * accepts those). For any option that does not have a corresponding value in
+ * the input, the output has it with a default value (if one exists for the
+ * option).
*
* Does not currently work for option sections in an array.
*
virtual int valueCount() const { return 0; }
virtual std::vector<Variant> defaultValues() const { return {}; }
virtual std::vector<std::string> defaultValuesAsStrings() const { return {}; }
+ virtual std::vector<Variant>
+ normalizeValues(const std::vector<Variant> &values) const { return values; }
private:
virtual void clearSet();
}
+std::vector<Variant>
+SelectionOptionStorage::normalizeValues(const std::vector<Variant> & /*values*/) const
+{
+ GMX_THROW(NotImplementedError("Selection options not supported in this context"));
+}
+
+
void SelectionOptionStorage::addSelections(
const SelectionList &selections,
bool bFullValue)
virtual OptionInfo &optionInfo() { return info_; }
virtual std::string typeString() const { return "selection"; }
virtual std::string formatSingleValue(const Selection &value) const;
+ virtual std::vector<Variant>
+ normalizeValues(const std::vector<Variant> &values) const;
/*! \brief
* Adds selections to the storage.