From: Roger Meier Date: Sat, 28 Apr 2012 11:33:58 +0000 (+0000) Subject: THRIFT-1583 c_glib leaks memory X-Git-Tag: 0.9.1~396 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=c75797d9060e049692c5db1617aa9560aec939c8;p=common%2Fthrift.git THRIFT-1583 c_glib leaks memory THRIFT-1578 C_GLib generated code does not compile THRIFT-1582 Bad includes of nested thrift files in c_glib Patch: José Antonio Santos Minor Modificatons by roger: - thrift prefix for includes - g_object_unref instead of g_clear_object (needs glib>=2.28) git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1331752 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/src/generate/t_c_glib_generator.cc b/compiler/cpp/src/generate/t_c_glib_generator.cc index d22b7232..b088299c 100644 --- a/compiler/cpp/src/generate/t_c_glib_generator.cc +++ b/compiler/cpp/src/generate/t_c_glib_generator.cc @@ -124,6 +124,7 @@ class t_c_glib_generator : public t_oop_generator { string argument_list(t_struct *tstruct); string xception_list(t_struct *tstruct); string declare_field(t_field *tfield, bool init=false, bool pointer=false, bool constant=false, bool reference=false); + void declare_local_variable(ofstream &out, t_type *ttype, string &base_name); /* generation functions */ void generate_const_initializer(string name, t_type *type, t_const_value *value); @@ -140,15 +141,19 @@ class t_c_glib_generator : public t_oop_generator { void generate_serialize_set_element(ofstream &out, t_set *tset, string element, int error_ret); void generate_serialize_list_element(ofstream &out, t_list *tlist, string list, string index, int error_ret); - void generate_deserialize_field(ofstream &out, t_field *tfield, string prefix, string suffix, int error_ret); - void generate_deserialize_struct(ofstream &out, t_struct *tstruct, string prefix, int error_ret); + void generate_deserialize_field(ofstream &out, t_field *tfield, string prefix, string suffix, int error_ret, bool allocate=true); + void generate_deserialize_struct(ofstream &out, t_struct *tstruct, string prefix, int error_ret, bool allocate=true); void generate_deserialize_container(ofstream &out, t_type *ttype, string prefix, int error_ret); void generate_deserialize_map_element(ofstream &out, t_map *tmap, string prefix, int error_ret); void generate_deserialize_set_element(ofstream &out, t_set *tset, string prefix, int error_ret); void generate_deserialize_list_element(ofstream &out, t_list *tlist, string prefix, string index, int error_ret); - string generate_new_hash_from_type(t_type * ttype); + string generate_new_hash_from_type(t_type * key, t_type * value); string generate_new_array_from_type(t_type * ttype); + + string generate_free_func_from_type(t_type * ttype); + string generate_hash_func_from_type(t_type * ttype); + string generate_cmp_func_from_type(t_type * ttype); }; /** @@ -185,7 +190,7 @@ void t_c_glib_generator::init_generator() { f_types_ << "/* base includes */" << endl << "#include " << endl << - "#include " << endl << + "#include " << endl << "#include " << endl; /* include other thrift includes */ @@ -193,7 +198,7 @@ void t_c_glib_generator::init_generator() { for (size_t i = 0; i < includes.size(); ++i) { f_types_ << "/* other thrift includes */" << endl << - "#include \"" << this->nspace_lc << includes[i]->get_name() << + "#include \"" << this->nspace_lc << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl; } f_types_ << endl; @@ -411,7 +416,7 @@ void t_c_glib_generator::generate_service (t_service *tservice) { f_service_ << "#include " << endl << "#include " << endl << - "#include " << endl << + "#include " << endl << "#include \"" << filename << ".h\"" << endl << endl; @@ -650,7 +655,7 @@ string t_c_glib_generator::constant_value(string name, t_type *type, t_const_val t_base_type::t_base tbase = ((t_base_type *) type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: - render << "\"" + value->get_string() + "\""; + render << "g_strdup (\"" + value->get_string() + "\")"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() != 0) ? 1 : 0); @@ -805,6 +810,8 @@ string t_c_glib_generator::declare_field(t_field *tfield, } } else if (type->is_enum()) { result += " = (" + type_name (type) + ") 0"; + } else if (type->is_struct() || type->is_container()) { + result += " = NULL"; } } @@ -876,7 +883,8 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t endl; } else if (type->is_list()) { string list_type = "GPtrArray *"; - string list_initializer = "g_ptr_array_new()"; + // TODO: This initialization should contain a free function for container + string list_initializer = "g_ptr_array_new();"; string list_appender = "g_ptr_array_add"; bool list_variable = false; @@ -885,6 +893,7 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t vector::const_iterator v_iter; ostringstream initializers; + 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) { @@ -897,7 +906,6 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: list_type = "GArray *"; - list_initializer = generate_new_array_from_type (etype); list_appender = "g_array_append_val"; list_variable = true; break; @@ -932,7 +940,7 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t " static " << list_type << " constant = NULL;" << endl << " if (constant == NULL)" << endl << " {" << endl << - " constant = " << list_initializer << ";" << endl << + " constant = " << list_initializer << endl << initializers.str() << endl << " }" << endl << " return constant;" << endl << @@ -961,6 +969,7 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t " static GHashTable *constant = NULL;" << endl << " if (constant == NULL)" << endl << " {" << endl << + // TODO: This initialization should contain a free function for elements " constant = g_hash_table_new (NULL, NULL);" << endl << initializers.str() << endl << " }" << endl << @@ -997,6 +1006,7 @@ void t_c_glib_generator::generate_const_initializer(string name, t_type *type, t " static GHashTable *constant = NULL;" << endl << " if (constant == NULL)" << endl << " {" << endl << + // TODO: This initialization should contain a free function for elements " constant = g_hash_table_new (NULL, NULL);" << endl << initializers.str() << endl << " }" << endl << @@ -1736,37 +1746,23 @@ void t_c_glib_generator::generate_object(t_struct *tstruct) { indent(f_types_impl_) << "object->" << name << " = NULL;" << endl; } else if (t->is_container()) { string name = (*m_iter)->get_name(); - - if (t->is_map() || t->is_set()) { - indent(f_types_impl_) << "object->" << name << " = g_hash_table_new (NULL, NULL);" << endl; + string init_function; + + 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()) { + t_type *etype = ((t_set *) t)->get_elem_type(); + init_function = generate_new_hash_from_type (etype, NULL); } else if (t->is_list()) { t_type *etype = ((t_list *) t)->get_elem_type(); - string init_function = "g_ptr_array_new()"; - - 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_BYTE: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - case t_base_type::TYPE_DOUBLE: - init_function = generate_new_array_from_type (etype); - break; - case t_base_type::TYPE_STRING: - break; - default: - throw "compiler error: no array info for type"; - } - } - - indent(f_types_impl_) << "object->" << name << " = " << - init_function << ";" << endl; + init_function = generate_new_array_from_type (etype); } + indent(f_types_impl_) << "object->" << name << " = " << + init_function << endl; + } /* if not required, initialize the __isset variable */ @@ -1800,8 +1796,14 @@ void t_c_glib_generator::generate_object(t_struct *tstruct) { if (t->is_container()) { string name = (*m_iter)->get_name(); if (t->is_map() || t->is_set()) { - f_types_impl_ << - indent() << "g_hash_table_unref (tobject->" << name << ");" << endl; + f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; + f_types_impl_ << indent() << "{" << endl; + indent_up(); + f_types_impl_ << + indent() << "g_hash_table_destroy (tobject->" << name << ");" << endl; + f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; + indent_down(); + f_types_impl_ << indent() << "}" << endl; } else if (t->is_list()) { t_type *etype = ((t_list *) t)->get_elem_type(); string destructor_function = "g_ptr_array_free"; @@ -1826,10 +1828,39 @@ void t_c_glib_generator::generate_object(t_struct *tstruct) { } } + f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; + f_types_impl_ << indent() << "{" << endl; + indent_up(); f_types_impl_ << indent() << destructor_function << " (tobject->" << name << - ", FALSE);" << endl; + ", TRUE);" << endl; + f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; + indent_down(); + f_types_impl_ << indent() << "}" << endl; } + } 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 << "));" << endl; + // does g_object_unref the trick? + f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; + f_types_impl_ << indent() << "{" << endl; + indent_up(); + f_types_impl_ << + indent() << "g_object_unref(tobject->" << name << ");" << endl; + f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; + indent_down(); + f_types_impl_ << indent() << "}" << endl; + } else if (t->is_string()) { + string name = (*m_iter)->get_name(); + f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; + f_types_impl_ << indent() << "{" << endl; + indent_up(); + f_types_impl_ << + indent() << "g_free (tobject->" << name << ");" << endl; + f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; + indent_down(); + f_types_impl_ << indent() << "}" << endl; } } @@ -2008,7 +2039,7 @@ void t_c_glib_generator::generate_struct_reader(ofstream &out, out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << - indent() << "gchar *name;" << endl << + indent() << "gchar *name = NULL;" << endl << indent() << "ThriftType ftype;" << endl << indent() << "gint16 fid;" << endl << indent() << "guint32 len = 0;" << endl << @@ -2044,6 +2075,7 @@ void t_c_glib_generator::generate_struct_reader(ofstream &out, indent() << "}" << endl << indent() << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << + indent() << "name = NULL;" << endl << endl; // read the struct fields @@ -2062,6 +2094,7 @@ void t_c_glib_generator::generate_struct_reader(ofstream &out, indent() << "}" << endl << indent() << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << + indent() << "name = NULL;" << endl << endl; // check for field STOP marker @@ -2093,7 +2126,7 @@ void t_c_glib_generator::generate_struct_reader(ofstream &out, indent_up(); // generate deserialize field - generate_deserialize_field (out, *f_iter, this_name, "", error_ret); + generate_deserialize_field (out, *f_iter, this_name, "", error_ret, false); indent_down(); out << @@ -2319,9 +2352,11 @@ void t_c_glib_generator::generate_serialize_container(ofstream &out, indent() << "GList *key_list = NULL, *iter = NULL;" << endl << indent() << telem_name << telem_ptr << " elem;" << endl << indent() << "gpointer value;" << endl << + indent() << "THRIFT_UNUSED_VAR (value);" << endl << + endl << indent() << "g_hash_table_foreach ((GHashTable *) " << prefix << ", thrift_hash_table_get_keys, &key_list);" << endl << - indent() << telem_name << telem_ptr << "keys[g_list_length (key_list)];" << endl << + indent() << telem_name << telem_ptr << " keys[g_list_length (key_list)];" << endl << indent() << "int i=0, key_count = g_list_length (key_list);" << endl << indent() << "for (iter = g_list_first (key_list); iter; iter = iter->next)" << endl << indent() << "{" << endl << @@ -2347,17 +2382,19 @@ void t_c_glib_generator::generate_serialize_container(ofstream &out, indent() << "xfer += ret;" << endl; } else if (ttype->is_list()) { string length = prefix + "->len"; + string i = tmp("i"); out << indent() << "if ((ret = thrift_protocol_write_list_begin (protocol, " << type_to_enum (((t_list *) ttype)->get_elem_type()) << ", (gint32) " << length << ", error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << - indent() << "guint i;" << endl << - indent() << "for (i=0; i<" << length << "; i++)" << endl; + indent() << "guint " << i << ";" << endl << + indent() << "for ("<< i << "=0; " << i << "<" << length << "; " << i << + "++)" << endl; scope_up(out); - generate_serialize_list_element (out, (t_list *) ttype, prefix, "i", error_ret); + generate_serialize_list_element (out, (t_list *) ttype, prefix, i, error_ret); scope_down(out); out << @@ -2397,6 +2434,7 @@ void t_c_glib_generator::generate_serialize_list_element(ofstream &out, t_type *ttype = tlist->get_elem_type(); // cast to non-const + string cast = ""; string name = "g_ptr_array_index ((GPtrArray *) " + list + ", " + index + ")"; @@ -2425,13 +2463,40 @@ void t_c_glib_generator::generate_serialize_list_element(ofstream &out, name = "g_array_index (" + list + ", gdouble, " + index + ")"; break; case t_base_type::TYPE_STRING: + cast = "(gchar*)"; break; default: throw "compiler error: no array info for type"; } + } else if (ttype->is_map() || ttype->is_set()) { + cast = "(GHashTable*)"; + } else if (ttype->is_list()) { + t_type *base = ((t_list *)ttype)->get_elem_type(); + if (base->is_base_type()) { + switch (((t_base_type *) base)->get_base()) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot determine array type"; + break; + case t_base_type::TYPE_BOOL: + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + case t_base_type::TYPE_DOUBLE: + cast = "(GArray*)"; + break; + case t_base_type::TYPE_STRING: + cast = "(GPtrArray*)"; + break; + default: + throw "Compiler error: no array info for type"; + } + } else { + cast = "(GPtrArray*)"; + } } - t_field efield (ttype, name); + t_field efield (ttype, "(" + cast + name + ")"); generate_serialize_field (out, &efield, "", "", error_ret); } @@ -2440,7 +2505,8 @@ void t_c_glib_generator::generate_deserialize_field(ofstream &out, t_field *tfield, string prefix, string suffix, - int error_ret) { + int error_ret, + bool allocate) { t_type *type = get_true_type (tfield->get_type()); if (type->is_void()) { @@ -2451,12 +2517,21 @@ void t_c_glib_generator::generate_deserialize_field(ofstream &out, string name = prefix + tfield->get_name() + suffix; if (type->is_struct() || type->is_xception()) { - generate_deserialize_struct (out, (t_struct *) type, name, error_ret); + generate_deserialize_struct (out, (t_struct *) type, name, error_ret, allocate); } else if (type->is_container()) { generate_deserialize_container (out, type, name, error_ret); } else if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type *) type)->get_base(); - + if (tbase == t_base_type::TYPE_STRING) { + indent(out) << "if (" << name << " != NULL)" << endl << + indent() << "{" << endl; + indent_up(); + indent(out) << "g_free(" << name << ");" << endl << + indent() << name << " = NULL;" << endl; + indent_down(); + indent(out) << "}" << endl << + endl; + } indent(out) << "if ((ret = thrift_protocol_read_"; switch (tbase) { @@ -2529,12 +2604,39 @@ void t_c_glib_generator::generate_deserialize_field(ofstream &out, void t_c_glib_generator::generate_deserialize_struct(ofstream &out, t_struct *tstruct, string prefix, - int error_ret) { + int error_ret, + bool allocate) { string name_uc = to_upper_case(initial_caps_to_underscores(tstruct->get_name())); + if (tstruct->is_xception()) { + out << + indent() << "/* This struct is an exception */" << endl; + allocate = true; + } + + if (allocate) { + out << + indent() << "if ( " << prefix << " != NULL)" << endl << + indent() << "{" << endl; + indent_up(); + out << + indent() << "g_object_unref (" << prefix << ");" << endl; + indent_down(); + out << + indent() << "}" << endl << + indent() << prefix << " = g_object_new (" << this->nspace_uc << "TYPE_" << name_uc << ", NULL);" << endl; + } out << - indent() << prefix << " = g_object_new (" << this->nspace_uc << "TYPE_" << name_uc << ", NULL);" << endl << indent() << "if ((ret = thrift_struct_read (THRIFT_STRUCT (" << prefix << "), protocol, error)) < 0)" << endl << - indent() << " return " << error_ret << ";" << endl << + indent() << "{" << endl; + indent_up(); + if (allocate) { + indent(out) << "g_object_unref (" << prefix << ");" << endl; + } + out << + indent() << "return " << error_ret << ";" << endl; + indent_down(); + out << + indent() << "}" << endl << indent() << "xfer += ret;" << endl; } @@ -2624,35 +2726,36 @@ void t_c_glib_generator::generate_deserialize_container (ofstream &out, t_type * scope_down(out); } +void t_c_glib_generator::declare_local_variable(ofstream &out, t_type *ttype, string &name) { + string tname = type_name (ttype); + string ptr = ttype->is_string() || !ttype->is_base_type() ? "" : "*"; + + if (ttype->is_map()) { + out << + indent() << tname << ptr << " " << name << " = g_hash_table_new (NULL, NULL);" << endl; + } else if (ttype->is_enum()) { + out << + indent() << tname << ptr << " " << name << ";" << endl; + } else { + out << + indent() << tname << ptr << " " << name << (ptr != "" ? " = g_new (" + tname + ", 1)" : " = NULL") << ";" << endl; + } +} + + void t_c_glib_generator::generate_deserialize_map_element(ofstream &out, t_map *tmap, string prefix, int error_ret) { t_type *tkey = tmap->get_key_type(); t_type *tval = tmap->get_val_type(); - string tkey_name = type_name (tkey); - string tval_name = type_name (tval); string tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*"; string tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*"; - string keyname = tmp("key"); string valname = tmp("val"); - if (tkey->is_map()) { - out << - indent() << tkey_name << tkey_ptr << " " << keyname << " = g_hash_table_new (NULL, NULL);" << endl; - } else { - out << - indent() << tkey_name << tkey_ptr << " " << keyname << (tkey_ptr != "" ? " = g_new (" + tkey_name + ", 1)" : "") << ";" << endl; - } - - if (tval->is_map()) { - out << - indent() << tval_name << tval_ptr << " " << valname << " = g_hash_table_new (NULL, NULL);" << endl; - } else { - out << - indent() << tval_name << tval_ptr << " " << valname << (tval_ptr != "" ? " = g_new (" + tval_name + ", 1)" : "") << ";" << endl; - } + declare_local_variable(out, tkey, keyname); + declare_local_variable(out, tval, valname); // deserialize the fields of the map element t_field fkey (tkey, tkey_ptr + keyname); @@ -2660,10 +2763,8 @@ void t_c_glib_generator::generate_deserialize_map_element(ofstream &out, t_field fval (tval, tval_ptr + valname); generate_deserialize_field (out, &fval, "", "", error_ret); - // insert into the hashtable. if the field is not a pointer, then use - // the address of the object. indent(out) << - "g_hash_table_insert ((GHashTable *)" << prefix << ", (gpointer) " << (tkey_ptr != "" ? "" : "&") << keyname << ", (gpointer) " << (tval_ptr != "" ? "" : "&") << valname << ");" << endl; + "g_hash_table_insert ((GHashTable *)" << prefix << ", (gpointer) " << keyname << ", (gpointer) " << valname << ");" << endl; } void t_c_glib_generator::generate_deserialize_set_element(ofstream &out, @@ -2671,22 +2772,17 @@ void t_c_glib_generator::generate_deserialize_set_element(ofstream &out, string prefix, int error_ret) { t_type *telem = tset->get_elem_type(); - string telem_name = type_name (telem); + string elem = tmp ("_elem"); string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*"; - if (telem->is_map()) { - out << - indent() << telem_name << telem_ptr << " elem = g_hash_table_new (NULL, NULL);" << endl; - } else { - out << - indent() << telem_name << telem_ptr << " elem" << (telem_ptr != "" ? " = g_new (" + telem_name + ", 1)" : "") << ";" << endl; - } + declare_local_variable(out, telem, elem); - t_field felem (telem, telem_ptr + "elem"); + t_field felem (telem, telem_ptr + elem); generate_deserialize_field (out, &felem, "", "", error_ret); indent(out) << - "g_hash_table_insert ((GHashTable *) " << prefix << ", (gpointer) elem, (gpointer) 1);" << endl; + "g_hash_table_insert ((GHashTable *) " << prefix << ", (gpointer) " << + elem << ", (gpointer) 1);" << endl; } void t_c_glib_generator::generate_deserialize_list_element(ofstream &out, @@ -2695,15 +2791,17 @@ void t_c_glib_generator::generate_deserialize_list_element(ofstream &out, string index, int error_ret) { (void) index; + t_type *ttype = tlist->get_elem_type(); string elem = tmp ("_elem"); - t_field felem (tlist->get_elem_type(), elem); + string telem_ptr = ttype->is_string() || !ttype->is_base_type() ? "" : "*"; + + declare_local_variable(out, ttype, elem); - indent(out) << declare_field (&felem, true) << endl; + t_field felem (ttype, telem_ptr + elem); generate_deserialize_field (out, &felem, "", "", error_ret); indent(out); - t_type *ttype = tlist->get_elem_type(); if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type *) ttype)->get_base(); switch (tbase) { @@ -2727,7 +2825,10 @@ void t_c_glib_generator::generate_deserialize_list_element(ofstream &out, out << "g_ptr_array_add (" << prefix << ", " << elem << ");" << endl; } -string t_c_glib_generator::generate_new_hash_from_type (t_type * ttype) { +string t_c_glib_generator::generate_free_func_from_type (t_type * ttype) { + if (ttype == NULL) + return "NULL"; + if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type *) ttype)->get_base(); switch (tbase) { @@ -2735,24 +2836,135 @@ string t_c_glib_generator::generate_new_hash_from_type (t_type * ttype) { throw "compiler error: cannot determine hash type"; break; case t_base_type::TYPE_BOOL: - return "g_hash_table_new (thrift_gboolean_hash, thrift_gboolean_equal);"; case t_base_type::TYPE_BYTE: - return "g_hash_table_new (thrift_gint8_hash, thrift_gint8_equal);"; case t_base_type::TYPE_I16: - return "g_hash_table_new (thrift_gint16_hash, thrift_gint16_equal);"; case t_base_type::TYPE_I32: - return "g_hash_table_new (thrift_gint32_hash, thrift_gint32_equal);"; case t_base_type::TYPE_I64: - return "g_hash_table_new (thrift_gint64_hash, thrift_gint64_equal);"; case t_base_type::TYPE_DOUBLE: - return "g_hash_table_new (thrift_gdouble_hash, thrift_gdouble_equal);"; + return "NULL"; case t_base_type::TYPE_STRING: - return "g_hash_table_new (g_str_hash, g_str_equal);"; + return "g_free"; default: throw "compiler error: no hash table info for type"; } + } else if (ttype->is_enum()) { + return "NULL"; + } else if (ttype->is_map() || ttype->is_set()) { + return "(GDestroyNotify) g_hash_table_destroy"; + } else if (ttype->is_struct()) { + return "g_object_unref"; + } else if (ttype->is_list()) { + t_type *etype = ((t_list *) ttype)->get_elem_type(); + 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"; + break; + case t_base_type::TYPE_BOOL: + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + case t_base_type::TYPE_DOUBLE: + return "(GDestroyNotify) g_array_unref"; + case t_base_type::TYPE_STRING: + return "(GDestroyNotify) g_ptr_array_unref"; + default: + throw "compiler error: no array info for type"; + } + } else if (etype->is_container() || etype->is_struct()) { + return "(GDestroyNotify) g_ptr_array_unref";; + } else if (etype->is_enum()) { + return "(GDestroyNotify) g_array_unref"; + } + printf("Type not expected inside the array: %s\n", etype->get_name().c_str()); + throw "Type not expected inside array" ; + } else if (ttype->is_typedef()) { + return generate_free_func_from_type(((t_typedef *) ttype)->get_type()); } - return "g_hash_table_new (NULL, NULL);"; + printf("Type not expected: %s\n", ttype->get_name().c_str()); + throw "Type not expected"; +} + +string t_c_glib_generator::generate_hash_func_from_type (t_type * ttype) { + if (ttype == NULL) + return "NULL"; + + if (ttype->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type *) ttype)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot determine hash type"; + break; + case t_base_type::TYPE_BOOL: + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + return "g_int_hash"; + case t_base_type::TYPE_I64: + return "g_int64_hash"; + case t_base_type::TYPE_DOUBLE: + return "g_double_hash"; + case t_base_type::TYPE_STRING: + return "g_str_hash"; + default: + throw "compiler error: no hash table info for type"; + } + } else if (ttype->is_enum()) { + return "g_direct_hash"; + } else if (ttype->is_container() || ttype->is_struct()) { + return "g_direct_hash"; + } else if (ttype->is_typedef()) { + return generate_hash_func_from_type(((t_typedef *) ttype)->get_type()); + } + printf("Type not expected: %s\n", ttype->get_name().c_str()); + throw "Type not expected"; +} + +string t_c_glib_generator::generate_cmp_func_from_type (t_type * ttype) { + if (ttype == NULL) + return "NULL"; + + if (ttype->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type *) ttype)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot determine hash type"; + break; + case t_base_type::TYPE_BOOL: + case t_base_type::TYPE_BYTE: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + return "g_int_equal"; + case t_base_type::TYPE_I64: + return "g_int64_equal"; + case t_base_type::TYPE_DOUBLE: + return "g_double_equal"; + case t_base_type::TYPE_STRING: + return "g_str_equal"; + default: + throw "compiler error: no hash table info for type"; + } + } else if (ttype->is_enum()) { + return "NULL"; + } else if (ttype->is_container() || ttype->is_struct()) { + return "g_direct_equal"; + } else if (ttype->is_typedef()) { + return generate_cmp_func_from_type(((t_typedef *) ttype)->get_type()); + } + printf("Type not expected: %s\n", ttype->get_name().c_str()); + throw "Type not expected"; +} + +string t_c_glib_generator::generate_new_hash_from_type (t_type * key, t_type *value) { + string hash_func = generate_hash_func_from_type(key); + string cmp_func = generate_cmp_func_from_type(key); + string key_free_func = generate_free_func_from_type(key); + string value_free_func = generate_free_func_from_type(value); + + return "g_hash_table_new_full (" + hash_func + ", " + cmp_func + ", " + + key_free_func + ", " + value_free_func + ");"; } string t_c_glib_generator::generate_new_array_from_type(t_type * ttype) { @@ -2775,11 +2987,17 @@ string t_c_glib_generator::generate_new_array_from_type(t_type * ttype) { case t_base_type::TYPE_DOUBLE: return "g_array_new (0, 1, sizeof (gdouble));"; case t_base_type::TYPE_STRING: - return "g_ptr_array_new();"; + return "g_ptr_array_new_with_free_func (g_free);"; default: throw "compiler error: no array info for type"; } + } else if (ttype->is_enum()) { + return "g_array_new (0, 1, sizeof (gint32));"; + } else { + string free_func = generate_free_func_from_type(ttype); + return "g_ptr_array_new_with_free_func (" + free_func + ");"; } + return "g_ptr_array_new();"; } diff --git a/lib/c_glib/test/testbinaryprotocol.c b/lib/c_glib/test/testbinaryprotocol.c index 7545fb96..a07118f3 100644 --- a/lib/c_glib/test/testbinaryprotocol.c +++ b/lib/c_glib/test/testbinaryprotocol.c @@ -71,7 +71,7 @@ my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, #define thrift_transport_read my_thrift_transport_read #define thrift_transport_write my_thrift_transport_write -#include "../src/protocol/thrift_binary_protocol.c" +#include "../src/thrift/protocol/thrift_binary_protocol.c" #undef thrift_transport_read #undef thrift_transport_write diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/testbufferedtransport.c index 64dbdd13..d04343e9 100644 --- a/lib/c_glib/test/testbufferedtransport.c +++ b/lib/c_glib/test/testbufferedtransport.c @@ -27,7 +27,7 @@ #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } -#include "../src/transport/thrift_buffered_transport.c" +#include "../src/thrift/transport/thrift_buffered_transport.c" static const char TEST_ADDRESS[] = "localhost"; static const short TEST_PORT = 64444; diff --git a/lib/c_glib/test/testdebugproto.c b/lib/c_glib/test/testdebugproto.c index f0654f17..689e001a 100644 --- a/lib/c_glib/test/testdebugproto.c +++ b/lib/c_glib/test/testdebugproto.c @@ -32,6 +32,8 @@ test_debug_proto(void) TTestOneOfEach *ooe = NULL; TTestNesting *n = NULL; TTestHolyMoley *hm = NULL; + gchar *random = g_strdup("random string"); + gchar *nothing = g_strdup("nothing"); ooe = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); ooe->im_true = TRUE; @@ -41,38 +43,37 @@ test_debug_proto(void) ooe->integer32 = 1<<24; ooe->integer64 = (guint64) 6000 * 1000 * 1000; ooe->double_precision = M_PI; - ooe->some_characters = "Debug THIS!"; - ooe->zomg_unicode = "\xd7\n\a\t"; + ooe->some_characters = g_strdup("Debug THIS!"); + ooe->zomg_unicode = g_strdup("\xd7\n\a\t"); n = g_object_new (T_TEST_TYPE_NESTING, NULL); + if (n->my_ooe != NULL) + g_object_unref(n->my_ooe); + n->my_ooe = ooe; n->my_ooe->integer16 = 16; n->my_ooe->integer32 = 32; n->my_ooe->integer64 = 64; n->my_ooe->double_precision = (sqrt(5.0) + 1) / 2; - n->my_ooe->some_characters = ":R (me going \"rrrr\")"; - n->my_ooe->zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20"; + n->my_ooe->some_characters = g_strdup(":R (me going \"rrrr\")"); + n->my_ooe->zomg_unicode = g_strdup("\xd3\x80\xe2\x85\xae\xce\x9d\x20"); n->my_bonk->type = 31337; - n->my_bonk->message = "I am a bonk... xor!"; + n->my_bonk->message = g_strdup("I am a bonk... xor!"); hm = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); g_ptr_array_add (hm->big, ooe); - g_ptr_array_add (hm->big, n->my_ooe); + g_ptr_array_add (hm->big, g_object_ref(n->my_ooe)); ((TTestOneOfEach *) g_ptr_array_index (hm->big, 0))->a_bite = 0x22; ((TTestOneOfEach *) g_ptr_array_index (hm->big, 1))->a_bite = 0x33; - g_hash_table_insert (hm->contain, "random string", "random string"); + g_hash_table_insert (hm->contain, random, random); TTestBonk *bonk = NULL; bonk = g_object_new (T_TEST_TYPE_BONK, NULL); - GPtrArray *bonks = g_ptr_array_new (); + GPtrArray *bonks = g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_add (bonks, bonk); - g_hash_table_insert (hm->bonks, "nothing", bonks); + g_hash_table_insert (hm->bonks, nothing, bonks); - g_ptr_array_free (bonks, TRUE); - g_object_unref (bonk); - g_object_unref (ooe); - g_object_unref (n); g_object_unref (hm); return 0; diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testframedtransport.c index 3587711a..dcaabda7 100644 --- a/lib/c_glib/test/testframedtransport.c +++ b/lib/c_glib/test/testframedtransport.c @@ -27,7 +27,7 @@ #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } -#include "../src/transport/thrift_framed_transport.c" +#include "../src/thrift/transport/thrift_framed_transport.c" static const char TEST_ADDRESS[] = "localhost"; static const short TEST_PORT = 64444; @@ -150,7 +150,7 @@ thrift_server (const int port) int bytes = 0; ThriftServerTransport *transport = NULL; ThriftTransport *client = NULL; - guchar buf[10]; /* a buffer */ + guchar buf[12]; /* a buffer */ guchar match[10] = TEST_DATA; ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, diff --git a/lib/c_glib/test/testmemorybuffer.c b/lib/c_glib/test/testmemorybuffer.c index b716f5fe..96981858 100644 --- a/lib/c_glib/test/testmemorybuffer.c +++ b/lib/c_glib/test/testmemorybuffer.c @@ -27,7 +27,7 @@ #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } -#include "../src/transport/thrift_memory_buffer.c" +#include "../src/thrift/transport/thrift_memory_buffer.c" /* test object creation and destruction */ static void diff --git a/lib/c_glib/test/testoptionalrequired.c b/lib/c_glib/test/testoptionalrequired.c index fdd4c1af..4f6fe156 100644 --- a/lib/c_glib/test/testoptionalrequired.c +++ b/lib/c_glib/test/testoptionalrequired.c @@ -20,7 +20,7 @@ #include #include -#include "thrift_struct.h" +#include #include #include #include @@ -55,8 +55,10 @@ test_old_school1 (void) o->im_int = 10; o->im_str = g_strdup ("test"); o->im_big = g_ptr_array_new (); - g_ptr_array_free (o->im_big, FALSE); + g_ptr_array_free (o->im_big, TRUE); + o->im_big = NULL; g_free (o->im_str); + o->im_str = NULL; g_object_unref (o); } diff --git a/lib/c_glib/test/teststruct.c b/lib/c_glib/test/teststruct.c index ec543be0..50b10dcb 100644 --- a/lib/c_glib/test/teststruct.c +++ b/lib/c_glib/test/teststruct.c @@ -20,7 +20,7 @@ #include #include -#include "../src/thrift_struct.c" +#include "../src/thrift/thrift_struct.c" /* tests to ensure we can extend a ThriftStruct */ diff --git a/lib/c_glib/test/testthrifttestclient.cpp b/lib/c_glib/test/testthrifttestclient.cpp index fb6af0b0..5d40331e 100644 --- a/lib/c_glib/test/testthrifttestclient.cpp +++ b/lib/c_glib/test/testthrifttestclient.cpp @@ -396,23 +396,25 @@ test_thrift_client (void) xtruct_out->__isset_i64_thing = TRUE; xtruct_out->string_thing = g_strdup ("abc123"); xtruct_out->__isset_string_thing = TRUE; + xtruct_in = (TTestXtruct *) g_object_new(T_TEST_TYPE_XTRUCT, NULL); assert (t_test_thrift_test_client_test_struct (iface, &xtruct_in, xtruct_out, &error) == TRUE); assert (error == NULL); xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, NULL); xtruct2_out->byte_thing = 1; xtruct2_out->__isset_byte_thing = TRUE; + if (xtruct2_out->struct_thing != NULL) + g_object_unref(xtruct2_out->struct_thing); xtruct2_out->struct_thing = xtruct_out; xtruct2_out->__isset_struct_thing = TRUE; xtruct2_out->i32_thing = 123; xtruct2_out->__isset_i32_thing = TRUE; + xtruct2_in = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, NULL); assert (t_test_thrift_test_client_test_nest (iface, &xtruct2_in, xtruct2_out, &error) == TRUE); assert (error == NULL); g_object_unref (xtruct2_out); g_object_unref (xtruct2_in); - g_free (xtruct_out->string_thing); - g_object_unref (xtruct_out); g_object_unref (xtruct_in); map_out = g_hash_table_new (NULL, NULL); @@ -490,7 +492,6 @@ test_thrift_client (void) xtruct2->string_thing = g_strdup ("abc123"); xtruct2->__isset_string_thing = TRUE; - insanity_out->xtructs = g_ptr_array_new (); insanity_in = g_hash_table_new (NULL, NULL); g_ptr_array_add (insanity_out->xtructs, xtruct1); g_ptr_array_add (insanity_out->xtructs, xtruct2); @@ -498,25 +499,24 @@ test_thrift_client (void) g_hash_table_unref (insanity_in); g_ptr_array_free (insanity_out->xtructs, TRUE); - g_free (xtruct1->string_thing); - g_free (xtruct2->string_thing); - g_object_unref (xtruct1); - g_object_unref (xtruct2); multi_map_out = g_hash_table_new (NULL, NULL); string = g_strdup ("abc123"); g_hash_table_insert (multi_map_out, &i16, string); + multi_in = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL); assert (t_test_thrift_test_client_test_multi (iface, &multi_in, byte, i32, i64, multi_map_out, enum_out, user_id_out, &error) == TRUE); assert (multi_in->i32_thing == i32); assert (multi_in->i64_thing == i64); g_object_unref (multi_in); g_hash_table_unref (multi_map_out); - g_free (string); + g_free (string); assert (t_test_thrift_test_client_test_exception (iface, "Xception", &xception, &error) == FALSE); assert (xception->errorCode == 1001); g_error_free (error); error = NULL; + g_object_unref (xception); + xception = NULL; assert (t_test_thrift_test_client_test_exception (iface, "ApplicationException", &xception, &error) == FALSE); g_error_free (error); @@ -527,23 +527,33 @@ test_thrift_client (void) assert (t_test_thrift_test_client_test_exception (iface, "Test", &xception, &error) == TRUE); assert (error == NULL); + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", NULL, &xception, &xception2, &error) == FALSE); assert (xception->errorCode == 1001); + assert (xception2 == NULL); g_error_free (error); error = NULL; g_object_unref (xception); + g_object_unref (multi_in); xception = NULL; - xception2 = NULL; + multi_in = NULL; + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", NULL, &xception, &xception2, &error) == FALSE); assert (xception2->errorCode == 2002); + assert (xception == NULL); g_error_free (error); error = NULL; g_object_unref (xception2); + g_object_unref (multi_in); xception2 = NULL; + multi_in = NULL; + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, NULL , NULL, &xception, &xception2, &error) == TRUE); assert (error == NULL); + g_object_unref(multi_in); + multi_in = NULL; assert (t_test_thrift_test_client_test_oneway (iface, 1, &error) == TRUE); assert (error == NULL); diff --git a/lib/c_glib/test/testtransportsocket.c b/lib/c_glib/test/testtransportsocket.c index cc21d581..41e0ea4a 100644 --- a/lib/c_glib/test/testtransportsocket.c +++ b/lib/c_glib/test/testtransportsocket.c @@ -63,7 +63,7 @@ my_send(int socket, const void *buffer, size_t length, int flags) #define socket my_socket #define recv my_recv #define send my_send -#include "../src/transport/thrift_socket.c" +#include "../src/thrift/transport/thrift_socket.c" #undef socket #undef recv #undef send