in compiler/cpp/src/thrift/generate/t_c_glib_generator.cc [1837:2052]
void t_c_glib_generator::generate_service_handler(t_service* tservice) {
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::const_iterator function_iter;
string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
string service_name_uc = to_upper_case(service_name_lc);
string service_handler_name = service_name_ + "Handler";
string class_name = this->nspace + service_handler_name;
string class_name_lc = this->nspace_lc + initial_caps_to_underscores(service_handler_name);
string class_name_uc = to_upper_case(class_name_lc);
string parent_class_name;
string parent_type_name;
string args_indent;
// The service this service extends, or nullptr if it extends no service
t_service* extends_service = tservice->get_extends();
// Determine the name of our parent service (if any) and the handler class'
// parent class name and type
if (extends_service) {
string parent_service_name = extends_service->get_name();
string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
string parent_service_name_uc = to_upper_case(parent_service_name_lc);
parent_class_name = this->nspace + parent_service_name + "Handler";
parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER";
} else {
parent_class_name = "GObject";
parent_type_name = "G_TYPE_OBJECT";
}
// Generate the handler class' definition in the header file
// Generate the handler instance definition
f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << '\n' << "struct _"
<< class_name << '\n' << "{" << '\n';
indent_up();
f_header_ << indent() << parent_class_name << " parent;" << '\n';
indent_down();
f_header_ << "};" << '\n' << "typedef struct _" << class_name << " " << class_name << ";" << '\n'
<< '\n';
// Generate the handler class definition, including its class members
// (methods)
f_header_ << "struct _" << class_name << "Class" << '\n' << "{" << '\n';
indent_up();
f_header_ << indent() << parent_class_name << "Class parent;" << '\n' << '\n';
for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
string method_name = initial_caps_to_underscores((*function_iter)->get_name());
t_type* return_type = (*function_iter)->get_returntype();
t_struct* arg_list = (*function_iter)->get_arglist();
t_struct* x_list = (*function_iter)->get_xceptions();
bool has_return = !return_type->is_void();
bool has_args = arg_list->get_members().size() == 0;
bool has_xceptions = x_list->get_members().size() == 0;
string params = "(" + this->nspace + service_name_ + "If *iface"
+ (has_return ? ", " + type_name(return_type) + "* _return" : "")
+ (has_args ? "" : (", " + argument_list(arg_list)))
+ (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << '\n';
}
indent_down();
f_header_ << "};" << '\n' << "typedef struct _" << class_name << "Class " << class_name
<< "Class;" << '\n' << '\n';
// Generate the remaining header boilerplate
f_header_ << "GType " << class_name_lc << "_get_type (void);" << '\n' << "#define "
<< this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER "
<< "(" << class_name_lc << "_get_type())" << '\n' << "#define " << class_name_uc
<< "(obj) "
<< "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
<< service_name_uc << "_HANDLER, " << class_name << "))" << '\n' << "#define "
<< this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) "
<< "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
<< service_name_uc << "_HANDLER))" << '\n' << "#define " << class_name_uc
<< "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_"
<< service_name_uc << "_HANDLER, " << class_name << "Class))" << '\n' << "#define "
<< this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) "
<< "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
<< "_HANDLER))" << '\n' << "#define " << this->nspace_uc << service_name_uc
<< "_HANDLER_GET_CLASS(obj) "
<< "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
<< service_name_uc << "_HANDLER, " << class_name << "Class))" << '\n' << '\n';
// Generate the handler class' method definitions
for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
string method_name = initial_caps_to_underscores((*function_iter)->get_name());
t_type* return_type = (*function_iter)->get_returntype();
t_struct* arg_list = (*function_iter)->get_arglist();
t_struct* x_list = (*function_iter)->get_xceptions();
bool has_return = !return_type->is_void();
bool has_args = arg_list->get_members().size() == 0;
bool has_xceptions = x_list->get_members().size() == 0;
string params = "(" + this->nspace + service_name_ + "If *iface"
+ (has_return ? ", " + type_name(return_type) + "* _return" : "")
+ (has_args ? "" : (", " + argument_list(arg_list)))
+ (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << '\n';
}
f_header_ << '\n';
// Generate the handler's implementation in the implementation file
// Generate the implementation boilerplate
f_service_ << "static void" << '\n' << class_name_lc << "_" << service_name_lc
<< "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
<< '\n' << '\n';
args_indent = string(25, ' ');
f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << '\n' << args_indent
<< class_name_lc << "," << '\n' << args_indent << parent_type_name << "," << '\n'
<< args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
<< service_name_uc << "_IF," << '\n';
args_indent += string(23, ' ');
f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))"
<< '\n' << '\n';
// Generate the handler method implementations
for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
string function_name = (*function_iter)->get_name();
string method_name = initial_caps_to_underscores(function_name);
t_type* return_type = (*function_iter)->get_returntype();
t_struct* arg_list = (*function_iter)->get_arglist();
t_struct* x_list = (*function_iter)->get_xceptions();
const vector<t_field*>& args = arg_list->get_members();
const vector<t_field*>& xceptions = x_list->get_members();
vector<t_field*>::const_iterator field_iter;
t_function implementing_function(return_type,
service_name_lc + "_handler_" + method_name,
arg_list,
x_list,
(*function_iter)->is_oneway());
indent(f_service_) << function_signature(&implementing_function) << '\n';
scope_up(f_service_);
f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_"
<< service_name_uc << "_HANDLER (iface), FALSE);" << '\n' << '\n' << indent()
<< "return " << class_name_uc << "_GET_CLASS (iface)"
<< "->" << method_name << " (iface, ";
if (!return_type->is_void()) {
f_service_ << "_return, ";
}
for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) {
f_service_ << (*field_iter)->get_name() << ", ";
}
for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) {
f_service_ << (*field_iter)->get_name() << ", ";
}
f_service_ << "error);" << '\n';
scope_down(f_service_);
f_service_ << '\n';
}
// Generate the handler interface initializer
f_service_ << "static void" << '\n' << class_name_lc << "_" << service_name_lc
<< "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)"
<< '\n';
scope_up(f_service_);
if (functions.size() > 0) {
for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
string method_name = initial_caps_to_underscores((*function_iter)->get_name());
f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_"
<< method_name << ";" << '\n';
}
}
else {
f_service_ << "THRIFT_UNUSED_VAR (iface);" << '\n';
}
scope_down(f_service_);
f_service_ << '\n';
// Generate the handler instance initializer
f_service_ << "static void" << '\n' << class_name_lc << "_init (" << class_name << " *self)"
<< '\n';
scope_up(f_service_);
f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << '\n';
scope_down(f_service_);
f_service_ << '\n';
// Generate the handler class initializer
f_service_ << "static void" << '\n'
<< class_name_lc << "_class_init (" << class_name << "Class *cls)"
<< '\n';
scope_up(f_service_);
if (functions.size() > 0) {
for (function_iter = functions.begin();
function_iter != functions.end();
++function_iter) {
string function_name = (*function_iter)->get_name();
string method_name = initial_caps_to_underscores(function_name);
// All methods are pure virtual and must be implemented by subclasses
f_service_ << indent() << "cls->" << method_name << " = NULL;" << '\n';
}
}
else {
f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << '\n';
}
scope_down(f_service_);
f_service_ << '\n';
}