Exemplo n.º 1
0
static void
_libwc_event_handler_pong(LibWCRelay *relay,
                          LibWCRelayMessage *event) {
    BEGIN_HANDLER;
    LibWCRelayMessageObject *argument_object;
    const gchar *ping_msg;
    gchar **ping_args = NULL;
    guint command_id;
    GTask *pending_task;
    GVariant *maybe = NULL;

    /* The only data we should get, if any, is a string */
    argument_object = g_list_first(event->objects)->data;
    IGNORE_EVENT_IF_FAIL(argument_object->type == LIBWC_OBJECT_TYPE_STRING);

    maybe = g_variant_get_maybe(argument_object->value);
    IGNORE_EVENT_IF_FAIL(maybe != NULL);
    ping_msg = g_variant_get_string(maybe, NULL);

    /* Split the ping message into two parts: the message ID, and (if
     * applicable) whatever string was returned with the ping */
    ping_args = g_strsplit(ping_msg, " ", 2);

    errno = 0;
    command_id = strtoul(ping_args[0], NULL, 16);
    IGNORE_EVENT_IF_FAIL(errno == 0);

    pending_task = _libwc_relay_pending_tasks_lookup(relay, command_id);
    IGNORE_EVENT_IF_FAIL(pending_task != NULL);

    g_task_return_pointer(pending_task, ping_args[1], g_free);
    _libwc_relay_pending_tasks_remove(relay, command_id);

    /* Mark the second argument as NULL, so it doesn't get freed with the rest
     * of the arguments */
    ping_args[1] = NULL;

    g_variant_unref(maybe);
    g_strfreev(ping_args);

    return;

event_error:
    if (maybe)
        g_variant_unref(maybe);
    if (ping_args)
        g_strfreev(ping_args);

    return;
}
Exemplo n.º 2
0
/* Generic qsort style comparison of variants
   For variants of the same class the "natural" order is used.
   If the types differ, we compare by value of GVariantClass
   except for:
    All numeric types (ints, double) compare by value
    All textish string types compare by utf8 collation
*/   
int
dtools_compare_variant (GVariant *a,
			GVariant *b)
{
  gint64 a64, b64;
  guint64 au64, bu64;
  double ad, bd;
  GVariantClass a_class, b_class;
  GVariant *ma, *mb;

  if (a == NULL && b == NULL)
    return 0;
  if (a == NULL)
    return 1;
  if (b == NULL)
    return -1;
  
  a_class = g_variant_classify (a);
  b_class = g_variant_classify (b);

  if (a_class == G_VARIANT_CLASS_MAYBE)
    {
      ma = g_variant_get_maybe (a);
      if (ma == NULL)
	{
	  if (b_class == G_VARIANT_CLASS_MAYBE &&
	      g_variant_get_maybe (b) == NULL)
	    return 0;
	  else
	    return 1; /* NULL sorts at end */
	}
      return dtools_compare_variant (ma, b);
    }

  if (b_class == G_VARIANT_CLASS_MAYBE)
    {
      mb = g_variant_get_maybe (b);
      if (mb == NULL)
	return -1; /* NULL sorts at end */
      return dtools_compare_variant (a, mb);
    }
  
  if (a_class == G_VARIANT_CLASS_VARIANT)
    return dtools_compare_variant (g_variant_get_child_value (a, 0),
				   b);
  
  if (b_class == G_VARIANT_CLASS_VARIANT)
    return dtools_compare_variant (a,
				   g_variant_get_child_value (b, 0));

  if (a_class == G_VARIANT_CLASS_DOUBLE &&
      b_class == G_VARIANT_CLASS_DOUBLE)
    {
      ad = g_variant_get_double (a);
      bd = g_variant_get_double (b);

      if (ad < bd)
	return -1;
      if (ad == bd)
	return 0;
      else
	return 1;
    }
  
  if (variant_class_is_int (a_class) &&
      variant_class_is_int (b_class))
    {
      if (variant_as_int64 (a, a_class, &a64) &&
	  variant_as_int64 (b, b_class, &b64))
	{
	  if (a64 < b64)
	    return -1;
	  else if (a64 == b64)
	    return 0;
	  else
	    return 1;
	}

      /* For integers the only leftover cases are:
	 a) Both a & b are uint64 (> maxint64)
	 b) One of a/b is uint64 (> maxint64)
	 b1) The other fits in uint64
	 b2) The other is < 0

	 This handles everything but case b2:
      */
      if (variant_as_uint64 (a, a_class, &au64) &&
	  variant_as_uint64 (b, b_class, &bu64))
	{
	  if (au64 < bu64)
	    return -1;
	  else if (au64 == bu64)
	    return 0;
	  else
	    return 1;
	}

      /* Handle case b2, one uint64, other is < 0  */
      if (variant_class_is_signed_int (a_class))
	/* signed but doesn't fit in uint64 => negative */
	return -1;
      else if (variant_class_is_signed_int (b_class))
	/* signed but doesn't fit in uint64 => negative */
	return 1;

      /* Can't be equal and yet not fit in either uint64 or int64 */
      g_assert_not_reached ();
    }

  if (a_class == G_VARIANT_CLASS_DOUBLE &&
      variant_class_is_int (b_class))
    {
      ad = g_variant_get_double (a);

      if (variant_as_int64 (b, b_class, &b64))
	return compare_double_int64 (ad, b64);
      else
	{
	  variant_as_uint64 (b, b_class, &bu64);
	  return compare_double_uint64 (ad, bu64);
	}
    }

  if (variant_class_is_int (a_class) &&
      b_class == G_VARIANT_CLASS_DOUBLE)
    {
      bd = g_variant_get_double (b);

      if (variant_as_int64 (a, a_class, &a64))
	return -compare_double_int64 (bd, a64);
      else
	{
	  variant_as_uint64 (a, a_class, &au64);
	  return -compare_double_uint64 (bd, au64);
	}

    }

  g_warning ("Unhandled variant type in compare\n");

  /* TODO: We just sort by ptr for now */
  if ((gsize)a < (gsize)b)
    return -1;
  else if (a == b)
    return 0;
  else
    return 1;
}