Improve Thrift map deserialization code

Summary: Instead of copy-constructing map values into the map, alter the code such that we insert default-constructed elements into the map and then deserialize them by reference.

Reviewed By: hzhao

Test Plan: Ran the test in test/cpp which include serialization and deserialization of nested maps.


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665448 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 1b560bc..2518509 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -70,7 +70,7 @@
 
   // Include the types file
   f_types_impl_ <<
-    "#include \"" << get_include_prefix(*get_program()) << program_name_ << 
+    "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
     "_types.h\"" << endl <<
     endl;
 
@@ -185,14 +185,14 @@
     "#ifndef " << program_name_ << "_CONSTANTS_H" << endl <<
     "#define " << program_name_ << "_CONSTANTS_H" << endl <<
     endl <<
-    "#include \"" << get_include_prefix(*get_program()) << program_name_ << 
+    "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
     "_types.h\"" << endl <<
     endl <<
     ns_open_ << endl <<
     endl;
 
   f_consts_impl <<
-    "#include \"" << get_include_prefix(*get_program()) << program_name_ << 
+    "#include \"" << get_include_prefix(*get_program()) << program_name_ <<
     "_constants.h\"" << endl <<
     endl <<
     ns_open_ << endl <<
@@ -2308,14 +2308,14 @@
   t_field fval(tmap->get_val_type(), val);
 
   out <<
-    indent() << declare_field(&fkey) << endl <<
-    indent() << declare_field(&fval) << endl;
+    indent() << declare_field(&fkey) << endl;
 
   generate_deserialize_field(out, &fkey);
-  generate_deserialize_field(out, &fval);
-
   indent(out) <<
-    prefix << ".insert(std::make_pair(" << key << ", " << val << "));" << endl;
+    declare_field(&fval, false, false, false, true) << " = " <<
+    prefix << "[" << key << "];" << endl;
+
+  generate_deserialize_field(out, &fval);
 }
 
 void t_cpp_generator::generate_deserialize_set_element(ofstream& out,
@@ -2701,7 +2701,7 @@
  * @param ttype The type
  * @return Field declaration, i.e. int x = 0;
  */
-string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant) {
+string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant, bool reference) {
   // TODO(mcslee): do we ever need to initialize the field?
   string result = "";
   if (constant) {
@@ -2711,6 +2711,9 @@
   if (pointer) {
     result += "*";
   }
+  if (reference) {
+    result += "&";
+  }
   result += " " + tfield->get_name();
   if (init) {
     t_type* type = get_true_type(tfield->get_type());
@@ -2742,7 +2745,10 @@
       result += " = (" + type_name(type) + ")0";
     }
   }
-  return result + ";";
+  if (!reference) {
+    result += ";";
+  }
+  return result;
 }
 
 /**
@@ -2887,6 +2893,6 @@
   if ((last_slash = include_prefix.rfind("/")) != string::npos) {
     return include_prefix.substr(0, last_slash) + "/" + out_dir_base_ + "/";
   }
-  
+
   return "";
 }
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index 4bc9783..ba19c1c 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -86,18 +86,18 @@
    */
 
   void generate_deserialize_field        (std::ofstream& out,
-                                          t_field*    tfield, 
+                                          t_field*    tfield,
                                           std::string prefix="",
                                           std::string suffix="");
-  
+
   void generate_deserialize_struct       (std::ofstream& out,
                                           t_struct*   tstruct,
                                           std::string prefix="");
-  
+
   void generate_deserialize_container    (std::ofstream& out,
                                           t_type*     ttype,
                                           std::string prefix="");
-  
+
   void generate_deserialize_set_element  (std::ofstream& out,
                                           t_set*      tset,
                                           std::string prefix="");
@@ -144,7 +144,7 @@
   std::string namespace_close(std::string ns);
   std::string type_name(t_type* ttype, bool in_typedef=false, bool arg=false);
   std::string base_type_name(t_base_type::t_base tbase);
-  std::string declare_field(t_field* tfield, bool init=false, bool pointer=false, bool constant=false);
+  std::string declare_field(t_field* tfield, bool init=false, bool pointer=false, bool constant=false, bool reference=false);
   std::string function_signature(t_function* tfunction, std::string prefix="");
   std::string argument_list(t_struct* tstruct);
   std::string type_to_enum(t_type* ttype);
@@ -158,7 +158,7 @@
     ttype = get_true_type(ttype);
 
     return
-      ttype->is_container() || 
+      ttype->is_container() ||
       ttype->is_struct() ||
       ttype->is_xception() ||
       (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));