in thrift/compiler/generate/t_cocoa_generator.cc [2911:3036]
std::string t_cocoa_generator::render_const_value(std::string name,
const t_type* type,
t_const_value* value,
bool containerize_it) {
type = type->get_true_type();
std::ostringstream render;
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_STRING:
render << "@\"" << get_escaped_string(value) << '"';
break;
case t_base_type::TYPE_BOOL:
render << ((value->get_integer() > 0) ? "YES" : "NO");
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
render << value->get_integer();
break;
case t_base_type::TYPE_DOUBLE:
if (value->get_type() == t_const_value::CV_INTEGER) {
render << value->get_integer();
} else {
render << value->get_double();
}
break;
default:
throw std::runtime_error("compiler error: no const of base type " + t_base_type::t_base_name(tbase));
}
} else if (type->is_enum()) {
render << value->get_integer();
} else if (type->is_struct() || type->is_xception()) {
const auto* as_struct = std::static_cast<const t_struct*>(type);
if (value->get_map().empty()) {
render << "[[" << type_name(type, true) << " alloc] init";
} else{
render << "[[" << type_name(type, true) << " alloc] initWith";
}
bool first = true;
for (const auto& entry : value->get_map()) {
// FIXME The generated code does not match with initWithXXX
// initializer and causes compile error.
// Try: test/DebugProtoTest.thrift and test/SmallTest.thrift
const auto* field = as_struct->get_field_by_name(entry.first->get_string());
if (field == nullptr) {
throw std::runtime_error("type error: " + type->name() + " has no field " + entry.first->get_string());
}
if (first) {
render << capitalize(field.name());
first = false;
} else {
render << " " << field.name();
}
render << ": " << render_const_value(name, field.get_type(), entry.second);
}
render << "]";
} else if (type->is_map()) {
render << "[[NSDictionary alloc] initWithObjectsAndKeys: ";
const t_type* ktype = ((t_map*)type)->get_key_type();
const t_type* vtype = ((t_map*)type)->get_val_type();
const std::map<t_const_value*, t_const_value*>& val = value->get_map();
std::map<t_const_value*, t_const_value*>::const_iterator v_iter;
bool first = true;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
std::string key = render_const_value(name, ktype, v_iter->first, true);
std::string val = render_const_value(name, vtype, v_iter->second, true);
if (first) {
first = false;
} else {
render << ", ";
}
render << val << ", " << key;
}
if (first)
render << " nil]";
else
render << ", nil]";
} else if (type->is_list()) {
render << "[[NSArray alloc] initWithObjects: ";
t_type * etype = ((t_list*)type)->get_elem_type();
const std::vector<t_const_value*>& val = value->get_list();
bool first = true;
std::vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
if (first) {
first = false;
} else {
render << ", ";
}
render << render_const_value(name, etype, *v_iter, true);
}
if (first)
render << " nil]";
else
render << ", nil]";
} else if (type->is_set()) {
render << "[[NSSet alloc] initWithObjects: ";
t_type * etype = ((t_set*)type)->get_elem_type();
const std::vector<t_const_value*>& val = value->get_list();
bool first = true;
std::vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
if (first) {
first = false;
} else {
render << ", ";
}
render << render_const_value(name, etype, *v_iter, true);
}
if (first)
render << " nil]";
else
render << ", nil]";
} else {
throw std::runtime_error("don't know how to render constant for type: " + type->name());
}
if (containerize_it) {
return containerize(type, render.str());
}
return render.str();
}