diff -x CVS -uNr glib.core/glib/ghash.c glib.funcs/glib/ghash.c
--- glib.core/glib/ghash.c	Thu May 30 18:51:19 2002
+++ glib.funcs/glib/ghash.c	Thu May 30 18:51:55 2002
@@ -697,3 +697,64 @@
       G_UNLOCK (g_hash_global);
     }
 }
+
+/**
+ * g_hash_table_iterate_keys:
+ * @list: The #GHashTable to iterate over.
+ *
+ * Creates an iterator to traverse the list of keys in this hash table.
+ * The list of keys is a snapshot of the current state of the hash table.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_hash_table_iterate_keys (GHashTable *hash_table)
+{
+    GList *list = NULL;
+    GHashNode *node;
+    GIterator *iter;
+    gint i;
+
+    g_return_val_if_fail (hash_table != NULL, g_iterator_new_empty());
+
+    for (i = 0; i < hash_table->size; i++)
+        for (node = hash_table->nodes[i]; node; node = node->next)
+            list = g_list_prepend(list, node->key);
+
+    list = g_list_reverse(list);
+
+    iter = g_list_iterate_and_consume(list);
+
+    return iter;
+}
+
+/**
+ * g_hash_table_iterate_values:
+ * @list: The #GHashTable to iterate over.
+ *
+ * Creates an iterator to traverse the list of values in this hash table.
+ * The list of values is a snapshot of the current state of the hash
+ * table.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_hash_table_iterate_values (GHashTable *hash_table)
+{
+    GList *list = NULL;
+    GHashNode *node;
+    GIterator *iter;
+    gint i;
+
+    g_return_val_if_fail (hash_table != NULL, g_iterator_new_empty());
+
+    for (i = 0; i < hash_table->size; i++)
+        for (node = hash_table->nodes[i]; node; node = node->next)
+            list = g_list_prepend(list, node->value);
+
+    list = g_list_reverse(list);
+
+    iter = g_list_iterate_and_consume(list);
+
+    return iter;
+}
diff -x CVS -uNr glib.core/glib/ghash.h glib.funcs/glib/ghash.h
--- glib.core/glib/ghash.h	Thu Dec  6 14:37:05 2001
+++ glib.funcs/glib/ghash.h	Sat Feb  2 21:48:31 2002
@@ -28,6 +28,7 @@
 #define __G_HASH_H__
 
 #include <glib/gtypes.h>
+#include <glib/giterator.h>
 
 G_BEGIN_DECLS
 
@@ -71,6 +72,8 @@
 guint	    g_hash_table_foreach_steal	   (GHashTable	   *hash_table,
 					    GHRFunc	    func,
 					    gpointer	    user_data);
+GIterator*  g_hash_table_iterate_keys      (GHashTable     *hash_table);
+GIterator*  g_hash_table_iterate_values    (GHashTable     *hash_table);
 guint	    g_hash_table_size		   (GHashTable	   *hash_table);
 
 #ifndef G_DISABLE_DEPRECATED
diff -x CVS -uNr glib.core/glib/glist.c glib.funcs/glib/glist.c
--- glib.core/glib/glist.c	Sun Jul  1 22:02:12 2001
+++ glib.funcs/glib/glist.c	Sun Feb  3 21:51:33 2002
@@ -874,3 +874,109 @@
   g_slist_free (runs);
   return list;
 }
+
+static gpointer
+g_list_iterator_has_more (gpointer context)
+{
+  gpointer *header;
+
+  g_return_val_if_fail (context != NULL, (gpointer) FALSE);
+
+  header = (gpointer *) context;
+  return (gpointer) (header[0] ? TRUE : FALSE);
+}
+
+static gpointer
+g_list_iterator_get_next (gpointer context)
+{
+  gpointer *header;
+  gpointer result;
+  GList *elem;
+  gboolean consume;
+
+  g_return_val_if_fail (context != NULL, NULL);
+
+  header = (gpointer *) context;
+  elem = (GList *) header[0];
+  consume = (gboolean) header[1];
+
+  /* User should have called has_more() */
+  g_return_val_if_fail(elem != NULL, NULL);
+
+  result = elem->data;
+
+  if (consume)
+    header[0] = (gpointer) g_list_delete_link(elem, elem);
+  else
+    header[0] = (gpointer) g_list_next(elem);
+
+  return result;
+}
+
+static void
+g_list_iterator_destroy_notify (gpointer context)
+{
+    gpointer *header;
+
+    g_return_if_fail (context != NULL);
+
+    header = (gpointer *) context;
+
+    g_free(header);
+}
+
+static GIterator *
+g_list_iterate_real (GList *list, gboolean consume)
+{
+  gpointer *header;
+  GIterator *iter;
+
+  if (!list)
+    return g_iterator_new_empty();
+
+  /* The header contains two elements.  The first is the next GList
+   * element to iterate.  The second is the value of consume.
+   */
+  header = g_new0(gpointer, 2);
+  header[0] = list;
+  header[1] = (gpointer) consume;
+
+  iter = g_iterator_new (header,
+                         g_list_iterator_has_more,
+                         g_list_iterator_get_next,
+                         g_list_iterator_destroy_notify);
+
+  return iter;
+}
+
+/**
+ * g_list_iterate:
+ * @list: The #GList to iterate over.
+ *
+ * Creates an iterator to iterate over the list.  The iterator traverses
+ * the list directly.  Removal of the most recently iterated item is
+ * safe, but no other deletion is supported.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_list_iterate (GList *list)
+{
+  return g_list_iterate_real (list, FALSE);
+}
+
+/**
+ * g_list_iterate_and_consume:
+ * @list: The #GList to iterate over and consume.
+ *
+ * Creates an iterator that consumes the list as it iterates it.  The
+ * data elements are untouched.  Modification of the list is strictly
+ * forbidden, as the iterator destroys it.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_list_iterate_and_consume (GList *list)
+{
+  return g_list_iterate_real (list, TRUE);
+}
diff -x CVS -uNr glib.core/glib/glist.h glib.funcs/glib/glist.h
--- glib.core/glib/glist.h	Sun Jul  1 22:02:12 2001
+++ glib.funcs/glib/glist.h	Sat Feb  2 21:18:57 2002
@@ -27,6 +27,7 @@
 #ifndef __G_LIST_H__
 #define __G_LIST_H__
 
+#include <glib/giterator.h>
 #include <glib/gmem.h>
 
 G_BEGIN_DECLS
@@ -91,6 +92,8 @@
 void     g_list_foreach        (GList            *list,
 				GFunc             func,
 				gpointer          user_data);
+GIterator* g_list_iterate      (GList            *list);
+GIterator* g_list_iterate_and_consume (GList     *list);
 GList*   g_list_sort           (GList            *list,
 				GCompareFunc      compare_func);
 GList*   g_list_sort_with_data (GList            *list,
diff -x CVS -uNr glib.core/glib/gslist.c glib.funcs/glib/gslist.c
--- glib.core/glib/gslist.c	Sun Jul  1 22:02:12 2001
+++ glib.funcs/glib/gslist.c	Sat Feb  2 23:14:08 2002
@@ -765,3 +765,109 @@
 {
   return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);
 }
+
+static gpointer
+g_slist_iterator_has_more (gpointer context)
+{
+  gpointer *header;
+
+  g_return_val_if_fail (context != NULL, (gpointer) FALSE);
+
+  header = (gpointer *) context;
+  return (gpointer) (header[0] ? TRUE : FALSE);
+}
+
+static gpointer
+g_slist_iterator_get_next (gpointer context)
+{
+  gpointer *header;
+  gpointer result;
+  GSList *elem;
+  gboolean consume;
+
+  g_return_val_if_fail (context != NULL, NULL);
+
+  header = (gpointer *) context;
+  elem = (GSList *) header[0];
+  consume = (gboolean) header[1];
+
+  /* User should have called has_more() */
+  g_return_val_if_fail(elem != NULL, NULL);
+
+  result = elem->data;
+
+  if (consume)
+    header[0] = (gpointer) g_slist_delete_link(elem, elem);
+  else
+    header[0] = (gpointer) g_slist_next(elem);
+
+  return result;
+}
+
+static void
+g_slist_iterator_destroy_notify (gpointer context)
+{
+    gpointer *header;
+
+    g_return_if_fail(context != NULL);
+
+    header = (gpointer *) context;
+
+    g_free(header);
+}
+
+static GIterator *
+g_slist_iterate_real (GSList *list, gboolean consume)
+{
+  gpointer *header;
+  GIterator *iter;
+
+  if (!list)
+    return g_iterator_new_empty();
+
+  /* The header contains two elements.  The first is the next GSList
+   * element to iterate.  The second is the value of consume.
+   */
+  header = g_new0(gpointer, 2);
+  header[0] = list;
+  header[1] = (gpointer) consume;
+
+  iter = g_iterator_new (header,
+                         g_slist_iterator_has_more,
+                         g_slist_iterator_get_next,
+                         g_slist_iterator_destroy_notify);
+
+  return iter;
+}
+
+/**
+ * g_slist_iterate:
+ * @list: The #GSList to iterate over.
+ *
+ * Creates an iterator to iterate over the list.  The iterator traverses
+ * the list directly.  Removal of the most recently iterated item is
+ * safe, but no other deletion is supported.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_slist_iterate (GSList *list)
+{
+  return g_slist_iterate_real (list, FALSE);
+}
+
+/**
+ * g_slist_iterate_and_consume:
+ * @list: The #GSList to iterate over and consume.
+ *
+ * Creates an iterator that consumes the list as it iterates it.  The
+ * data elements are untouched.  Modification of the list is strictly
+ * forbidden, as the iterator destroys it.
+ *
+ * Return value: The new #GIterator.
+ */
+GIterator*
+g_slist_iterate_and_consume (GSList *list)
+{
+  return g_slist_iterate_real (list, TRUE);
+}
diff -x CVS -uNr glib.core/glib/gslist.h glib.funcs/glib/gslist.h
--- glib.core/glib/gslist.h	Tue Jun 26 09:01:14 2001
+++ glib.funcs/glib/gslist.h	Sat Feb  2 21:20:51 2002
@@ -27,6 +27,7 @@
 #ifndef __G_SLIST_H__
 #define __G_SLIST_H__
 
+#include <glib/giterator.h>
 #include <glib/gmem.h>
 
 G_BEGIN_DECLS
@@ -87,6 +88,8 @@
 void     g_slist_foreach        (GSList           *list,
 				 GFunc             func,
 				 gpointer          user_data);
+GIterator* g_slist_iterate      (GSList           *list);
+GIterator* g_slist_iterate_and_consume (GSList    *list);
 GSList*  g_slist_sort           (GSList           *list,
 				 GCompareFunc      compare_func);
 GSList*  g_slist_sort_with_data (GSList           *list,
diff -x CVS -uNr glib.core/tests/testglib.c glib.funcs/tests/testglib.c
--- glib.core/tests/testglib.c	Thu May 30 18:51:24 2002
+++ glib.funcs/tests/testglib.c	Thu May 30 18:52:00 2002
@@ -795,6 +795,62 @@
   g_print ("ok\n");
 
 
+  g_print ("checking iteration from GList... ");
+
+  list = NULL;
+  for (i = 0; i < 10; i++)
+    list = g_list_append(list, (gpointer) i);
+
+  iter = g_list_iterate(list);
+  while (g_iterator_has_more (iter))
+    g_print ("%d ", (int) g_iterator_get_next (iter));
+
+  g_iterator_free(iter);
+  g_list_free(list);
+
+  g_print ("ok\n");
+
+  g_print ("checking iteration from GSList... ");
+
+  slist = NULL;
+  for (i = 0; i < 10; i++)
+    slist = g_slist_append(slist, (gpointer) i);
+
+  iter = g_slist_iterate(slist);
+  while (g_iterator_has_more (iter))
+    g_print ("%d ", (int) g_iterator_get_next (iter));
+
+  g_iterator_free(iter);
+  g_slist_free(slist);
+
+  g_print ("ok\n");
+
+
+  g_print ("checking iteration of hash keys... ");
+
+  hash_table = g_hash_table_new (my_hash, my_hash_equal);
+  for (i = 0; i < 10; i++)
+    {
+      array[i] = i;
+      g_hash_table_insert (hash_table, &array[i], &array[i]);
+    }
+
+  iter = g_hash_table_iterate_keys (hash_table);
+
+  i = 0;
+  while (g_iterator_has_more (iter))
+      i += *((guint8 *) g_iterator_get_next (iter));
+      
+  if (i != (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9))
+    g_print ("bad\n");
+  
+  g_iterator_free (iter);
+  
+  g_hash_table_destroy (hash_table);
+
+  g_print ("ok\n");
+
+
   g_print ("checking string chunks...");
 
   string_chunk = g_string_chunk_new (1024);
