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 d22b723..b088299 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 @@
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 @@
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 @@
f_types_ <<
"/* base includes */" << endl <<
"#include <glib-object.h>" << endl <<
- "#include <thrift_struct.h>" << endl <<
+ "#include <thrift/thrift_struct.h>" << endl <<
"#include <thrift/protocol/thrift_protocol.h>" << endl;
/* include other thrift includes */
@@ -193,7 +198,7 @@
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 @@
f_service_ <<
"#include <string.h>" << endl <<
"#include <thrift/thrift.h>" << endl <<
- "#include <thrift_application_exception.h>" << endl <<
+ "#include <thrift/thrift_application_exception.h>" << endl <<
"#include \"" << filename << ".h\"" << endl <<
endl;
@@ -650,7 +655,7 @@
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 @@
}
} else if (type->is_enum()) {
result += " = (" + type_name (type) + ") 0";
+ } else if (type->is_struct() || type->is_container()) {
+ result += " = NULL";
}
}
@@ -876,7 +883,8 @@
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 @@
vector<t_const_value*>::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 @@
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 @@
" 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 @@
" 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 @@
" 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 @@
indent(f_types_impl_) << "object->" << name << " = NULL;" << endl;
} else if (t->is_container()) {
string name = (*m_iter)->get_name();
+ string init_function;
- if (t->is_map() || t->is_set()) {
- indent(f_types_impl_) << "object->" << name << " = g_hash_table_new (NULL, NULL);" << endl;
+ 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 @@
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 @@
}
}
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
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 @@
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 @@
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 @@
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() ? "" : "*";
- indent(out) << declare_field (&felem, true) << endl;
+ declare_local_variable(out, ttype, elem);
+
+ 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 @@
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 @@
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 @@
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 7545fb9..a07118f 100644
--- a/lib/c_glib/test/testbinaryprotocol.c
+++ b/lib/c_glib/test/testbinaryprotocol.c
@@ -71,7 +71,7 @@
#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 64dbdd1..d04343e 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 f0654f1..689e001 100644
--- a/lib/c_glib/test/testdebugproto.c
+++ b/lib/c_glib/test/testdebugproto.c
@@ -32,6 +32,8 @@
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 @@
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 3587711..dcaabda 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 @@
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 b716f5f..9698185 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 fdd4c1a..4f6fe15 100644
--- a/lib/c_glib/test/testoptionalrequired.c
+++ b/lib/c_glib/test/testoptionalrequired.c
@@ -20,7 +20,7 @@
#include <assert.h>
#include <glib.h>
-#include "thrift_struct.h"
+#include <thrift/thrift_struct.h>
#include <thrift/protocol/thrift_protocol.h>
#include <thrift/protocol/thrift_binary_protocol.h>
#include <thrift/transport/thrift_memory_buffer.h>
@@ -55,8 +55,10 @@
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 ec543be..50b10dc 100644
--- a/lib/c_glib/test/teststruct.c
+++ b/lib/c_glib/test/teststruct.c
@@ -20,7 +20,7 @@
#include <assert.h>
#include <glib-object.h>
-#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 fb6af0b..5d40331 100644
--- a/lib/c_glib/test/testthrifttestclient.cpp
+++ b/lib/c_glib/test/testthrifttestclient.cpp
@@ -396,23 +396,25 @@
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 @@
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 @@
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 @@
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 cc21d58..41e0ea4 100644
--- a/lib/c_glib/test/testtransportsocket.c
+++ b/lib/c_glib/test/testtransportsocket.c
@@ -63,7 +63,7 @@
#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