Esempio n. 1
0
void        bb_adjust_value            (GValue       *out,
                                        const GValue *in,
                                        BbAdjustmentMode adjust_mode)
{
  GType type = G_VALUE_TYPE (out);
  switch (G_TYPE_FUNDAMENTAL (type))
    {
    case G_TYPE_DOUBLE:
      if (G_VALUE_TYPE (in) != G_TYPE_DOUBLE)
        g_error ("cannot adjust a double with a %s", G_VALUE_TYPE_NAME (in));
      g_value_set_double (out, bb_adjust_double (g_value_get_double (out), g_value_get_double (in), adjust_mode));
      break;
    default:
      if (type == BB_TYPE_DURATION)
        {
          BbDuration dur;
          switch (adjust_mode)
            {
            case BB_ADJUSTMENT_REPLACE:
              {
                if (G_VALUE_TYPE (in) != type)
                  g_error ("cannot replace a %s with a %s", g_type_name (type),
                           G_VALUE_TYPE_NAME (in));
                g_value_copy (in, out);
                break;
              }
            case BB_ADJUSTMENT_MULTIPLY:
              {
                if (G_VALUE_TYPE (in) != G_TYPE_DOUBLE)
                  g_error ("cannot multiply a duration by a %s",
                           G_VALUE_TYPE_NAME (in));
                bb_value_get_duration (out, &dur);
                dur.value *= g_value_get_double (in);
                bb_value_set_duration (out, dur.units, dur.value);
                break;
              }
            case BB_ADJUSTMENT_ADD:
              {
                BbDuration indur;
                if (G_VALUE_TYPE (in) != BB_TYPE_DURATION)
                  g_error ("cannot add a %s to a duration",
                           G_VALUE_TYPE_NAME (in));
                bb_value_get_duration (out, &dur);
                bb_value_get_duration (in, &indur);
                if (dur.units != indur.units)
                  g_error ("cannot add durations of differing units");
                dur.value += indur.value;
                bb_value_set_duration (out, dur.units, dur.value);
                break;
              }
            case BB_ADJUSTMENT_DIVIDE:
              {
                if (G_VALUE_TYPE (in) != G_TYPE_DOUBLE)
                  g_error ("cannot divide a duration by a %s",
                           G_VALUE_TYPE_NAME (in));
                bb_value_get_duration (out, &dur);
                dur.value *= g_value_get_double (in);
                bb_value_set_duration (out, dur.units, dur.value);
                break;
              }
            case BB_ADJUSTMENT_SUBTRACT:
              {
                BbDuration indur;
                if (G_VALUE_TYPE (in) != BB_TYPE_DURATION)
                  g_error ("cannot subtract a %s to a duration",
                           G_VALUE_TYPE_NAME (in));
                bb_value_get_duration (out, &dur);
                bb_value_get_duration (in, &indur);
                if (dur.units != indur.units)
                  g_error ("cannot subtract durations of differing units");
                dur.value -= indur.value;
                bb_value_set_duration (out, dur.units, dur.value);
                break;
              }
            default:
              g_return_if_reached ();
            }
        }
      else
        g_error ("cannot interpolate value of type %s", g_type_name (type));
    }
}
Esempio n. 2
0
static GObject *
json_gobject_new (GType       gtype,
                  JsonObject *object)
{
  JsonSerializableIface *iface = NULL;
  JsonSerializable *serializable = NULL;
  gboolean find_property;
  gboolean deserialize_property;
  gboolean set_property;
  GQueue *members;
  GList *l;
  GQueue members_left = G_QUEUE_INIT;
  guint n_members;
  GObjectClass *klass;
  GObject *retval;
  GArray *construct_params;
  gint i;

  klass = g_type_class_ref (gtype);

  n_members = json_object_get_size (object);
  members = json_object_get_members_internal (object);

  /* first pass: construct-only properties; here we cannot use Serializable
   * because we don't have an instance yet; we use the default implementation
   * of json_deserialize_pspec() to deserialize known types
   *
   * FIXME - find a way to allow deserialization for these properties
   */
  construct_params = g_array_sized_new (FALSE, FALSE, sizeof (GParameter), n_members);

  for (l = members->head; l != NULL; l = l->next)
    {
      const gchar *member_name = l->data;
      GParamSpec *pspec;
      GParameter param = { NULL, };
      JsonNode *val;
      gboolean res = FALSE;

      pspec = g_object_class_find_property (klass, member_name);
      if (!pspec)
        goto next_member;

      /* we only apply construct-only properties here */
      if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0)
        goto next_member;

      if (!(pspec->flags & G_PARAM_WRITABLE))
        goto next_member;

      g_value_init (&param.value, G_PARAM_SPEC_VALUE_TYPE (pspec));

      val = json_object_get_member (object, member_name);
      res = json_deserialize_pspec (&param.value, pspec, val);
      if (!res)
	{
	  g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
		     pspec->name, G_VALUE_TYPE_NAME (&param.value), g_type_name (gtype));

	  g_value_unset (&param.value);
	}
      else
        {
          param.name = g_strdup (pspec->name);

          g_array_append_val (construct_params, param);

          continue;
        }

    next_member:
      g_queue_push_tail (&members_left, l->data);
    }

  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
  retval = g_object_newv (gtype,
                          construct_params->len,
                          (GParameter *) construct_params->data);
  G_GNUC_END_IGNORE_DEPRECATIONS

  /* free the contents of the GArray */
  for (i = 0; i < construct_params->len; i++)
    {
      GParameter *param = &g_array_index (construct_params, GParameter, i);

      g_free ((gchar *) param->name);
      g_value_unset (&param->value);
    }

  g_array_free (construct_params, TRUE);

  /* do the Serializable type check once */
  if (g_type_is_a (gtype, JSON_TYPE_SERIALIZABLE))
    {
      serializable = JSON_SERIALIZABLE (retval);
      iface = JSON_SERIALIZABLE_GET_IFACE (serializable);
      find_property = (iface->find_property != NULL);
      deserialize_property = (iface->deserialize_property != NULL);
      set_property = (iface->set_property != NULL);
    }
  else
    {
      find_property = FALSE;
      deserialize_property = FALSE;
      set_property = FALSE;
    }

  g_object_freeze_notify (retval);

  for (l = members_left.head; l != NULL; l = l->next)
    {
      const gchar *member_name = l->data;
      GParamSpec *pspec;
      JsonNode *val;
      GValue value = { 0, };
      gboolean res = FALSE;

      if (find_property)
        pspec = json_serializable_find_property (serializable, member_name);
      else
        pspec = g_object_class_find_property (klass, member_name);

      if (pspec == NULL)
        continue;

      /* we should have dealt with these above */
      if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
        continue;

      if (!(pspec->flags & G_PARAM_WRITABLE))
        continue;

      g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));

      val = json_object_get_member (object, member_name);

      if (deserialize_property)
        {
          JSON_NOTE (GOBJECT, "Using JsonSerializable for property '%s'", pspec->name);
          res = json_serializable_deserialize_property (serializable,
                                                        pspec->name,
                                                        &value,
                                                        pspec,
                                                        val);
        }

      if (!res)
        {
          JSON_NOTE (GOBJECT, "Using json_deserialize_pspec for property '%s'", pspec->name);
          res = json_deserialize_pspec (&value, pspec, val);
        }

      if (res)
        {
          JSON_NOTE (GOBJECT, "Calling set_property('%s', '%s')",
                     pspec->name,
                     g_type_name (G_VALUE_TYPE (&value)));

          if (set_property)
            json_serializable_set_property (serializable, pspec, &value);
          else
            g_object_set_property (retval, pspec->name, &value);
        }
      else
	g_warning ("Failed to deserialize \"%s\" property of type \"%s\" for an object of type \"%s\"",
		   pspec->name, g_type_name (G_VALUE_TYPE (&value)), g_type_name (gtype));

      g_value_unset (&value);
    }

  g_queue_clear (&members_left);

  g_object_thaw_notify (retval);

  g_type_class_unref (klass);

  return retval;
}