the_Foundation [release-1.2]

StringList: Implemented missing iterator remove and take methods

=> 08d97e4bfec42162b7953efe80cc2b410b63fdcd

diff --git a/CHANGES.md b/CHANGES.md
index ba891bd..59b43d4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,7 @@
 
 ## 1.7.1
 * String: Fixed issue with the `mid` method when starting position is at or past the end.
+* StringList: Implemented missing iterator `remove` and `take` methods.
 * TlsRequest: TLS 1.2 is the minimum accepted protocol version.
 
 ## 1.7
diff --git a/src/stringlist.c b/src/stringlist.c
index 70ae6ec..e16d63e 100644
--- a/src/stringlist.c
+++ b/src/stringlist.c
@@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include 
 #include 
 
-#define iStringListMaxStringsPerNode    1024
+#define iStringListMaxStringsPerNode    512    /* TODO: could be a per-list dynamic setting */
 
 iDeclareType(StringListNode)
 
@@ -101,6 +101,7 @@ void clear_StringList(iStringList *d) {
 static iStringListNode *locateNode_StringList_(const iStringList *d, size_t pos, size_t *start_out) {
     iAssert(pos < d->size);
     if (isEmpty_List(&d->list)) {
+        *start_out = iInvalidPos;
         return NULL;
     }
     const iBool forwards = (pos < d->size / 2);
@@ -330,6 +331,11 @@ void init_StringListIterator(iStringListIterator *d, iStringList *list) {
 void next_StringListIterator(iStringListIterator *d) {
     d->pos++;
     d->nodePos++;
+    if (!d->node || d->pos >= d->list->size) {
+        d->value = NULL;
+        return;
+    }
+    iAssert(d->nodePos <= size_StringListNode_(d->node));
     if (d->nodePos == size_StringListNode_(d->node)) {
         d->nodePos = 0;
         d->node = next_StringListNode_(d->node);
@@ -341,6 +347,25 @@ void next_StringListIterator(iStringListIterator *d) {
     updateValue_StringListIterator(d);
 }
 
+void remove_StringListIterator(iStringListIterator *d) {
+    delete_String(take_StringListIterator(d));
+}
+
+iString *take_StringListIterator(iStringListIterator *d) {
+    iString *taken = take_StringList(d->list, d->pos);
+    if (d->list->size == 0) {
+        d->node = NULL;
+    }
+    else {
+        size_t start;
+        d->pos--;
+        d->node = locateNode_StringList_(d->list, d->pos < size_StringList(d->list) ? d->pos : 0,
+                                         &start);
+        d->nodePos = d->pos - start;
+    }
+    return taken;
+}
+
 void init_StringListConstIterator(iStringListConstIterator *d, const iStringList *list) {
     d->node = front_List(&list->list);
     d->list = list;
diff --git a/tests/t_string.c b/tests/t_string.c
index e95b196..1e17811 100644
--- a/tests/t_string.c
+++ b/tests/t_string.c
@@ -42,12 +42,12 @@ int main(int argc, char *argv[]) {
         const iString str = iStringLiteral("Ääkkönén");
         iString *upper = collect_String(upper_String(&str));
         iString *lower = collect_String(lower_String(&str));
-        printf("Original: %s Upper: %s Lower: %s\n", 
+        printf("Original: %s Upper: %s Lower: %s\n",
                cstrLocal_String(&str), cstrLocal_String(upper), cstrLocal_String(lower));
     }
     /* Test Unicode strings. */ {
         iString *s = collect_String(newCStr_String("A_Äö\U0001f698a"));
-        printf("String: %s length: %zu size: %zu\n", 
+        printf("String: %s length: %zu size: %zu\n",
             cstrLocal_String(s), length_String(s), size_String(s)); {
             iConstForEach(String, i, s) {
                 printf(" char: %06x [%s]\n", i.value, cstrLocal_Char(i.value));
@@ -60,7 +60,7 @@ int main(int argc, char *argv[]) {
         }
         printf("Starts with: %i %i\n", startsWith_String(s, "a"), startsWithCase_String(s, "a"));
         printf("Ends with: %i %i\n", endsWith_String(s, "a"), endsWithCase_String(s, "A"));
-        printf("Mid: %s\n", cstrLocal_String(collect_String(mid_String(s, 3, 1))));        
+        printf("Mid: %s\n", cstrLocal_String(collect_String(mid_String(s, 3, 1))));
         printf("%s is at: %zu %zu\n", cstrLocal_Char(u'ö'), indexOfCStr_String(s, "ö"), indexOf_String(s, U'ö'));
         truncate_String(s, 3);
         printf("Truncated: %s\n", cstrLocal_String(s));
@@ -105,6 +105,34 @@ int main(int argc, char *argv[]) {
         }
         iRelease(file);
     }
+    /* String list iteration. */ {
+        iStringList *list = new_StringList();
+        pushBackCStr_StringList(list, "first");
+        pushBackCStr_StringList(list, "second");
+        /* Remove it with the iterator. */
+        iForEach(StringList, j, list) {
+            if (!cmp_String(j.value, "first")) {
+                remove_StringListIterator(&j);
+            }
+        }
+        clear_StringList(list);
+        iAssert(size_StringList(list) == 0);
+        for (size_t i = 0; i < 514; i++) {
+            iString *s = newFormat_String("str%zu", i);
+            pushBack_StringList(list, s);
+            delete_String(s);
+        }
+        int numRemoved = 2;
+        printf("Iterating %zu strings, removing some:\n", size_StringList(list));
+        iForEach(StringList, i, list) {
+            if (i.pos == 256 && numRemoved-- > 0) {
+                remove_StringListIterator(&i);
+                continue;
+            }
+            printf("%s\n", cstr_String(i.value));
+        }
+        iRelease(list);
+    }
     /* Splitting a string. */ {
         const iString *str = &iStringLiteral("/usr/local/bin");
         const iRangecc rng = range_String(str);
Proxy Information
Original URL
gemini://git.skyjake.fi/the_Foundation/release-1.2/cdiff/08d97e4bfec42162b7953efe80cc2b410b63fdcd
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
28.736983 milliseconds
Gemini-to-HTML Time
0.511793 milliseconds

This content has been proxied by September (ba2dc).