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; | 
