diff options
Diffstat (limited to 'json-glib/json-gobject.c')
-rw-r--r-- | json-glib/json-gobject.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/json-glib/json-gobject.c b/json-glib/json-gobject.c index f10434d..fdb17e4 100644 --- a/json-glib/json-gobject.c +++ b/json-glib/json-gobject.c @@ -130,6 +130,134 @@ json_serializable_deserialize_property (JsonSerializable *serializable, } static gboolean +enum_from_string (GType type, + const gchar *string, + gint *enum_value) +{ + GEnumClass *eclass; + GEnumValue *ev; + gchar *endptr; + gint value; + gboolean retval = TRUE; + + g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0); + g_return_val_if_fail (string != NULL, 0); + + value = strtoul (string, &endptr, 0); + if (endptr != string) /* parsed a number */ + *enum_value = value; + else + { + eclass = g_type_class_ref (type); + ev = g_enum_get_value_by_name (eclass, string); + if (!ev) + ev = g_enum_get_value_by_nick (eclass, string); + + if (ev) + *enum_value = ev->value; + else + retval = FALSE; + + g_type_class_unref (eclass); + } + + return retval; +} + +static gboolean +flags_from_string (GType type, + const gchar *string, + gint *flags_value) +{ + GFlagsClass *fclass; + gchar *endptr, *prevptr; + guint i, j, ret, value; + gchar *flagstr; + GFlagsValue *fv; + const gchar *flag; + gunichar ch; + gboolean eos; + + g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0); + g_return_val_if_fail (string != 0, 0); + + ret = TRUE; + + value = strtoul (string, &endptr, 0); + if (endptr != string) /* parsed a number */ + *flags_value = value; + else + { + fclass = g_type_class_ref (type); + + flagstr = g_strdup (string); + for (value = i = j = 0; ; i++) + { + eos = flagstr[i] == '\0'; + + if (!eos && flagstr[i] != '|') + continue; + + flag = &flagstr[j]; + endptr = &flagstr[i]; + + if (!eos) + { + flagstr[i++] = '\0'; + j = i; + } + + /* trim spaces */ + for (;;) + { + ch = g_utf8_get_char (flag); + if (!g_unichar_isspace (ch)) + break; + flag = g_utf8_next_char (flag); + } + + while (endptr > flag) + { + prevptr = g_utf8_prev_char (endptr); + ch = g_utf8_get_char (prevptr); + if (!g_unichar_isspace (ch)) + break; + endptr = prevptr; + } + + if (endptr > flag) + { + *endptr = '\0'; + fv = g_flags_get_value_by_name (fclass, flag); + + if (!fv) + fv = g_flags_get_value_by_nick (fclass, flag); + + if (fv) + value |= fv->value; + else + { + ret = FALSE; + break; + } + } + + if (eos) + { + *flags_value = value; + break; + } + } + + g_free (flagstr); + + g_type_class_unref (fclass); + } + + return ret; +} + +static gboolean json_deserialize_pspec (GValue *value, GParamSpec *pspec, JsonNode *node) @@ -201,6 +329,48 @@ json_deserialize_pspec (GValue *value, retval = TRUE; break; + case G_TYPE_ENUM: + { + gint enum_value; + + if (G_VALUE_HOLDS (&node_value, G_TYPE_INT)) + { + enum_value = g_value_get_int (&node_value); + retval = TRUE; + } + else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + retval = enum_from_string (G_VALUE_TYPE (value), + g_value_get_string (&node_value), + &enum_value); + } + + if (retval) + g_value_set_enum (value, enum_value); + } + break; + + case G_TYPE_FLAGS: + { + gint flags_value; + + if (G_VALUE_HOLDS (&node_value, G_TYPE_INT)) + { + flags_value = g_value_get_int (&node_value); + retval = TRUE; + } + else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + retval = flags_from_string (G_VALUE_TYPE (value), + g_value_get_string (&node_value), + &flags_value); + } + + if (retval) + g_value_set_flags (value, flags_value); + } + break; + default: retval = FALSE; break; |