| ... | @@ -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 | } |
| 296 | | 296 | |
| 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, |
| 303 | | 303 | 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 | } |
| 316 | | 330 | |
| 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 | } | | |
| 327 | | 333 | |
| 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]; |
| 330 | | 336 | |
| 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 | } |
| 333 | | 344 | |
| 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 | } |
| 341 | | 347 | |
| 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) |
| 344 | | 350 | 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]; | | |
| 350 | | 353 | |
| 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 | } |
| 353 | | 356 | |
| 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 | } |
| 362 | | 366 | |
| 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 | } |
| 376 | | 392 | |
| 377 | test "basic usage" { | 393 | test "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 | } |
| 420 | | 436 | |
| | 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); |
| 423 | | 453 | |