The pl_truncate function
The pl_remove function is not so fast because it internally uses
memmove. Removing last elements can be done more quickly.
@@ -1456,7 +1456,7 @@ | ||
1456 | 1456 | size_t newlen = dest->length; |
1457 | 1457 | if (!shopt_emptylastfield && newlen - oldlen >= 2 * 2 && |
1458 | 1458 | dest->contents[newlen - 2] == dest->contents[newlen - 1]) |
1459 | - pl_remove(dest, newlen - 2, 2); | |
1459 | + pl_truncate(dest, newlen - 2); | |
1460 | 1460 | |
1461 | 1461 | assert(dest->length - oldlen >= 2); |
1462 | 1462 | return (wchar_t *) &s[ifswhitestartindex]; |
@@ -1,6 +1,6 @@ | ||
1 | 1 | /* Yash: yet another shell */ |
2 | 2 | /* job.c: job control */ |
3 | -/* (C) 2007-2019 magicant */ | |
3 | +/* (C) 2007-2020 magicant */ | |
4 | 4 | |
5 | 5 | /* This program is free software: you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License as published by |
@@ -191,7 +191,7 @@ | ||
191 | 191 | while (tail > 1 && joblist.contents[tail - 1] == NULL) |
192 | 192 | tail--; |
193 | 193 | assert(tail > 0); |
194 | - pl_remove(&joblist, tail, SIZE_MAX); | |
194 | + pl_truncate(&joblist, tail); | |
195 | 195 | } |
196 | 196 | } |
197 | 197 |
@@ -501,7 +501,7 @@ | ||
501 | 501 | { |
502 | 502 | for (size_t i = undo_index; i < undo_history.length; i++) |
503 | 503 | free(undo_history.contents[i]); |
504 | - pl_remove(&undo_history, undo_index, SIZE_MAX); | |
504 | + pl_truncate(&undo_history, undo_index); | |
505 | 505 | |
506 | 506 | // No need to check for overflow in `len + 1' here. Should overflow occur, |
507 | 507 | // the buffer would not have been allocated successfully. |
@@ -1284,7 +1284,7 @@ | ||
1284 | 1284 | if (isdir) { |
1285 | 1285 | rp = prev; |
1286 | 1286 | /* result[index] = L'\0'; */ |
1287 | - pl_remove(&clist, clist.length - 1, 1); | |
1287 | + pl_truncate(&clist, clist.length - 1); | |
1288 | 1288 | path += 2; |
1289 | 1289 | continue; |
1290 | 1290 | } else { |
@@ -53,6 +53,8 @@ | ||
53 | 53 | __attribute__((nonnull)); |
54 | 54 | extern plist_T *pl_ensuremax(plist_T *list, size_t max) |
55 | 55 | __attribute__((nonnull)); |
56 | +static inline plist_T *pl_truncate(plist_T *list, size_t newlength) | |
57 | + __attribute__((nonnull)); | |
56 | 58 | extern plist_T *pl_clear(plist_T *list, void freer(void *elem)) |
57 | 59 | __attribute__((nonnull(1))); |
58 | 60 | extern plist_T *pl_replace( |
@@ -134,6 +136,20 @@ | ||
134 | 136 | return a; |
135 | 137 | } |
136 | 138 | |
139 | +/* Shrinks the length of the pointer list to `newlength'. | |
140 | + * `newlength' must not be larger than the current length. | |
141 | + * `maxlength' of the list is not changed. | |
142 | + * It's the caller's responsibility to free the objects pointed by the removed | |
143 | + * pointers. */ | |
144 | +plist_T *pl_truncate(plist_T *list, size_t newlength) | |
145 | +{ | |
146 | +#ifdef assert | |
147 | + assert(newlength <= list->length); | |
148 | +#endif | |
149 | + list->contents[list->length = newlength] = NULL; | |
150 | + return list; | |
151 | +} | |
152 | + | |
137 | 153 | /* Inserts the first `n' elements of array `a' at offset `i' in pointer list |
138 | 154 | * `list'. |
139 | 155 | * NULL elements in `a' are not treated specially. |