/* gcc `pkg-config --cflags --libs glib-2.0` test.c -o test */
#include <glib.h>

GHashTable *table;
gint destroy_notify_count = 0;

void
value_destroy_notify (gpointer value)
{
  destroy_notify_count += 1;
  g_hash_table_remove (table, value);
  g_printf ("inserting %i\n", GPOINTER_TO_SIZE (value));
  g_hash_table_insert (table, value, value);
}


gboolean
hash_table_remove_func (gpointer key, gpointer value, gpointer user_data)
{
  gboolean result;

  result =  GPOINTER_TO_SIZE (value) % 2;
  g_printf ("remove_func for %i is %i\n", GPOINTER_TO_SIZE (key), GPOINTER_TO_SIZE (result));
  return result;
}


GHashTable*
create_populated_table ()
{
  GHashTable *result;
  gint i;

  result = g_hash_table_new_full (g_direct_hash,
                                  g_direct_equal,
                                  NULL,
                                  value_destroy_notify);

  for (i = 0; i < 100; i += 2) {
    g_hash_table_insert (result, GSIZE_TO_POINTER (i), GSIZE_TO_POINTER (i+1));
    g_hash_table_insert (result, GSIZE_TO_POINTER (i+1), GSIZE_TO_POINTER (i));
  }

  return result;
}

int
main()
{
  /* Test for g_hash_table_remove_all */
#if 1
  table = create_populated_table ();

  destroy_notify_count = 0;
  g_hash_table_remove_all (table);
  /* 100 are removed, and 100 are readded */
  g_assert (g_hash_table_size (table) == 100);
  g_assert (destroy_notify_count == 100);

  g_printf ("all nodes removed\n");

  destroy_notify_count = 0;
  g_hash_table_unref (table);
  /* Note: The hash table still contains 100 elements at final destruction. */
  g_assert (destroy_notify_count == 100);

  table = NULL;
#endif

  /* Test for g_hash_table_foreach_remove */
#if 1
  table = create_populated_table ();

  g_printf ("removing all odd elements with an odd value\n");
  destroy_notify_count = 0;
  g_assert (g_hash_table_foreach_remove (table, hash_table_remove_func, NULL) == 50);
  /* The foreach removed half of the items (50), but the other half
   * was destroyed by the notification.
   * This means we destroyed (and reinserted) everything */
  g_assert (g_hash_table_size (table) == 100);
  g_assert (destroy_notify_count == 100);

  g_printf ("stealing all odd elements now\n");
  destroy_notify_count = 0;
  g_assert (g_hash_table_foreach_steal (table, hash_table_remove_func, NULL) == 50);
  /* 50 are removed, and 0 are readded */
  g_assert (g_hash_table_size (table) == 50);
  g_assert (destroy_notify_count == 0);

  g_printf ("and destroying the table\n");
  destroy_notify_count = 0;
  g_hash_table_unref (table);
  /* Note: The hash table still contains 50 elements at final destruction. */
  g_assert (destroy_notify_count == 50);
#endif
}

