Thrift C++ code generator returns complex types by reference

Summary: Efficiency, Yo.

Reviewed By: aditya


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664910 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 68a491b..efe327b 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -788,10 +788,15 @@
       f_header_ <<
         indent() << "return;" << endl;
     } else {
-      t_field returnfield(returntype, "rval");
-      f_header_ <<
-        indent() << declare_field(&returnfield, true) << endl <<
-        indent() << "return rval;" << endl;
+      if (is_complex_type(returntype)) {
+        f_header_ <<
+          indent() << "return;" << endl;
+      } else {
+        t_field returnfield(returntype, "_return");
+        f_header_ <<
+          indent() << declare_field(&returnfield, true) << endl <<
+          indent() << "return _return;" << endl;
+      }
     }
     indent_down();
     f_header_ <<
@@ -873,6 +878,10 @@
 
     string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
     bool first = true;
+    if (is_complex_type((*f_iter)->get_returntype())) {
+      call += "_return";
+      first = false;
+    }
     for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
       if (first) {
         first = false;
@@ -891,8 +900,16 @@
       indent() << "for (uint32_t i = 0; i < sz; ++i) {" << endl;
     if (!(*f_iter)->get_returntype()->is_void()) {
       f_header_ <<
-        indent() << "  if (i == sz - 1) {" << endl <<
-        indent() << "    return " << call << ";" << endl <<
+        indent() << "  if (i == sz - 1) {" << endl;
+      if (is_complex_type((*f_iter)->get_returntype())) {
+        f_header_ <<
+          indent() << "    " << call << ";" << endl <<
+          indent() << "    return;" << endl;
+      } else {
+        f_header_ <<
+          indent() << "    return " << call << ";" << endl;
+      }
+      f_header_ <<
         indent() << "  } else {" << endl <<
         indent() << "    " << call << ";" << endl <<
         indent() << "  }" << endl;
@@ -1024,10 +1041,15 @@
     if (!(*f_iter)->is_async()) {
       f_service_ << indent();
       if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ << "return ";
+        if (is_complex_type((*f_iter)->get_returntype())) {
+          f_service_ << "recv_" << funname << "(_return);" << endl;
+        } else {
+          f_service_ << "return recv_" << funname << "();" << endl;
+        }
+      } else {
+        f_service_ <<
+          "recv_" << funname << "();" << endl;
       }
-      f_service_ <<
-        "recv_" << funname << "();" << endl;
     }
     scope_down(f_service_);
     f_service_ << endl;
@@ -1100,10 +1122,18 @@
 
       // Careful, only look for _result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
-        f_service_ <<
-          indent() << "if (result.__isset.success) {" << endl <<
-          indent() << "  return result.success;" << endl <<
-          indent() << "}" << endl;
+        if (is_complex_type((*f_iter)->get_returntype())) {
+          f_service_ <<
+            indent() << "if (result.__isset.success) {" << endl <<
+            indent() << "  _return = result.success;" << endl <<
+            indent() << "  return;" << endl <<
+            indent() << "}" << endl;
+        } else {
+          f_service_ <<
+            indent() << "if (result.__isset.success) {" << endl <<
+            indent() << "  return result.success;" << endl <<
+            indent() << "}" << endl;
+        }
       }
 
       t_struct* xs = (*f_iter)->get_xceptions();
@@ -1349,13 +1379,19 @@
   const std::vector<t_field*>& fields = arg_struct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
+  bool first = true;
   f_service_ << indent();
   if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
-    f_service_ << "result.success = ";    
+    if (is_complex_type(tfunction->get_returntype())) {
+      first = false;
+      f_service_ << "iface_->" << tfunction->get_name() << "(result.success";
+    } else {
+      f_service_ << "result.success = iface_->" << tfunction->get_name() << "(";
+    }
+  } else {
+    f_service_ <<
+      "iface_->" << tfunction->get_name() << "(";
   }
-  f_service_ <<
-    "iface_->" << tfunction->get_name() << "(";
-  bool first = true;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     if (first) {
       first = false;
@@ -2095,9 +2131,19 @@
 string t_cpp_generator::function_signature(t_function* tfunction,
                                            string prefix) {
   t_type* ttype = tfunction->get_returntype();
-  return
-    type_name(ttype) + " " + prefix + tfunction->get_name() +
-    "(" + argument_list(tfunction->get_arglist()) + ")";
+  t_struct* arglist = tfunction->get_arglist();
+
+  if (is_complex_type(ttype)) {
+    bool empty = arglist->get_members().size() == 0;
+    return
+      "void " + prefix + tfunction->get_name() +
+      "(" + type_name(ttype) + "& _return" +
+      (empty ? "" : (", " + argument_list(arglist))) + ")";
+  } else {
+    return
+      type_name(ttype) + " " + prefix + tfunction->get_name() +
+      "(" + argument_list(arglist) + ")";
+  }
 }
 
 /**
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index aae6f4f..886279d 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -134,6 +134,14 @@
   std::string argument_list(t_struct* tstruct);
   std::string type_to_enum(t_type* ttype);
 
+  bool is_complex_type(t_type* ttype) {
+    return
+      ttype->is_container() || 
+      ttype->is_struct() ||
+      ttype->is_xception() ||
+      (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
+  }
+
  private:
 
   /**