Rewrite the array config visitor so that it doesn't need the OptionValueList base class
Originally committed to SVN as r5817.
This commit is contained in:
parent
84c545b978
commit
8fcd3daf28
|
@ -48,55 +48,59 @@ void ConfigVisitor::Visit(const json::Object& object) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline T convert_unknown(json::UnknownElement const& ue) {
|
||||||
|
return ue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int64_t convert_unknown(json::UnknownElement const& ue) {
|
||||||
|
return (int64_t)(double)ue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class OptionValueType, class ValueType>
|
||||||
|
static OptionValue *read_array(json::Array const& src, std::string const& array_type, std::string const& name, void (OptionValueType::*set_list)(const std::vector<ValueType>&)) {
|
||||||
|
std::vector<ValueType> arr;
|
||||||
|
arr.reserve(src.size());
|
||||||
|
|
||||||
|
for (json::Array::const_iterator it = src.begin(); it != src.end(); ++it) {
|
||||||
|
json::Object const& obj = *it;
|
||||||
|
|
||||||
|
if (obj.size() != 1)
|
||||||
|
throw OptionJsonValueArray("Invalid array member");
|
||||||
|
if (obj.begin()->first != array_type)
|
||||||
|
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
|
||||||
|
|
||||||
|
arr.push_back(convert_unknown<ValueType>(obj.begin()->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionValueType *ret = new OptionValueType(name);
|
||||||
|
(ret->*set_list)(arr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigVisitor::Visit(const json::Array& array) {
|
void ConfigVisitor::Visit(const json::Array& array) {
|
||||||
OptionValueList *array_list = NULL;
|
if (array.empty())
|
||||||
|
throw OptionJsonValueArray("Cannot infer the type of an empty array");
|
||||||
|
|
||||||
json::Array::const_iterator index(array.begin()), indexEnd(array.end());
|
json::Object const& front = array.front();
|
||||||
|
if (front.size() != 1)
|
||||||
|
throw OptionJsonValueArray("Invalid array member");
|
||||||
|
|
||||||
for (; index != indexEnd; ++index) {
|
const std::string& array_type = front.begin()->first;
|
||||||
const json::Object& index_array = *index;
|
|
||||||
|
|
||||||
json::Object::const_iterator it(index_array.begin()), index_objectEnd(index_array.end());
|
if (array_type == "string")
|
||||||
|
AddOptionValue(read_array(array, array_type, name, &OptionValueListString::SetListString));
|
||||||
for (; it != index_objectEnd; ++it) {
|
else if (array_type == "int")
|
||||||
const std::string& member_name = it->first;
|
AddOptionValue(read_array(array, array_type, name, &OptionValueListInt::SetListInt));
|
||||||
|
else if (array_type == "double")
|
||||||
// This can only happen once since a list must always be of the same
|
AddOptionValue(read_array(array, array_type, name, &OptionValueListDouble::SetListDouble));
|
||||||
// type, if we try inserting another type into it we want it to fail.
|
else if (array_type == "bool")
|
||||||
if (!array_list) {
|
AddOptionValue(read_array(array, array_type, name, &OptionValueListBool::SetListBool));
|
||||||
if (member_name == "string")
|
else if (array_type == "colour")
|
||||||
array_list = new OptionValueListString(name);
|
AddOptionValue(read_array(array, array_type, name, &OptionValueListColour::SetListColour));
|
||||||
else if (member_name == "int")
|
|
||||||
array_list = new OptionValueListInt(name);
|
|
||||||
else if (member_name == "double")
|
|
||||||
array_list = new OptionValueListDouble(name);
|
|
||||||
else if (member_name == "bool")
|
|
||||||
array_list = new OptionValueListBool(name);
|
|
||||||
else if (member_name == "colour")
|
|
||||||
array_list = new OptionValueListColour(name);
|
|
||||||
else
|
else
|
||||||
throw OptionJsonValueArray("Array type not handled");
|
throw OptionJsonValueArray("Array type not handled");
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (member_name == "string")
|
|
||||||
array_list->InsertString(it->second);
|
|
||||||
else if (member_name == "int")
|
|
||||||
array_list->InsertInt((int64_t)(double)it->second);
|
|
||||||
else if (member_name == "double")
|
|
||||||
array_list->InsertDouble(it->second);
|
|
||||||
else if (member_name == "bool")
|
|
||||||
array_list->InsertBool(it->second);
|
|
||||||
else if (member_name == "colour")
|
|
||||||
array_list->InsertColour(it->second);
|
|
||||||
} catch (agi::Exception&) {
|
|
||||||
delete array_list;
|
|
||||||
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
|
|
||||||
}
|
|
||||||
} // for index_object
|
|
||||||
} // for index
|
|
||||||
|
|
||||||
if (array_list) AddOptionValue(array_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,6 @@ DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorNotFound, OptionValueError, "opt
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidListType, OptionValueError, "options/array/invalid_type")
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidListType, OptionValueError, "options/array/invalid_type")
|
||||||
|
|
||||||
|
|
||||||
class ConfigVisitor;
|
|
||||||
|
|
||||||
/// @class OptionValue
|
/// @class OptionValue
|
||||||
/// Holds an actual option.
|
/// Holds an actual option.
|
||||||
class OptionValue {
|
class OptionValue {
|
||||||
|
@ -143,24 +140,11 @@ CONFIG_OPTIONVALUE(Double, double)
|
||||||
CONFIG_OPTIONVALUE(Colour, Colour)
|
CONFIG_OPTIONVALUE(Colour, Colour)
|
||||||
CONFIG_OPTIONVALUE(Bool, bool)
|
CONFIG_OPTIONVALUE(Bool, bool)
|
||||||
|
|
||||||
|
|
||||||
class OptionValueList: public OptionValue {
|
|
||||||
friend class ConfigVisitor;
|
|
||||||
|
|
||||||
virtual void InsertString(const std::string val) { throw ListTypeError("string", " insert "); }
|
|
||||||
virtual void InsertInt(const int64_t val) { throw ListTypeError("int", " insert "); }
|
|
||||||
virtual void InsertDouble(const double val) { throw ListTypeError("double", " insert "); }
|
|
||||||
virtual void InsertColour(const Colour val) { throw ListTypeError("colour", " insert "); }
|
|
||||||
virtual void InsertBool(const bool val) { throw ListTypeError("bool", " insert "); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define CONFIG_OPTIONVALUE_LIST(type_name, type) \
|
#define CONFIG_OPTIONVALUE_LIST(type_name, type) \
|
||||||
class OptionValueList##type_name : public OptionValueList { \
|
class OptionValueList##type_name : public OptionValue { \
|
||||||
std::vector<type> array; \
|
std::vector<type> array; \
|
||||||
std::vector<type> array_default; \
|
std::vector<type> array_default; \
|
||||||
std::string name; \
|
std::string name; \
|
||||||
void Insert##type_name(const type val) { array.push_back(val); } \
|
|
||||||
public: \
|
public: \
|
||||||
virtual std::string GetString() const { return "";} \
|
virtual std::string GetString() const { return "";} \
|
||||||
OptionValueList##type_name(std::string member_name): name(member_name) {} \
|
OptionValueList##type_name(std::string member_name): name(member_name) {} \
|
||||||
|
|
Loading…
Reference in a new issue