From f05c86618ce97c8b07b094911cf93f0c11b960c9 Mon Sep 17 00:00:00 2001
From: ZmnSCPxj <ZmnSCPxj@protonmail.com>
Date: Sat, 24 Feb 2018 12:11:14 +0000
Subject: [PATCH] invoices: Change iteration interface to be more abstract.

---
 lightningd/invoice.c     |  8 ++++----
 wallet/invoices.c        | 18 +++++++++++++-----
 wallet/invoices.h        | 31 ++++++++++++++++++++++++-------
 wallet/test/run-wallet.c | 10 ++++++++--
 wallet/wallet.c          | 13 ++++++++++---
 wallet/wallet.h          | 37 ++++++++++++++++++++++++++++++-------
 6 files changed, 89 insertions(+), 28 deletions(-)

diff --git a/lightningd/invoice.c b/lightningd/invoice.c
index 2cf380277..1e8f9e9b1 100644
--- a/lightningd/invoice.c
+++ b/lightningd/invoice.c
@@ -245,15 +245,15 @@ static void json_add_invoices(struct json_result *response,
 			      const char *buffer, const jsmntok_t *label,
 			      bool modern)
 {
-	const struct invoice *i;
+	struct invoice_iterator it;
 	struct invoice_details details;
 	char *lbl = NULL;
 	if (label)
 		lbl = tal_strndup(response, &buffer[label->start], label->end - label->start);
 
-	i = NULL;
-	while ((i = wallet_invoice_iterate(wallet, i)) != NULL) {
-		wallet_invoice_details(response, wallet, i, &details);
+	memset(&it, 0, sizeof(it));
+	while (wallet_invoice_iterate(wallet, &it)) {
+		wallet_invoice_iterator_deref(response, wallet, &it, &details);
 		if (lbl && !streq(details.label, lbl))
 			continue;
 		json_add_invoice(response, &details, modern);
diff --git a/wallet/invoices.c b/wallet/invoices.c
index d6d7f05b5..39058f30e 100644
--- a/wallet/invoices.c
+++ b/wallet/invoices.c
@@ -446,13 +446,21 @@ bool invoices_delete(struct invoices *invoices,
 	return true;
 }
 
-const struct invoice *invoices_iterate(struct invoices *invoices,
-				       const struct invoice *invoice)
+bool invoices_iterate(struct invoices *invoices,
+		      struct invoice_iterator *it)
 {
-	if (invoice)
-		return list_next(&invoices->invlist, invoice, list);
+	if (it->curr)
+		it->curr = list_next(&invoices->invlist, it->curr, list);
 	else
-		return list_top(&invoices->invlist, struct invoice, list);
+		it->curr = list_top(&invoices->invlist, struct invoice, list);
+	return it->curr != NULL;
+}
+void invoices_iterator_deref(const tal_t *ctx,
+			     struct invoices *invoices,
+			     const struct invoice_iterator *it,
+			     struct invoice_details *details)
+{
+	invoices_get_details(ctx, invoices, it->curr, details);
 }
 
 static s64 get_next_pay_index(struct db *db)
diff --git a/wallet/invoices.h b/wallet/invoices.h
index de46ed6b4..83ebcc7c4 100644
--- a/wallet/invoices.h
+++ b/wallet/invoices.h
@@ -8,6 +8,7 @@
 struct db;
 struct invoice;
 struct invoice_details;
+struct invoice_iterator;
 struct invoices;
 struct log;
 struct sha256;
@@ -91,18 +92,34 @@ bool invoices_delete(struct invoices *invoices,
  * invoices_iterate - Iterate over all existing invoices
  *
  * @invoices - the invoice handler.
- * @invoice - the previous invoice you iterated over.
+ * @iterator - the iterator object to use.
  *
- * Return NULL at end-of-sequence. Usage:
+ * Return false at end-of-sequence, true if still iterating.
+ * Usage:
  *
- *   const struct invoice *i;
- *   i = NULL;
- *   while ((i = invoices_iterate(invoices, i))) {
+ *   struct invoice_iterator it;
+ *   memset(&it, 0, sizeof(it))
+ *   while (invoices_iterate(wallet, &it)) {
  *       ...
  *   }
  */
-const struct invoice *invoices_iterate(struct invoices *invoices,
-				       const struct invoice *invoice);
+bool invoices_iterate(struct invoices *invoices,
+		      struct invoice_iterator *it);
+
+/**
+ * wallet_invoice_iterator_deref - Read the details of the
+ * invoice currently pointed to by the given iterator.
+ *
+ * @ctx - the owner of the label and msatoshi fields returned.
+ * @wallet - the wallet whose invoices are to be iterated over.
+ * @iterator - the iterator object to use.
+ * @details - pointer to details object to load.
+ *
+ */
+void invoices_iterator_deref(const tal_t *ctx,
+			     struct invoices *invoices,
+			     const struct invoice_iterator *it,
+			     struct invoice_details *details);
 
 /**
  * invoices_resolve - Mark an invoice as paid
diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c
index 097ff3cdc..48ad1a10a 100644
--- a/wallet/test/run-wallet.c
+++ b/wallet/test/run-wallet.c
@@ -119,9 +119,15 @@ void invoices_get_details(const tal_t *ctx UNNEEDED,
 			  struct invoice_details *details UNNEEDED)
 { fprintf(stderr, "invoices_get_details called!\n"); abort(); }
 /* Generated stub for invoices_iterate */
-const struct invoice *invoices_iterate(struct invoices *invoices UNNEEDED,
-				       const struct invoice *invoice UNNEEDED)
+bool invoices_iterate(struct invoices *invoices UNNEEDED,
+		      struct invoice_iterator *it UNNEEDED)
 { fprintf(stderr, "invoices_iterate called!\n"); abort(); }
+/* Generated stub for invoices_iterator_deref */
+void invoices_iterator_deref(const tal_t *ctx UNNEEDED,
+			     struct invoices *invoices UNNEEDED,
+			     const struct invoice_iterator *it UNNEEDED,
+			     struct invoice_details *details UNNEEDED)
+{ fprintf(stderr, "invoices_iterator_deref called!\n"); abort(); }
 /* Generated stub for invoices_load */
 bool invoices_load(struct invoices *invoices UNNEEDED)
 { fprintf(stderr, "invoices_load called!\n"); abort(); }
diff --git a/wallet/wallet.c b/wallet/wallet.c
index 2c02242b0..0e5564444 100644
--- a/wallet/wallet.c
+++ b/wallet/wallet.c
@@ -1287,10 +1287,17 @@ bool wallet_invoice_delete(struct wallet *wallet,
 {
 	return invoices_delete(wallet->invoices, invoice);
 }
-const struct invoice *wallet_invoice_iterate(struct wallet *wallet,
-					     const struct invoice *invoice)
+bool wallet_invoice_iterate(struct wallet *wallet,
+			    struct invoice_iterator *it)
 {
-	return invoices_iterate(wallet->invoices, invoice);
+	return invoices_iterate(wallet->invoices, it);
+}
+void wallet_invoice_iterator_deref(const tal_t *ctx,
+				   struct wallet *wallet,
+				   const struct invoice_iterator *it,
+				   struct invoice_details *details)
+{
+	return invoices_iterator_deref(ctx, wallet->invoices, it, details);
 }
 void wallet_invoice_resolve(struct wallet *wallet,
 			    const struct invoice *invoice,
diff --git a/wallet/wallet.h b/wallet/wallet.h
index 02f64b6c7..dde8bdcb7 100644
--- a/wallet/wallet.h
+++ b/wallet/wallet.h
@@ -390,6 +390,13 @@ struct invoice_details {
 	u64 paid_timestamp;
 };
 
+/* An object that handles iteration over the set of invoices */
+struct invoice_iterator {
+	/* The contents of this object is subject to change
+	 * and should not be depended upon */
+	const struct invoice *curr;
+};
+
 struct invoice {
 	/* Internal, rest of lightningd should not use */
 	/* List off ld->wallet->invoices. Must be first or else
@@ -476,18 +483,34 @@ bool wallet_invoice_delete(struct wallet *wallet,
  * wallet_invoice_iterate - Iterate over all existing invoices
  *
  * @wallet - the wallet whose invoices are to be iterated over.
- * @invoice - the previous invoice you iterated over.
+ * @iterator - the iterator object to use.
  *
- * Return NULL at end-of-sequence. Usage:
+ * Return false at end-of-sequence, true if still iterating.
+ * Usage:
  *
- *   const struct invoice *i;
- *   i = NULL;
- *   while ((i = wallet_invoice_iterate(wallet, i))) {
+ *   struct invoice_iterator it;
+ *   memset(&it, 0, sizeof(it))
+ *   while (wallet_invoice_iterate(wallet, &it)) {
  *       ...
  *   }
  */
-const struct invoice *wallet_invoice_iterate(struct wallet *wallet,
-					     const struct invoice *invoice);
+bool wallet_invoice_iterate(struct wallet *wallet,
+			    struct invoice_iterator *it);
+
+/**
+ * wallet_invoice_iterator_deref - Read the details of the
+ * invoice currently pointed to by the given iterator.
+ *
+ * @ctx - the owner of the label and msatoshi fields returned.
+ * @wallet - the wallet whose invoices are to be iterated over.
+ * @iterator - the iterator object to use.
+ * @details - pointer to details object to load.
+ *
+ */
+void wallet_invoice_iterator_deref(const tal_t *ctx,
+				   struct wallet *wallet,
+				   const struct invoice_iterator *it,
+				   struct invoice_details *details);
 
 /**
  * wallet_invoice_resolve - Mark an invoice as paid