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
2 changed files with 50 additions and 62 deletions
|
@ -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) {
|
||||
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 json::Object& index_array = *index;
|
||||
const std::string& array_type = front.begin()->first;
|
||||
|
||||
json::Object::const_iterator it(index_array.begin()), index_objectEnd(index_array.end());
|
||||
|
||||
for (; it != index_objectEnd; ++it) {
|
||||
const std::string& member_name = it->first;
|
||||
|
||||
// This can only happen once since a list must always be of the same
|
||||
// type, if we try inserting another type into it we want it to fail.
|
||||
if (!array_list) {
|
||||
if (member_name == "string")
|
||||
array_list = new OptionValueListString(name);
|
||||
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
|
||||
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);
|
||||
if (array_type == "string")
|
||||
AddOptionValue(read_array(array, array_type, name, &OptionValueListString::SetListString));
|
||||
else if (array_type == "int")
|
||||
AddOptionValue(read_array(array, array_type, name, &OptionValueListInt::SetListInt));
|
||||
else if (array_type == "double")
|
||||
AddOptionValue(read_array(array, array_type, name, &OptionValueListDouble::SetListDouble));
|
||||
else if (array_type == "bool")
|
||||
AddOptionValue(read_array(array, array_type, name, &OptionValueListBool::SetListBool));
|
||||
else if (array_type == "colour")
|
||||
AddOptionValue(read_array(array, array_type, name, &OptionValueListColour::SetListColour));
|
||||
else
|
||||
throw OptionJsonValueArray("Array type not handled");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,9 +38,6 @@ DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorNotFound, OptionValueError, "opt
|
|||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidListType, OptionValueError, "options/array/invalid_type")
|
||||
|
||||
|
||||
class ConfigVisitor;
|
||||
|
||||
/// @class OptionValue
|
||||
/// Holds an actual option.
|
||||
class OptionValue {
|
||||
|
@ -143,24 +140,11 @@ CONFIG_OPTIONVALUE(Double, double)
|
|||
CONFIG_OPTIONVALUE(Colour, Colour)
|
||||
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) \
|
||||
class OptionValueList##type_name : public OptionValueList { \
|
||||
class OptionValueList##type_name : public OptionValue { \
|
||||
std::vector<type> array; \
|
||||
std::vector<type> array_default; \
|
||||
std::string name; \
|
||||
void Insert##type_name(const type val) { array.push_back(val); } \
|
||||
public: \
|
||||
virtual std::string GetString() const { return "";} \
|
||||
OptionValueList##type_name(std::string member_name): name(member_name) {} \
|
||||
|
|
Loading…
Reference in a new issue