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...@@ -294,71 +294,75 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
294 }294 }
295 }295 }
296296
297 pub const Iterator = struct {297 pub const Iterator = BaseIterator(*Self, *T);
298 list: *Self,298 pub const ConstIterator = BaseIterator(*const Self, *const T);
299 index: usize,299 fn BaseIterator(comptime SelfType: type, comptime ElementPtr: type) type {
300 box_index: usize,300 return struct {
301 shelf_index: ShelfIndex,301 list: SelfType,
302 shelf_size: usize,302 index: usize,
303303 box_index: usize,
304 pub fn next(it: *Iterator) ?*T {304 shelf_index: ShelfIndex,
305 if (it.index >= it.list.len) return null;305 shelf_size: usize,
306 if (it.index < prealloc_item_count) {306
307 const ptr = &it.list.prealloc_segment[it.index];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];
308 it.index += 1;321 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;
310 it.box_index = 0;325 it.box_index = 0;
311 it.shelf_index = 0;326 it.shelf_size *= 2;
312 it.shelf_size = prealloc_item_count * 2;
313 }327 }
314 return ptr;328 return ptr;
315 }329 }
316330
317 const ptr = &it.list.dynamic_segments[it.shelf_index][it.box_index];331 pub fn prev(it: *@This()) ?ElementPtr {
318 it.index += 1;332 if (it.index == 0) return null;
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 }
327333
328 pub fn prev(it: *Iterator) ?*T {334 it.index -= 1;
329 if (it.index == 0) return null;335 if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];
330336
331 it.index -= 1;337 if (it.box_index == 0) {
332 if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];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) {345 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
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;
340 }346 }
341347
342 return &it.list.dynamic_segments[it.shelf_index][it.box_index];348 pub fn peek(it: *@This()) ?ElementPtr {
343 }349 if (it.index >= it.list.len)
344350 return null;
345 pub fn peek(it: *Iterator) ?*T {351 if (it.index < prealloc_item_count)
346 if (it.index >= it.list.len)352 return &it.list.prealloc_segment[it.index];
347 return null;
348 if (it.index < prealloc_item_count)
349 return &it.list.prealloc_segment[it.index];
350353
351 return &it.list.dynamic_segments[it.shelf_index][it.box_index];354 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
352 }355 }
353356
354 pub fn set(it: *Iterator, index: usize) void {357 pub fn set(it: *@This(), index: usize) void {
355 it.index = index;358 it.index = index;
356 if (index < prealloc_item_count) return;359 if (index < prealloc_item_count) return;
357 it.shelf_index = shelfIndex(index);360 it.shelf_index = shelfIndex(index);
358 it.box_index = boxIndex(index, it.shelf_index);361 it.box_index = boxIndex(index, it.shelf_index);
359 it.shelf_size = shelfSize(it.shelf_index);362 it.shelf_size = shelfSize(it.shelf_index);
360 }363 }
361 };364 };
365 }
362366
363 pub fn iterator(self: *Self, start_index: usize) Iterator {367 pub fn iterator(self: *Self, start_index: usize) Iterator {
364 var it = Iterator{368 var it = Iterator{
...@@ -371,10 +375,22 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -371,10 +375,22 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
371 it.set(start_index);375 it.set(start_index);
372 return it;376 return it;
373 }377 }
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 }
374 };390 };
375}391}
376392
377test "basic usage" {393test "SegmentedList basic usage" {
378 try testSegmentedList(0);394 try testSegmentedList(0);
379 try testSegmentedList(1);395 try testSegmentedList(1);
380 try testSegmentedList(2);396 try testSegmentedList(2);
...@@ -418,6 +434,20 @@ fn testSegmentedList(comptime prealloc: usize) !void {...@@ -418,6 +434,20 @@ fn testSegmentedList(comptime prealloc: usize) !void {
418 try testing.expect(x == 0);434 try testing.expect(x == 0);
419 }435 }
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
421 try testing.expect(list.pop().? == 100);451 try testing.expect(list.pop().? == 100);
422 try testing.expect(list.len == 99);452 try testing.expect(list.len == 99);
423453