+/* iterate over all memberships in the table
+ *
+ * The table is structured as a vertical list of memberships, each for a
+ * different community/realm. Each element in this list has a horizontal "origin list,"
+ * each for the same community/realm but with a different origin for the membership.
+ * Only the first element in the origin list has a vertical link ("next" pointer).
+ * Any element may have a horizontal link ("origin_next" pointer).
+ *
+ * (A) - (B) - (C) - X
+ * |
+ * (D) - (E) - X
+ * |
+ * (F) - X
+ * |
+ * (G) - (H) - X
+ * |
+ * X
+ *
+ * A, B, and C are all community/realm pair membership 1, with different origins
+ * D, E are a second community/realm pair, with different origins
+ * F is a third...
+ * G, H are a fourth pair, with different origins
+ *
+ * This iterator will return every element in the grid.
+ *
+ * Algorithm:
+ * The iterator struct stores the current member (cur_memb) and the origin head (cur_orig_head).
+ * The latter is a pointer to the head of the current origin list (i.e., first element in a row).
+ * The former can point to any element in the list. Both start at the root of the list (A in the
+ * diagram above).
+ *
+ * After each call to _first() or _next(), cur_memb points to the element just returned.
+ *
+ * 0. _first() just returns the first element. The rest of the steps are in _next()
+ *
+ * 1. If cur_memb has an origin_next element, walk the origin list. Move cur_memb to
+ * the origin_list element (next one in this row) and return it.
+ * 2. If cur_memb does not have an origin_next element, we've finished the current origin
+ * list. Move cur_memb to cur_orig_head's next element (the start of the next column),
+ * move cur_orig_head to that same place, and return it.
+ * 3. If neither cur_memb has an origin_next element nor cur_orig_head has a next element,
+ * then we have already reached the end of the list and there's nothing more to do.
+ * Return NULL.
+ */