Switch to storing string form of error quarks

Instead of storing the name of the function to call to get the
error quark, store the string form of the error quark, which
we derive from the introspection binary during scanning.

Update EnumBlob and GIEnumInfo to include the new information.

This will allow determining a back-mapping from error quark
to error domain without having to dlsym() and call all the
known error quark functions.

Based on earlier patches from Owen Taylor and Maxim Ermilov.

https://bugzilla.gnome.org/show_bug.cgi?id=602516
This commit is contained in:
Dan Winship 2011-05-19 16:21:13 -04:00 committed by Johan Dahlin
parent 6ee82c14e8
commit 215d83ebb0
8 changed files with 104 additions and 17 deletions

57
gdump.c
View File

@ -70,6 +70,7 @@ goutput_write (GOutputStream *out, const char *str)
}
typedef GType (*GetTypeFunc)(void);
typedef GQuark (*ErrorQuarkFunc)(void);
static GType
invoke_get_type (GModule *self, const char *symbol, GError **error)
@ -97,6 +98,23 @@ invoke_get_type (GModule *self, const char *symbol, GError **error)
return ret;
}
static GQuark
invoke_error_quark (GModule *self, const char *symbol, GError **error)
{
ErrorQuarkFunc sym;
if (!g_module_symbol (self, symbol, (void**)&sym))
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to find symbol '%s'", symbol);
return G_TYPE_INVALID;
}
return sym ();
}
static void
dump_properties (GType type, GOutputStream *out)
{
@ -365,6 +383,13 @@ dump_type (GType type, const char *symbol, GOutputStream *out)
}
}
static void
dump_error_quark (GQuark quark, const char *symbol, GOutputStream *out)
{
escaped_printf (out, " <error-quark function=\"%s\" domain=\"%s\"/>\n",
symbol, g_quark_to_string (quark));
}
/**
* g_irepository_dump:
* @arg: Comma-separated pair of input and output filenames
@ -437,7 +462,7 @@ g_irepository_dump (const char *arg, GError **error)
{
gsize len;
char *line = g_data_input_stream_read_line (in, &len, NULL, NULL);
GType type;
const char *function;
if (line == NULL || *line == '\0')
{
@ -446,10 +471,18 @@ g_irepository_dump (const char *arg, GError **error)
}
g_strchomp (line);
type = invoke_get_type (self, line, error);
if (strncmp (line, "get-type:", strlen ("get-type:")) == 0)
{
GType type;
function = line + strlen ("get-type:");
type = invoke_get_type (self, function, error);
if (type == G_TYPE_INVALID)
{
g_printerr ("Invalid GType function: '%s'\n", function);
caught_error = TRUE;
g_free (line);
break;
@ -459,7 +492,25 @@ g_irepository_dump (const char *arg, GError **error)
goto next;
g_hash_table_insert (output_types, (gpointer) type, (gpointer) type);
dump_type (type, line, G_OUTPUT_STREAM (output));
dump_type (type, function, G_OUTPUT_STREAM (output));
}
else if (strncmp (line, "error-quark:", strlen ("error-quark:")) == 0)
{
GQuark quark;
function = line + strlen ("error-quark:");
quark = invoke_error_quark (self, function, error);
if (quark == 0)
{
g_printerr ("Invalid error quark function: '%s'\n", function);
caught_error = TRUE;
g_free (line);
break;
}
dump_error_quark (quark, function, G_OUTPUT_STREAM (output));
}
next:
g_free (line);

View File

@ -66,6 +66,23 @@ g_enum_info_get_n_values (GIEnumInfo *info)
return blob->n_values;
}
const gchar *
g_enum_info_get_error_domain (GIEnumInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
EnumBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_ENUM_INFO (info), 0);
blob = (EnumBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->error_domain)
return g_typelib_get_string (rinfo->typelib, blob->error_domain);
else
return NULL;
}
/**
* g_enum_info_get_value:
* @info: a #GIEnumInfo

View File

@ -41,6 +41,7 @@ gint g_enum_info_get_n_values (GIEnumInfo *info);
GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
gint n);
GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info);
const gchar * g_enum_info_get_error_domain (GIEnumInfo *info);
gint64 g_value_info_get_value (GIValueInfo *info);

View File

@ -328,6 +328,7 @@ _g_ir_node_free (GIrNode *node)
g_free (node->name);
g_free (enum_->gtype_name);
g_free (enum_->gtype_init);
g_free (enum_->error_domain);
for (l = enum_->values; l; l = l->next)
_g_ir_node_free ((GIrNode *)l->data);
@ -712,6 +713,8 @@ _g_ir_node_get_full_size_internal (GIrNode *parent,
size += ALIGN_VALUE (strlen (enum_->gtype_name) + 1, 4);
size += ALIGN_VALUE (strlen (enum_->gtype_init) + 1, 4);
}
if (enum_->error_domain)
size += ALIGN_VALUE (strlen (enum_->error_domain) + 1, 4);
for (l = enum_->values; l; l = l->next)
size += _g_ir_node_get_full_size_internal (node, (GIrNode *)l->data);
@ -2021,6 +2024,10 @@ _g_ir_node_build_typelib (GIrNode *node,
blob->gtype_name = 0;
blob->gtype_init = 0;
}
if (enum_->error_domain)
blob->error_domain = _g_ir_write_string (enum_->error_domain, strings, data, offset2);
else
blob->error_domain = 0;
blob->n_values = 0;
blob->reserved2 = 0;

View File

@ -285,6 +285,7 @@ struct _GIrNodeEnum
gchar *gtype_name;
gchar *gtype_init;
gchar *error_domain;
GList *values;
};

View File

@ -1332,6 +1332,7 @@ start_enum (GMarkupParseContext *context,
const gchar *typename;
const gchar *typeinit;
const gchar *deprecated;
const gchar *error_domain;
GIrNodeEnum *enum_;
if (!((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
@ -1344,6 +1345,7 @@ start_enum (GMarkupParseContext *context,
name = find_attribute ("name", attribute_names, attribute_values);
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
error_domain = find_attribute ("glib:error-domain", attribute_names, attribute_values);
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
if (name == NULL)
@ -1361,6 +1363,8 @@ start_enum (GMarkupParseContext *context,
((GIrNode *)enum_)->name = g_strdup (name);
enum_->gtype_name = g_strdup (typename);
enum_->gtype_init = g_strdup (typeinit);
enum_->error_domain = g_strdup (error_domain);
if (deprecated)
enum_->deprecated = TRUE;
else

View File

@ -805,6 +805,7 @@ write_enum_info (const gchar *namespace,
const gchar *name;
const gchar *type_name;
const gchar *type_init;
const gchar *error_domain;
gboolean deprecated;
gint i;
@ -813,6 +814,7 @@ write_enum_info (const gchar *namespace,
type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
error_domain = g_enum_info_get_error_domain (info);
if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
xml_start_element (file, "enumeration");
@ -822,6 +824,8 @@ write_enum_info (const gchar *namespace,
if (type_init)
xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
if (error_domain)
xml_printf (file, " glib:error-domain=\"%s\"", error_domain);
if (deprecated)
xml_printf (file, " deprecated=\"1\"");

View File

@ -798,6 +798,8 @@ typedef struct {
* (will be a signed or unsigned integral type)
* @gtype_name: String name of the associated #GType
* @gtype_init: String naming the symbol which gets the runtime #GType
* @error_domain: String naming the #GError domain this enum is
* associated with
* @n_values: The lengths of the values arrays.
* @values: Describes the enum values.
*/
@ -817,7 +819,7 @@ typedef struct {
guint16 n_values;
guint16 reserved2;
guint32 reserved3;
guint32 error_domain;
ValueBlob values[];
} EnumBlob;