in compiler/cpp/src/thrift/generate/t_c_glib_generator.cc [997:1215]
void t_c_glib_generator::generate_const_initializer(string name,
t_type* type,
t_const_value* value,
bool top_level) {
string name_u = initial_caps_to_underscores(name);
string name_lc = to_lower_case(name_u);
string type_u = initial_caps_to_underscores(type->get_name());
string type_uc = to_upper_case(type_u);
string maybe_static = top_level ? "" : "static ";
if (type->is_struct() || type->is_xception()) {
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
ostringstream initializers;
// initialize any constants that may be referenced by this initializer
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
t_type* field_type = nullptr;
string field_name = "";
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
if ((*f_iter)->get_name() == v_iter->first->get_string()) {
field_type = (*f_iter)->get_type();
field_name = (*f_iter)->get_name();
break;
}
}
if (field_type == nullptr) {
throw "type error: " + type->get_name() + " has no field "
+ v_iter->first->get_string();
}
field_name = tmp(field_name);
generate_const_initializer(name + "_constant_" + field_name,
field_type,
v_iter->second);
initializers << " constant->" << v_iter->first->get_string() << " = "
<< constant_value(name + "_constant_" + field_name,
field_type,
v_iter->second) << ";" << '\n'
<< " constant->__isset_" << v_iter->first->get_string()
<< " = TRUE;" << '\n';
}
// implement the initializer
f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *"
<< '\n'
<< this->nspace_lc << name_lc << "_constant (void)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "static " << this->nspace << type->get_name()
<< " *constant = NULL;" << '\n'
<< indent() << "if (constant == NULL)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc
<< "TYPE_" << type_uc << ", NULL);" << '\n'
<< initializers.str();
scope_down(f_types_impl_);
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
t_type* field_type = nullptr;
string field_name = "";
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
if ((*f_iter)->get_name() == v_iter->first->get_string()) {
field_type = (*f_iter)->get_type();
field_name = (*f_iter)->get_name();
break;
}
}
if (field_type == nullptr) {
throw "type error: " + type->get_name() + " has no field "
+ v_iter->first->get_string();
}
field_name = tmp(field_name);
}
f_types_impl_ << indent() << "return constant;" << '\n';
scope_down(f_types_impl_);
f_types_impl_ << '\n';
} else if (type->is_list()) {
string list_type = "GPtrArray *";
string free_func
= generate_free_func_from_type(reinterpret_cast<t_list*>(type)->get_elem_type());
string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");";
string list_appender = "g_ptr_array_add";
bool list_variable = false;
t_type* etype = ((t_list*)type)->get_elem_type();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
ostringstream initializers;
ostringstream appenders;
list_initializer = generate_new_array_from_type(etype);
if (etype->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
switch (tbase) {
case t_base_type::TYPE_VOID:
throw "compiler error: cannot determine array type";
case t_base_type::TYPE_BOOL:
case t_base_type::TYPE_I8:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
case t_base_type::TYPE_DOUBLE:
list_type = "GArray *";
list_appender = "g_array_append_val";
list_variable = true;
break;
case t_base_type::TYPE_STRING:
break;
default:
throw "compiler error: no array info for type";
}
} else if (etype->is_enum()) {
list_type = "GArray *";
list_appender = "g_array_append_val";
list_variable = true;
}
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string fname = tmp(name);
generate_const_initializer(fname, etype, (*v_iter));
if (list_variable) {
initializers << " " << type_name(etype) << " " << fname << " = "
<< constant_value(fname, (t_type*)etype, (*v_iter)) << ";"
<< '\n';
appenders << " " << list_appender << "(constant, " << fname << ");"
<< '\n';
} else {
appenders << " " << list_appender << "(constant, "
<< constant_value(fname, (t_type*)etype, (*v_iter)) << ");"
<< '\n';
}
}
f_types_impl_ << maybe_static << list_type << '\n'
<< this->nspace_lc << name_lc << "_constant (void)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "static " << list_type << " constant = NULL;"
<< '\n'
<< indent() << "if (constant == NULL)" << '\n';
scope_up(f_types_impl_);
if (!initializers.str().empty()) {
f_types_impl_ << initializers.str()
<< '\n';
}
f_types_impl_ << indent() << "constant = " << list_initializer << '\n'
<< appenders.str();
scope_down(f_types_impl_);
f_types_impl_ << indent() << "return constant;" << '\n';
scope_down(f_types_impl_);
f_types_impl_ << '\n';
} else if (type->is_set()) {
t_type* etype = ((t_set*)type)->get_elem_type();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
ostringstream initializers;
ostringstream appenders;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string fname = tmp(name);
string ptr = is_numeric(etype) ? "*" : "";
generate_const_initializer(fname, etype, (*v_iter));
initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter);
appenders << " g_hash_table_insert (constant, " << fname << ", 0);" << '\n';
}
f_types_impl_ << maybe_static << "GHashTable *" << '\n'
<< this->nspace_lc << name_lc << "_constant (void)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << '\n'
<< indent() << "if (constant == NULL)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << initializers.str() << '\n'
<< indent() << "constant = " << generate_new_hash_from_type(etype, nullptr) << '\n'
<< appenders.str();
scope_down(f_types_impl_);
f_types_impl_ << indent() << "return constant;" << '\n';
scope_down(f_types_impl_);
f_types_impl_ << '\n';
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
ostringstream initializers;
ostringstream appenders;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
string fname = tmp(name);
string kname = fname + "key";
string vname = fname + "val";
generate_const_initializer(kname, ktype, v_iter->first);
generate_const_initializer(vname, vtype, v_iter->second);
initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first);
initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second);
appenders << " g_hash_table_insert (constant, " << kname << ", " << vname << ");" << '\n';
}
f_types_impl_ << maybe_static << "GHashTable *" << '\n'
<< this->nspace_lc << name_lc << "_constant (void)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << '\n'
<< indent() << "if (constant == NULL)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << initializers.str() << '\n'
<< indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << '\n'
<< appenders.str();
scope_down(f_types_impl_);
f_types_impl_ << indent() << "return constant;" << '\n';
scope_down(f_types_impl_);
f_types_impl_ << '\n';
}
}