| ... | ... | @@ -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 { |
| 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]; |
| 308 | 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 | 325 | it.box_index = 0; |
| 311 | | it.shelf_index = 0; |
| 312 | | it.shelf_size = prealloc_item_count * 2; |
| 326 | it.shelf_size *= 2; |
| 313 | 327 | } |
| 314 | 328 | return ptr; |
| 315 | 329 | } |
| 316 | 330 | |
| 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; |
| 327 | 333 | |
| 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]; |
| 330 | 336 | |
| 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 | } |
| 333 | 344 | |
| 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]; |
| 340 | 346 | } |
| 341 | 347 | |
| 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]; |
| 350 | 353 | |
| 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 | } |
| 353 | 356 | |
| 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 | } |
| 362 | 366 | |
| 363 | 367 | pub fn iterator(self: *Self, start_index: usize) Iterator { |
| 364 | 368 | var it = Iterator{ |
| ... | ... | @@ -371,10 +375,22 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 371 | 375 | it.set(start_index); |
| 372 | 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 | 394 | try testSegmentedList(0); |
| 379 | 395 | try testSegmentedList(1); |
| 380 | 396 | try testSegmentedList(2); |
| ... | ... | @@ -418,6 +434,20 @@ fn testSegmentedList(comptime prealloc: usize) !void { |
| 418 | 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 | 451 | try testing.expect(list.pop().? == 100); |
| 422 | 452 | try testing.expect(list.len == 99); |
| 423 | 453 | |