Handle enumerations with the full range of signed and unsigned values

The C compiler will pick an enumeration type that accomodates the specified
values for the enumeration, so ignoring 64-bit enumerations, we can
have enumeration values from MININT32 to MAXUINT32. To handle this properly:

 - Use gint64 for holding eumeration values when scanning
 - Add a 'unsigned_value' bit to ValueBlob so we can distinguish the
   int32 vs. uint32 cases in the typelib
 - Change the return value of g_value_info_get_value() to gint64.

https://bugzilla.gnome.org/show_bug.cgi?id=629704
This commit is contained in:
Owen W. Taylor 2010-09-14 11:59:03 -04:00
parent 7fa7162361
commit ec76ea8628
8 changed files with 28 additions and 17 deletions

View File

@ -127,9 +127,11 @@ g_enum_info_get_storage_type (GIEnumInfo *info)
* *
* Obtain the enumeration value of the #GIValueInfo. * Obtain the enumeration value of the #GIValueInfo.
* *
* Returns: the enumeration value * Returns: the enumeration value. This will always be representable
* as a 32-bit signed or unsigned value. The use of gint64 as the
* return type is to allow both.
*/ */
glong gint64
g_value_info_get_value (GIValueInfo *info) g_value_info_get_value (GIValueInfo *info)
{ {
GIRealInfo *rinfo = (GIRealInfo *)info; GIRealInfo *rinfo = (GIRealInfo *)info;
@ -140,6 +142,9 @@ g_value_info_get_value (GIValueInfo *info)
blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset]; blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
return (glong)blob->value; if (blob->unsigned_value)
return (gint64)(guint32)blob->value;
else
return (gint64)blob->value;
} }

View File

@ -42,7 +42,7 @@ GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
gint n); gint n);
GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info); GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info);
glong g_value_info_get_value (GIValueInfo *info); gint64 g_value_info_get_value (GIValueInfo *info);
G_END_DECLS G_END_DECLS

View File

@ -269,9 +269,9 @@ g_field_info_get_field (GIFieldInfo *field_info,
case GI_INFO_TYPE_FLAGS: case GI_INFO_TYPE_FLAGS:
{ {
/* FIXME: there's a mismatch here between the value->v_int we use /* FIXME: there's a mismatch here between the value->v_int we use
* here and the glong result returned from g_value_info_get_value(). * here and the gint64 result returned from g_value_info_get_value().
* But to switch this to glong, we'd have to make g_function_info_invoke() * But to switch this to gint64, we'd have to make g_function_info_invoke()
* translate value->v_long to the proper ABI for an enum function * translate value->v_int64 to the proper ABI for an enum function
* call parameter, which will usually be int, and then fix up language * call parameter, which will usually be int, and then fix up language
* bindings. * bindings.
*/ */

View File

@ -2201,8 +2201,9 @@ g_ir_node_build_typelib (GIrNode *node,
blob->deprecated = value->deprecated; blob->deprecated = value->deprecated;
blob->reserved = 0; blob->reserved = 0;
blob->unsigned_value = value->value >= 0 ? 1 : 0;
blob->name = write_string (node->name, strings, data, offset2); blob->name = write_string (node->name, strings, data, offset2);
blob->value = value->value; blob->value = (gint32)value->value;
} }
break; break;

View File

@ -262,7 +262,7 @@ struct _GIrNodeValue
gboolean deprecated; gboolean deprecated;
gint32 value; gint64 value;
}; };
struct _GIrNodeConstant struct _GIrNodeConstant

View File

@ -1440,7 +1440,7 @@ start_property (GMarkupParseContext *context,
return TRUE; return TRUE;
} }
static gint static gint64
parse_value (const gchar *str) parse_value (const gchar *str)
{ {
gchar *shift_op; gchar *shift_op;
@ -1450,15 +1450,15 @@ parse_value (const gchar *str)
if (shift_op) if (shift_op)
{ {
gint base, shift; gint64 base, shift;
base = strtol (str, NULL, 10); base = g_ascii_strtoll (str, NULL, 10);
shift = strtol (shift_op + 3, NULL, 10); shift = g_ascii_strtoll (shift_op + 3, NULL, 10);
return base << shift; return base << shift;
} }
else else
return strtol (str, NULL, 10); return g_ascii_strtoll (str, NULL, 10);
return 0; return 0;
} }

View File

@ -704,7 +704,8 @@ write_value_info (const gchar *namespace,
Xml *file) Xml *file)
{ {
const gchar *name; const gchar *name;
glong value; gint64 value;
gchar *value_str;
gboolean deprecated; gboolean deprecated;
name = g_base_info_get_name ((GIBaseInfo *)info); name = g_base_info_get_name ((GIBaseInfo *)info);
@ -712,7 +713,9 @@ write_value_info (const gchar *namespace,
deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info); deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
xml_start_element (file, "member"); xml_start_element (file, "member");
xml_printf (file, " name=\"%s\" value=\"%ld\"", name, value); value_str = g_strdup_printf ("%" G_GINT64_FORMAT, value);
xml_printf (file, " name=\"%s\" value=\"%s\"", name, value_str);
g_free (value_str);
if (deprecated) if (deprecated)
xml_printf (file, " deprecated=\"1\""); xml_printf (file, " deprecated=\"1\"");

View File

@ -632,6 +632,7 @@ typedef struct {
/** /**
* ValueBlob: * ValueBlob:
* @deprecated: Whether this value is deprecated * @deprecated: Whether this value is deprecated
* @unsigned_value: if set, value is a 32-bit unsigned integer cast to gint32
* @value: The numerical value * @value: The numerical value
* @name: Name of blob * @name: Name of blob
* *
@ -639,8 +640,9 @@ typedef struct {
*/ */
typedef struct { typedef struct {
guint32 deprecated : 1; guint32 deprecated : 1;
guint32 unsigned_value : 1;
/* <private> */ /* <private> */
guint32 reserved :31; guint32 reserved :30;
/* <public> */ /* <public> */
guint32 name; guint32 name;
gint32 value; gint32 value;