authorgravatar for natanalt@protonmail.comNatalia Cholewa <natanalt@protonmail.com> 2022-04-24 19:09:10+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-29 14:48:49-04:00
log0e49142ce478c13f3ec701900cd894b3536471a1
treedf820565adcb1039af5754d4df0bc183d8259ac8
parent3b8187072fc76966da9d9ab1a6a0ecd7aff4e090

std.SegmentedList: add constIterator


1 files changed, 83 insertions(+), 53 deletions(-)

lib/std/segmented_list.zig+83-53
......@@ -294,71 +294,75 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
294294 }
295295 }
296296
297 pub const Iterator = struct {
298 list: *Self,
299 index: usize,
300 box_index: usize,
301 shelf_index: ShelfIndex,
302 shelf_size: usize,
303
304 pub fn next(it: *Iterator) ?*T {
305 if (it.index >= it.list.len) return null;
306 if (it.index < prealloc_item_count) {
307 const ptr = &it.list.prealloc_segment[it.index];
297 pub const Iterator = BaseIterator(*Self, *T);
298 pub const ConstIterator = BaseIterator(*const Self, *const T);
299 fn BaseIterator(comptime SelfType: type, comptime ElementPtr: type) type {
300 return struct {
301 list: SelfType,
302 index: usize,
303 box_index: usize,
304 shelf_index: ShelfIndex,
305 shelf_size: usize,
306
307 pub fn next(it: *@This()) ?ElementPtr {
308 if (it.index >= it.list.len) return null;
309 if (it.index < prealloc_item_count) {
310 const ptr = &it.list.prealloc_segment[it.index];
311 it.index += 1;
312 if (it.index == prealloc_item_count) {
313 it.box_index = 0;
314 it.shelf_index = 0;
315 it.shelf_size = prealloc_item_count * 2;
316 }
317 return ptr;
318 }
319
320 const ptr = &it.list.dynamic_segments[it.shelf_index][it.box_index];
308321 it.index += 1;
309 if (it.index == prealloc_item_count) {
322 it.box_index += 1;
323 if (it.box_index == it.shelf_size) {
324 it.shelf_index += 1;
310325 it.box_index = 0;
311 it.shelf_index = 0;
312 it.shelf_size = prealloc_item_count * 2;
326 it.shelf_size *= 2;
313327 }
314328 return ptr;
315329 }
316330
317 const ptr = &it.list.dynamic_segments[it.shelf_index][it.box_index];
318 it.index += 1;
319 it.box_index += 1;
320 if (it.box_index == it.shelf_size) {
321 it.shelf_index += 1;
322 it.box_index = 0;
323 it.shelf_size *= 2;
324 }
325 return ptr;
326 }
331 pub fn prev(it: *@This()) ?ElementPtr {
332 if (it.index == 0) return null;
327333
328 pub fn prev(it: *Iterator) ?*T {
329 if (it.index == 0) return null;
334 it.index -= 1;
335 if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];
330336
331 it.index -= 1;
332 if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];
337 if (it.box_index == 0) {
338 it.shelf_index -= 1;
339 it.shelf_size /= 2;
340 it.box_index = it.shelf_size - 1;
341 } else {
342 it.box_index -= 1;
343 }
333344
334 if (it.box_index == 0) {
335 it.shelf_index -= 1;
336 it.shelf_size /= 2;
337 it.box_index = it.shelf_size - 1;
338 } else {
339 it.box_index -= 1;
345 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
340346 }
341347
342 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
343 }
344
345 pub fn peek(it: *Iterator) ?*T {
346 if (it.index >= it.list.len)
347 return null;
348 if (it.index < prealloc_item_count)
349 return &it.list.prealloc_segment[it.index];
348 pub fn peek(it: *@This()) ?ElementPtr {
349 if (it.index >= it.list.len)
350 return null;
351 if (it.index < prealloc_item_count)
352 return &it.list.prealloc_segment[it.index];
350353
351 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
352 }
354 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
355 }
353356
354 pub fn set(it: *Iterator, index: usize) void {
355 it.index = index;
356 if (index < prealloc_item_count) return;
357 it.shelf_index = shelfIndex(index);
358 it.box_index = boxIndex(index, it.shelf_index);
359 it.shelf_size = shelfSize(it.shelf_index);
360 }
361 };
357 pub fn set(it: *@This(), index: usize) void {
358 it.index = index;
359 if (index < prealloc_item_count) return;
360 it.shelf_index = shelfIndex(index);
361 it.box_index = boxIndex(index, it.shelf_index);
362 it.shelf_size = shelfSize(it.shelf_index);
363 }
364 };
365 }
362366
363367 pub fn iterator(self: *Self, start_index: usize) Iterator {
364368 var it = Iterator{
......@@ -371,10 +375,22 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
371375 it.set(start_index);
372376 return it;
373377 }
378
379 pub fn constIterator(self: *const Self, start_index: usize) ConstIterator {
380 var it = ConstIterator{
381 .list = self,
382 .index = undefined,
383 .shelf_index = undefined,
384 .box_index = undefined,
385 .shelf_size = undefined,
386 };
387 it.set(start_index);
388 return it;
389 }
374390 };
375391}
376392
377test "basic usage" {
393test "SegmentedList basic usage" {
378394 try testSegmentedList(0);
379395 try testSegmentedList(1);
380396 try testSegmentedList(2);
......@@ -418,6 +434,20 @@ fn testSegmentedList(comptime prealloc: usize) !void {
418434 try testing.expect(x == 0);
419435 }
420436
437 {
438 var it = list.constIterator(0);
439 var x: i32 = 0;
440 while (it.next()) |item| {
441 x += 1;
442 try testing.expect(item.* == x);
443 }
444 try testing.expect(x == 100);
445 while (it.prev()) |item| : (x -= 1) {
446 try testing.expect(item.* == x);
447 }
448 try testing.expect(x == 0);
449 }
450
421451 try testing.expect(list.pop().? == 100);
422452 try testing.expect(list.len == 99);
423453