Delete a range of elements from the quicklist. * * elements may span across multiple quicklistNodes, so we * have to be careful about tracking where we start and end. * * Returns 1 if entries were deleted, 0 if nothing was deleted. */
| 980 | * |
| 981 | * Returns 1 if entries were deleted, 0 if nothing was deleted. */ |
| 982 | int quicklistDelRange(quicklist *quicklist, const long start, |
| 983 | const long count) { |
| 984 | if (count <= 0) |
| 985 | return 0; |
| 986 | |
| 987 | unsigned long extent = count; /* range is inclusive of start position */ |
| 988 | |
| 989 | if (start >= 0 && extent > (quicklist->count - start)) { |
| 990 | /* if requesting delete more elements than exist, limit to list size. */ |
| 991 | extent = quicklist->count - start; |
| 992 | } else if (start < 0 && extent > (unsigned long)(-start)) { |
| 993 | /* else, if at negative offset, limit max size to rest of list. */ |
| 994 | extent = -start; /* c.f. LREM -29 29; just delete until end. */ |
| 995 | } |
| 996 | |
| 997 | quicklistEntry entry; |
| 998 | if (!quicklistIndex(quicklist, start, &entry)) |
| 999 | return 0; |
| 1000 | |
| 1001 | D("Quicklist delete request for start %ld, count %ld, extent: %ld", start, |
| 1002 | count, extent); |
| 1003 | quicklistNode *node = entry.node; |
| 1004 | |
| 1005 | /* iterate over next nodes until everything is deleted. */ |
| 1006 | while (extent) { |
| 1007 | quicklistNode *next = node->next; |
| 1008 | |
| 1009 | unsigned long del; |
| 1010 | int delete_entire_node = 0; |
| 1011 | if (entry.offset == 0 && extent >= node->count) { |
| 1012 | /* If we are deleting more than the count of this node, we |
| 1013 | * can just delete the entire node without ziplist math. */ |
| 1014 | delete_entire_node = 1; |
| 1015 | del = node->count; |
| 1016 | } else if (entry.offset >= 0 && extent + entry.offset >= node->count) { |
| 1017 | /* If deleting more nodes after this one, calculate delete based |
| 1018 | * on size of current node. */ |
| 1019 | del = node->count - entry.offset; |
| 1020 | } else if (entry.offset < 0) { |
| 1021 | /* If offset is negative, we are in the first run of this loop |
| 1022 | * and we are deleting the entire range |
| 1023 | * from this start offset to end of list. Since the Negative |
| 1024 | * offset is the number of elements until the tail of the list, |
| 1025 | * just use it directly as the deletion count. */ |
| 1026 | del = -entry.offset; |
| 1027 | |
| 1028 | /* If the positive offset is greater than the remaining extent, |
| 1029 | * we only delete the remaining extent, not the entire offset. |
| 1030 | */ |
| 1031 | if (del > extent) |
| 1032 | del = extent; |
| 1033 | } else { |
| 1034 | /* else, we are deleting less than the extent of this node, so |
| 1035 | * use extent directly. */ |
| 1036 | del = extent; |
| 1037 | } |
| 1038 | |
| 1039 | D("[%ld]: asking to del: %ld because offset: %d; (ENTIRE NODE: %d), " |
no test coverage detected