in compiler/cpp/src/thrift/generate/t_c_glib_generator.cc [2795:3502]
void t_c_glib_generator::generate_object(t_struct* tstruct) {
string name = tstruct->get_name();
string name_u = initial_caps_to_underscores(name);
string name_uc = to_upper_case(name_u);
string class_name = this->nspace + name;
string class_name_lc = this->nspace_lc + initial_caps_to_underscores(name);
string class_name_uc = to_upper_case(class_name_lc);
string function_name;
string args_indent;
// write the instance definition
f_types_ << "struct _" << this->nspace << name << '\n' << "{ " << '\n'
<< " ThriftStruct parent; " << '\n' << '\n' << " /* public */" << '\n';
// for each field, add a member variable
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& members = tstruct->get_members();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = get_true_type((*m_iter)->get_type());
f_types_ << " " << type_name(t) << " " << (*m_iter)->get_name() << ";" << '\n';
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
f_types_ << " gboolean __isset_" << (*m_iter)->get_name() << ";" << '\n';
}
}
// close the structure definition and create a typedef
f_types_ << "};" << '\n' << "typedef struct _" << this->nspace << name << " " << this->nspace
<< name << ";" << '\n' << '\n';
// write the class definition
f_types_ << "struct _" << this->nspace << name << "Class" << '\n' << "{" << '\n'
<< " ThriftStructClass parent;" << '\n' << "};" << '\n' << "typedef struct _"
<< this->nspace << name << "Class " << this->nspace << name << "Class;" << '\n' << '\n';
// write the standard GObject boilerplate
f_types_ << "GType " << this->nspace_lc << name_u << "_get_type (void);" << '\n' << "#define "
<< this->nspace_uc << "TYPE_" << name_uc << " (" << this->nspace_lc << name_u
<< "_get_type())" << '\n' << "#define " << this->nspace_uc << name_uc
<< "(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << name_uc
<< ", " << this->nspace << name << "))" << '\n' << "#define " << this->nspace_uc
<< name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "_TYPE_"
<< name_uc << ", " << this->nspace << name << "Class))" << '\n' << "#define "
<< this->nspace_uc << "IS_" << name_uc << "(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), "
<< this->nspace_uc << "TYPE_" << name_uc << "))" << '\n' << "#define " << this->nspace_uc
<< "IS_" << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc
<< "TYPE_" << name_uc << "))" << '\n' << "#define " << this->nspace_uc << name_uc
<< "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
<< name_uc << ", " << this->nspace << name << "Class))" << '\n' << '\n';
// start writing the object implementation .c file
// generate properties enum
if (members.size() > 0) {
f_types_impl_ << "enum _" << class_name << "Properties" << '\n' << "{" << '\n';
indent_up();
f_types_impl_ << indent() << "PROP_" << class_name_uc << "_0";
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
string member_name_uc
= to_upper_case(to_lower_case(initial_caps_to_underscores((*m_iter)->get_name())));
f_types_impl_ << "," << '\n' << indent() << "PROP_" << class_name_uc << "_" << member_name_uc;
}
f_types_impl_ << '\n';
indent_down();
f_types_impl_ << "};" << '\n' << '\n';
}
// generate struct I/O methods
string this_get = this->nspace + name + " * this_object = " + this->nspace_uc + name_uc
+ "(object);";
generate_struct_reader(f_types_impl_, tstruct, "this_object->", this_get);
generate_struct_writer(f_types_impl_, tstruct, "this_object->", this_get);
// generate property setter and getter
if (members.size() > 0) {
// generate property setter
function_name = class_name_lc + "_set_property";
args_indent = string(function_name.length() + 2, ' ');
f_types_impl_ << "static void" << '\n' << function_name << " (GObject *object," << '\n'
<< args_indent << "guint property_id," << '\n' << args_indent
<< "const GValue *value," << '\n' << args_indent << "GParamSpec *pspec)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << '\n'
<< '\n' << indent() << "switch (property_id)" << '\n';
scope_up(f_types_impl_);
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* member = (*m_iter);
string member_name = member->get_name();
string member_name_uc
= to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
t_type* member_type = get_true_type(member->get_type());
string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
f_types_impl_ << indent() << "case " << property_identifier + ":" << '\n';
indent_up();
if (member_type->is_base_type()) {
t_base_type* base_type = ((t_base_type*)member_type);
string assign_function_name;
if (base_type->get_base() == t_base_type::TYPE_STRING) {
string release_function_name;
f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << '\n';
indent_up();
if (base_type->is_binary()) {
release_function_name = "g_byte_array_unref";
assign_function_name = "g_value_dup_boxed";
} else {
release_function_name = "g_free";
assign_function_name = "g_value_dup_string";
}
f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");"
<< '\n';
indent_down();
} else {
switch (base_type->get_base()) {
case t_base_type::TYPE_BOOL:
assign_function_name = "g_value_get_boolean";
break;
case t_base_type::TYPE_I8:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
assign_function_name = "g_value_get_int";
break;
case t_base_type::TYPE_I64:
assign_function_name = "g_value_get_int64";
break;
case t_base_type::TYPE_DOUBLE:
assign_function_name = "g_value_get_double";
break;
default:
throw "compiler error: "
"unrecognized base type \"" + base_type->get_name() + "\" "
"for struct member \""
+ member_name + "\"";
break;
}
}
f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name
<< " (value);" << '\n';
} else if (member_type->is_enum()) {
f_types_impl_ << indent() << "self->" << member_name << " = g_value_get_int (value);"
<< '\n';
} else if (member_type->is_container()) {
string release_function_name;
string assign_function_name;
if (member_type->is_list()) {
t_type* elem_type = ((t_list*)member_type)->get_elem_type();
// Lists of base types other than strings are represented as GArrays;
// all others as GPtrArrays
if (is_numeric(elem_type)) {
release_function_name = "g_array_unref";
} else {
release_function_name = "g_ptr_array_unref";
}
assign_function_name = "g_value_dup_boxed";
} else if (member_type->is_set() || member_type->is_map()) {
release_function_name = "g_hash_table_unref";
assign_function_name = "g_value_dup_boxed";
}
f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << '\n';
indent_up();
f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");"
<< '\n';
indent_down();
f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name
<< " (value);" << '\n';
} else if (member_type->is_struct() || member_type->is_xception()) {
f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << '\n';
indent_up();
f_types_impl_ << indent() << "g_object_unref (self->" << member_name << ");" << '\n';
indent_down();
f_types_impl_ << indent() << "self->" << member_name << " = g_value_dup_object (value);"
<< '\n';
}
if (member->get_req() != t_field::T_REQUIRED) {
f_types_impl_ << indent() << "self->__isset_" << member_name << " = TRUE;" << '\n';
}
f_types_impl_ << indent() << "break;" << '\n' << '\n';
indent_down();
}
f_types_impl_ << indent() << "default:" << '\n';
indent_up();
f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
<< '\n' << indent() << "break;" << '\n';
indent_down();
scope_down(f_types_impl_);
scope_down(f_types_impl_);
f_types_impl_ << '\n';
// generate property getter
function_name = class_name_lc + "_get_property";
args_indent = string(function_name.length() + 2, ' ');
f_types_impl_ << "static void" << '\n' << function_name << " (GObject *object," << '\n'
<< args_indent << "guint property_id," << '\n' << args_indent << "GValue *value,"
<< '\n' << args_indent << "GParamSpec *pspec)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << '\n'
<< '\n' << indent() << "switch (property_id)" << '\n';
scope_up(f_types_impl_);
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* member = (*m_iter);
string member_name = (*m_iter)->get_name();
string member_name_uc
= to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
t_type* member_type = get_true_type(member->get_type());
string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
string setter_function_name;
if (member_type->is_base_type()) {
t_base_type* base_type = ((t_base_type*)member_type);
switch (base_type->get_base()) {
case t_base_type::TYPE_BOOL:
setter_function_name = "g_value_set_boolean";
break;
case t_base_type::TYPE_I8:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
setter_function_name = "g_value_set_int";
break;
case t_base_type::TYPE_I64:
setter_function_name = "g_value_set_int64";
break;
case t_base_type::TYPE_DOUBLE:
setter_function_name = "g_value_set_double";
break;
case t_base_type::TYPE_STRING:
if (base_type->is_binary()) {
setter_function_name = "g_value_set_boxed";
} else {
setter_function_name = "g_value_set_string";
}
break;
default:
throw "compiler error: "
"unrecognized base type \"" + base_type->get_name() + "\" "
"for struct member \""
+ member_name + "\"";
break;
}
} else if (member_type->is_enum()) {
setter_function_name = "g_value_set_int";
} else if (member_type->is_struct() || member_type->is_xception()) {
setter_function_name = "g_value_set_object";
} else if (member_type->is_container()) {
setter_function_name = "g_value_set_boxed";
} else {
throw "compiler error: "
"unrecognized type for struct member \"" + member_name + "\"";
}
f_types_impl_ << indent() << "case " << property_identifier + ":" << '\n';
indent_up();
f_types_impl_ << indent() << setter_function_name << " (value, self->" << member_name << ");"
<< '\n' << indent() << "break;" << '\n' << '\n';
indent_down();
}
f_types_impl_ << indent() << "default:" << '\n';
indent_up();
f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
<< '\n' << indent() << "break;" << '\n';
indent_down();
scope_down(f_types_impl_);
scope_down(f_types_impl_);
f_types_impl_ << '\n';
}
// generate the instance init function
f_types_impl_ << "static void " << '\n' << this->nspace_lc << name_u << "_instance_init ("
<< this->nspace << name << " * object)" << '\n' << "{" << '\n';
indent_up();
// generate default-value structures for container-type members
bool constant_declaration_output = false;
bool string_list_constant_output = false;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* member = *m_iter;
t_const_value* member_value = member->get_value();
if (member_value != nullptr) {
string member_name = member->get_name();
t_type* member_type = get_true_type(member->get_type());
if (member_type->is_list()) {
const vector<t_const_value*>& list = member_value->get_list();
t_type* elem_type = ((t_list*)member_type)->get_elem_type();
// Generate an array with the list literal
indent(f_types_impl_) << "static " << type_name(elem_type, false, true) << " __default_"
<< member_name << "[" << list.size() << "] = " << '\n';
indent_up();
f_types_impl_ << indent() << constant_literal(member_type, member_value) << ";" << '\n';
indent_down();
constant_declaration_output = true;
// If we are generating values for a pointer array (i.e. a list of
// strings), set a flag so we know to also declare an index variable to
// use in pre-populating the array
if (elem_type->is_string()) {
string_list_constant_output = true;
}
}
// TODO: Handle container types other than list
}
}
if (constant_declaration_output) {
if (string_list_constant_output) {
indent(f_types_impl_) << "unsigned int list_index;" << '\n';
}
f_types_impl_ << '\n';
}
// satisfy compilers with -Wall turned on
indent(f_types_impl_) << "/* satisfy -Wall */" << '\n' << indent()
<< "THRIFT_UNUSED_VAR (object);" << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* member_type = (*m_iter)->get_type();
t_type* t = get_true_type(member_type);
if (t->is_base_type()) {
string dval = " = ";
if (t->is_enum()) {
dval += "(" + type_name(t) + ")";
}
t_const_value* cv = (*m_iter)->get_value();
if (cv != nullptr) {
dval += constant_value("", t, cv);
} else {
dval += t->is_string() ? "NULL" : "0";
}
indent(f_types_impl_) << "object->" << (*m_iter)->get_name() << dval << ";" << '\n';
} else if (t->is_struct()) {
string name = (*m_iter)->get_name();
t_program* type_program = member_type->get_program();
string type_nspace = type_program ? type_program->get_namespace("c_glib") : "";
string type_nspace_prefix =
type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_";
string type_name_uc = to_upper_case(initial_caps_to_underscores(member_type->get_name()));
indent(f_types_impl_) << "object->" << name << " = g_object_new ("
<< to_upper_case(type_nspace_prefix) << "TYPE_" << type_name_uc
<< ", NULL);" << '\n';
} else if (t->is_xception()) {
string name = (*m_iter)->get_name();
indent(f_types_impl_) << "object->" << name << " = NULL;" << '\n';
} else if (t->is_container()) {
string name = (*m_iter)->get_name();
string init_function;
t_type* etype = nullptr;
if (t->is_map()) {
t_type* key = ((t_map*)t)->get_key_type();
t_type* value = ((t_map*)t)->get_val_type();
init_function = generate_new_hash_from_type(key, value);
} else if (t->is_set()) {
etype = ((t_set*)t)->get_elem_type();
init_function = generate_new_hash_from_type(etype, nullptr);
} else if (t->is_list()) {
etype = ((t_list*)t)->get_elem_type();
init_function = generate_new_array_from_type(etype);
}
indent(f_types_impl_) << "object->" << name << " = " << init_function << '\n';
// Pre-populate the container with the specified default values, if any
if ((*m_iter)->get_value()) {
t_const_value* member_value = (*m_iter)->get_value();
if (t->is_list()) {
const vector<t_const_value*>& list = member_value->get_list();
if (is_numeric(etype)) {
indent(f_types_impl_) <<
"g_array_append_vals (object->" << name << ", &__default_" <<
name << ", " << list.size() << ");" << '\n';
}
else {
indent(f_types_impl_) <<
"for (list_index = 0; list_index < " << list.size() << "; " <<
"list_index += 1)" << '\n';
indent_up();
indent(f_types_impl_) <<
"g_ptr_array_add (object->" << name << "," << '\n' <<
indent() << string(17, ' ') << "g_strdup (__default_" <<
name << "[list_index]));" << '\n';
indent_down();
}
}
// TODO: Handle container types other than list
}
}
/* if not required, initialize the __isset variable */
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
indent(f_types_impl_) << "object->__isset_" << (*m_iter)->get_name() << " = FALSE;" << '\n';
}
}
indent_down();
f_types_impl_ << "}" << '\n' << '\n';
/* create the destructor */
f_types_impl_ << "static void " << '\n' << this->nspace_lc << name_u
<< "_finalize (GObject *object)" << '\n' << "{" << '\n';
indent_up();
f_types_impl_ << indent() << this->nspace << name << " *tobject = " << this->nspace_uc << name_uc
<< " (object);" << '\n' << '\n';
f_types_impl_ << indent() << "/* satisfy -Wall in case we don't use tobject */" << '\n'
<< indent() << "THRIFT_UNUSED_VAR (tobject);" << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = get_true_type((*m_iter)->get_type());
if (t->is_container()) {
string name = (*m_iter)->get_name();
if (t->is_map() || t->is_set()) {
f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << '\n';
f_types_impl_ << indent() << "{" << '\n';
indent_up();
f_types_impl_ << indent() << "g_hash_table_destroy (tobject->" << name << ");" << '\n';
f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << '\n';
indent_down();
f_types_impl_ << indent() << "}" << '\n';
} else if (t->is_list()) {
t_type* etype = ((t_list*)t)->get_elem_type();
string destructor_function = "g_ptr_array_unref";
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:
destructor_function = "g_array_unref";
break;
case t_base_type::TYPE_STRING:
break;
default:
throw "compiler error: no array info for type";
}
} else if (etype->is_enum()) {
destructor_function = "g_array_unref";
}
f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << '\n';
f_types_impl_ << indent() << "{" << '\n';
indent_up();
f_types_impl_ << indent() << destructor_function << " (tobject->" << name << ");" << '\n';
f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << '\n';
indent_down();
f_types_impl_ << indent() << "}" << '\n';
}
} else if (t->is_struct() || t->is_xception()) {
string name = (*m_iter)->get_name();
// TODO: g_clear_object needs glib >= 2.28
// f_types_impl_ << indent() << "g_clear_object (&(tobject->" << name << "));" << '\n';
// does g_object_unref the trick?
f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << '\n';
f_types_impl_ << indent() << "{" << '\n';
indent_up();
f_types_impl_ << indent() << "g_object_unref(tobject->" << name << ");" << '\n';
f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << '\n';
indent_down();
f_types_impl_ << indent() << "}" << '\n';
} else if (t->is_string()) {
string name = (*m_iter)->get_name();
f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << '\n';
f_types_impl_ << indent() << "{" << '\n';
indent_up();
f_types_impl_ << indent() << generate_free_func_from_type(t) << "(tobject->" << name << ");"
<< '\n';
f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << '\n';
indent_down();
f_types_impl_ << indent() << "}" << '\n';
}
}
indent_down();
f_types_impl_ << "}" << '\n' << '\n';
// generate the class init function
f_types_impl_ << "static void" << '\n' << class_name_lc << "_class_init (" << class_name
<< "Class * cls)" << '\n';
scope_up(f_types_impl_);
f_types_impl_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << '\n'
<< indent() << "ThriftStructClass *struct_class = "
<< "THRIFT_STRUCT_CLASS (cls);" << '\n' << '\n' << indent()
<< "struct_class->read = " << class_name_lc << "_read;" << '\n' << indent()
<< "struct_class->write = " << class_name_lc << "_write;" << '\n' << '\n'
<< indent() << "gobject_class->finalize = " << class_name_lc << "_finalize;"
<< '\n';
if (members.size() > 0) {
f_types_impl_ << indent() << "gobject_class->get_property = " << class_name_lc
<< "_get_property;" << '\n' << indent()
<< "gobject_class->set_property = " << class_name_lc << "_set_property;" << '\n';
// install a property for each member
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* member = (*m_iter);
string member_name = member->get_name();
string member_name_uc
= to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
t_type* member_type = get_true_type(member->get_type());
t_const_value* member_value = member->get_value();
string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
f_types_impl_ << '\n' << indent() << "g_object_class_install_property" << '\n';
indent_up();
args_indent = indent() + ' ';
f_types_impl_ << indent() << "(gobject_class," << '\n' << args_indent << property_identifier
<< "," << '\n' << args_indent;
if (member_type->is_base_type()) {
t_base_type::t_base base_type = ((t_base_type*)member_type)->get_base();
if (base_type == t_base_type::TYPE_STRING) {
if (((t_base_type*)member_type)->is_binary()) {
args_indent += string(20, ' ');
f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< "G_TYPE_BYTE_ARRAY," << '\n' << args_indent << "G_PARAM_READWRITE));"
<< '\n';
} else {
args_indent += string(21, ' ');
f_types_impl_ << "g_param_spec_string (\"" << member_name << "\"," << '\n'
<< args_indent << "NULL," << '\n' << args_indent << "NULL," << '\n'
<< args_indent
<< ((member_value != NULL) ? "\"" + member_value->get_string() + "\""
: "NULL") << "," << '\n' << args_indent
<< "G_PARAM_READWRITE));" << '\n';
}
} else if (base_type == t_base_type::TYPE_BOOL) {
args_indent += string(22, ' ');
f_types_impl_ << "g_param_spec_boolean (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< (((member_value != NULL) && (member_value->get_integer() != 0))
? "TRUE"
: "FALSE") << "," << '\n' << args_indent << "G_PARAM_READWRITE));"
<< '\n';
} else if ((base_type == t_base_type::TYPE_I8) || (base_type == t_base_type::TYPE_I16)
|| (base_type == t_base_type::TYPE_I32) || (base_type == t_base_type::TYPE_I64)
|| (base_type == t_base_type::TYPE_DOUBLE)) {
string param_spec_function_name = "g_param_spec_int";
string min_value;
string max_value;
ostringstream default_value;
switch (base_type) {
case t_base_type::TYPE_I8:
min_value = "G_MININT8";
max_value = "G_MAXINT8";
break;
case t_base_type::TYPE_I16:
min_value = "G_MININT16";
max_value = "G_MAXINT16";
break;
case t_base_type::TYPE_I32:
min_value = "G_MININT32";
max_value = "G_MAXINT32";
break;
case t_base_type::TYPE_I64:
param_spec_function_name = "g_param_spec_int64";
min_value = "G_MININT64";
max_value = "G_MAXINT64";
break;
case t_base_type::TYPE_DOUBLE:
param_spec_function_name = "g_param_spec_double";
min_value = "-INFINITY";
max_value = "INFINITY";
break;
default:
throw "compiler error: "
"unrecognized base type \"" + member_type->get_name() + "\" "
"for struct member \""
+ member_name + "\"";
break;
}
if (member_value != nullptr) {
default_value << (base_type == t_base_type::TYPE_DOUBLE ? member_value->get_double()
: member_value->get_integer());
} else {
default_value << "0";
}
args_indent += string(param_spec_function_name.length() + 2, ' ');
f_types_impl_ << param_spec_function_name << " (\"" << member_name << "\"," << '\n'
<< args_indent << "NULL," << '\n' << args_indent << "NULL," << '\n'
<< args_indent << min_value << "," << '\n' << args_indent << max_value
<< "," << '\n' << args_indent << default_value.str() << "," << '\n'
<< args_indent << "G_PARAM_READWRITE));" << '\n';
}
indent_down();
} else if (member_type->is_enum()) {
t_enum_value* enum_min_value = ((t_enum*)member_type)->get_min_value();
t_enum_value* enum_max_value = ((t_enum*)member_type)->get_max_value();
int min_value = (enum_min_value != nullptr) ? enum_min_value->get_value() : 0;
int max_value = (enum_max_value != nullptr) ? enum_max_value->get_value() : 0;
args_indent += string(18, ' ');
f_types_impl_ << "g_param_spec_int (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< min_value << "," << '\n' << args_indent << max_value << "," << '\n'
<< args_indent << min_value << "," << '\n' << args_indent
<< "G_PARAM_READWRITE));" << '\n';
indent_down();
} else if (member_type->is_struct() || member_type->is_xception()) {
t_program* type_program = member_type->get_program();
string type_nspace = type_program ? type_program->get_namespace("c_glib") : "";
string type_nspace_prefix =
type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_";
string param_type = to_upper_case(type_nspace_prefix) + "TYPE_"
+ to_upper_case(initial_caps_to_underscores(member_type->get_name()));
args_indent += string(20, ' ');
f_types_impl_ << "g_param_spec_object (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< param_type << "," << '\n' << args_indent << "G_PARAM_READWRITE));" << '\n';
indent_down();
} else if (member_type->is_list()) {
t_type* elem_type = ((t_list*)member_type)->get_elem_type();
string param_type;
if (elem_type->is_base_type() && !elem_type->is_string()) {
param_type = "G_TYPE_ARRAY";
} else {
param_type = "G_TYPE_PTR_ARRAY";
}
args_indent += string(20, ' ');
f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< param_type << "," << '\n' << args_indent << "G_PARAM_READWRITE));" << '\n';
indent_down();
} else if (member_type->is_set() || member_type->is_map()) {
args_indent += string(20, ' ');
f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << '\n' << args_indent
<< "NULL," << '\n' << args_indent << "NULL," << '\n' << args_indent
<< "G_TYPE_HASH_TABLE," << '\n' << args_indent << "G_PARAM_READWRITE));"
<< '\n';
indent_down();
}
}
}
scope_down(f_types_impl_);
f_types_impl_ << '\n';
f_types_impl_ << "GType" << '\n' << this->nspace_lc << name_u << "_get_type (void)" << '\n' << "{"
<< '\n' << " static GType type = 0;" << '\n' << '\n' << " if (type == 0) " << '\n'
<< " {" << '\n' << " static const GTypeInfo type_info = " << '\n' << " {"
<< '\n' << " sizeof (" << this->nspace << name << "Class)," << '\n'
<< " NULL, /* base_init */" << '\n' << " NULL, /* base_finalize */"
<< '\n' << " (GClassInitFunc) " << this->nspace_lc << name_u << "_class_init,"
<< '\n' << " NULL, /* class_finalize */" << '\n'
<< " NULL, /* class_data */" << '\n' << " sizeof (" << this->nspace
<< name << ")," << '\n' << " 0, /* n_preallocs */" << '\n'
<< " (GInstanceInitFunc) " << this->nspace_lc << name_u << "_instance_init,"
<< '\n' << " NULL, /* value_table */" << '\n' << " };" << '\n' << '\n'
<< " type = g_type_register_static (THRIFT_TYPE_STRUCT, " << '\n'
<< " \"" << this->nspace << name << "Type\","
<< '\n' << " &type_info, 0);" << '\n' << " }"
<< '\n' << '\n' << " return type;" << '\n' << "}" << '\n' << '\n';
}