#include <stdio.h>
#include <stdlib.h>
#include "gio/gio.h"

GDBusMessage *
marshall_message ()
{
  GVariantBuilder builder;
  GDBusMessage *msg = g_dbus_message_new_signal ("/org/gnome/gdbus/test",
                                                 "org.gnome.GDBus.Test",
                                                 "Test");

  g_dbus_message_set_body (msg, g_variant_new ("(iis)", 1, 2, "string"));
  return msg;
}

static void
mode_1 (int tries)
{
  int i;
  gsize size;

  for (i = 0; i < tries; i++)
  {
    GDBusMessage *msg = marshall_message ();
    gchar *blob = g_dbus_message_to_blob (msg, &size, 0, NULL);
    g_free (blob);
    g_object_unref (msg);
  }
}

static void
mode_2 (int tries)
{
  int i;
  gsize size;
  GDBusMessage *msg = marshall_message ();

  for (i = 0; i < tries; i++)
  {
    gchar *blob = g_dbus_message_to_blob (msg, &size, 0, NULL);
    g_free (blob);
  }
  g_object_unref (msg);
}

static void
mode_3 (int tries)
{
  int i;
  gsize size;
  GDBusMessage *msg = marshall_message ();
  gchar *blob = g_dbus_message_to_blob (msg, &size, 0, NULL);
  GError *error = NULL;

  for (i = 0; i < tries; i++)
  {
    GDBusMessage *msg2 = g_dbus_message_new_from_blob (blob, size, 0, &error);
    g_object_unref (msg2);
  }
  g_free (blob);
  g_object_unref (msg);
}

main(int argc, const char *argv[])
{
  GDBusConnection *bus;
  int i;
  GError *error = NULL;
  gint mode = 1;
  const gchar *name;

  g_type_init ();
  if (argc > 1)
  {
    if (argc > 2 || sscanf (argv[1], "--mode=%d\n", &mode) != 1)
    {
      g_print ("Usage: %s [--mode=<mode>]\n", argv[0]);
      g_print ("Modes are as follows:\n");
      g_print ("1 = marshal and serialize\n");
      g_print ("2 = serialize only\n");
      g_print ("3 = de-serialize only\n");
      exit (1);
    }
  }

  bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
  if (!bus)
  {
    fprintf(stderr, "Couldn't connect to the bus\n");
    return 1;
  }
  name = g_dbus_connection_get_unique_name (bus);
  switch (mode)
  {
  case 1:
    mode_1 (50000);
    break;
  case 2:
    mode_2 (50000);
    break;
  case 3:
    mode_3 (50000);
    break;
  default:
    g_print ("%s: Invalid mode: %d\n", argv[0], mode);
  }
}
