| ... | @@ -333,8 +333,20 @@ pub fn zeroes(comptime T: type) T { | ... | @@ -333,8 +333,20 @@ pub fn zeroes(comptime T: type) T { |
| 333 | } | 333 | } |
| 334 | return array; | 334 | return array; |
| 335 | }, | 335 | }, |
| 336 | .Vector, .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => { | 336 | .Vector, |
| 337 | @compileError("Can't set a "++ @typeName(T) ++" to zero."); | 337 | .ErrorUnion, |
| | 338 | .ErrorSet, |
| | 339 | .Union, |
| | 340 | .Fn, |
| | 341 | .BoundFn, |
| | 342 | .Type, |
| | 343 | .NoReturn, |
| | 344 | .Undefined, |
| | 345 | .Opaque, |
| | 346 | .Frame, |
| | 347 | .AnyFrame, |
| | 348 | => { |
| | 349 | @compileError("Can't set a " ++ @typeName(T) ++ " to zero."); |
| 338 | }, | 350 | }, |
| 339 | } | 351 | } |
| 340 | } | 352 | } |
| ... | @@ -470,20 +482,122 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | ... | @@ -470,20 +482,122 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 470 | return true; | 482 | return true; |
| 471 | } | 483 | } |
| 472 | | 484 | |
| | 485 | /// Deprecated. Use `length` or `indexOfSentinel`. |
| 473 | pub fn len(comptime T: type, ptr: [*:0]const T) usize { | 486 | pub fn len(comptime T: type, ptr: [*:0]const T) usize { |
| 474 | var count: usize = 0; | 487 | var count: usize = 0; |
| 475 | while (ptr[count] != 0) : (count += 1) {} | 488 | while (ptr[count] != 0) : (count += 1) {} |
| 476 | return count; | 489 | return count; |
| 477 | } | 490 | } |
| 478 | | 491 | |
| | 492 | /// Deprecated. Use `span`. |
| 479 | pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T { | 493 | pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T { |
| 480 | return ptr[0..len(T, ptr) :0]; | 494 | return ptr[0..len(T, ptr) :0]; |
| 481 | } | 495 | } |
| 482 | | 496 | |
| | 497 | /// Deprecated. Use `span`. |
| 483 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { | 498 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { |
| 484 | return ptr[0..len(T, ptr) :0]; | 499 | return ptr[0..len(T, ptr) :0]; |
| 485 | } | 500 | } |
| 486 | | 501 | |
| | 502 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and |
| | 503 | /// returns a slice. If there is a sentinel on the input type, there will be a |
| | 504 | /// sentinel on the output type. The constness of the output type matches |
| | 505 | /// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated. |
| | 506 | pub fn Span(comptime T: type) type { |
| | 507 | var ptr_info = @typeInfo(T).Pointer; |
| | 508 | switch (ptr_info.size) { |
| | 509 | .One => switch (@typeInfo(ptr_info.child)) { |
| | 510 | .Array => |info| { |
| | 511 | ptr_info.child = info.child; |
| | 512 | ptr_info.sentinel = info.sentinel; |
| | 513 | }, |
| | 514 | else => @compileError("invalid type given to std.mem.Span"), |
| | 515 | }, |
| | 516 | .C => { |
| | 517 | ptr_info.sentinel = 0; |
| | 518 | }, |
| | 519 | .Many, .Slice => {}, |
| | 520 | } |
| | 521 | ptr_info.size = .Slice; |
| | 522 | return @Type(std.builtin.TypeInfo{ .Pointer = ptr_info }); |
| | 523 | } |
| | 524 | |
| | 525 | test "Span" { |
| | 526 | testing.expect(Span(*[5]u16) == []u16); |
| | 527 | testing.expect(Span(*const [5]u16) == []const u16); |
| | 528 | testing.expect(Span([]u16) == []u16); |
| | 529 | testing.expect(Span([]const u8) == []const u8); |
| | 530 | testing.expect(Span([:1]u16) == [:1]u16); |
| | 531 | testing.expect(Span([:1]const u8) == [:1]const u8); |
| | 532 | testing.expect(Span([*:1]u16) == [:1]u16); |
| | 533 | testing.expect(Span([*:1]const u8) == [:1]const u8); |
| | 534 | testing.expect(Span([*c]u16) == [:0]u16); |
| | 535 | testing.expect(Span([*c]const u8) == [:0]const u8); |
| | 536 | } |
| | 537 | |
| | 538 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and |
| | 539 | /// returns a slice. If there is a sentinel on the input type, there will be a |
| | 540 | /// sentinel on the output type. The constness of the output type matches |
| | 541 | /// the constness of the input type. |
| | 542 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| | 543 | const Result = Span(@TypeOf(ptr)); |
| | 544 | const l = length(ptr); |
| | 545 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| | 546 | return ptr[0..l :s]; |
| | 547 | } else { |
| | 548 | return ptr[0..l]; |
| | 549 | } |
| | 550 | } |
| | 551 | |
| | 552 | test "span" { |
| | 553 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| | 554 | const ptr = array[0..2 :3].ptr; |
| | 555 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); |
| | 556 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| | 557 | } |
| | 558 | |
| | 559 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |
| | 560 | /// or a slice, and returns the length. |
| | 561 | pub fn length(ptr: var) usize { |
| | 562 | return switch (@typeInfo(@TypeOf(ptr))) { |
| | 563 | .Array => |info| info.len, |
| | 564 | .Pointer => |info| switch (info.size) { |
| | 565 | .One => switch (@typeInfo(info.child)) { |
| | 566 | .Array => |x| x.len, |
| | 567 | else => @compileError("invalid type given to std.mem.length"), |
| | 568 | }, |
| | 569 | .Many => if (info.sentinel) |sentinel| |
| | 570 | indexOfSentinel(info.child, sentinel, ptr) |
| | 571 | else |
| | 572 | @compileError("length of pointer with no sentinel"), |
| | 573 | .C => indexOfSentinel(info.child, 0, ptr), |
| | 574 | .Slice => ptr.len, |
| | 575 | }, |
| | 576 | else => @compileError("invalid type given to std.mem.length"), |
| | 577 | }; |
| | 578 | } |
| | 579 | |
| | 580 | test "length" { |
| | 581 | testing.expect(length("aoeu") == 4); |
| | 582 | |
| | 583 | { |
| | 584 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| | 585 | testing.expect(length(&array) == 5); |
| | 586 | testing.expect(length(array[0..3]) == 3); |
| | 587 | array[2] = 0; |
| | 588 | const ptr = array[0..2 :0].ptr; |
| | 589 | testing.expect(length(ptr) == 2); |
| | 590 | } |
| | 591 | } |
| | 592 | |
| | 593 | pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize { |
| | 594 | var i: usize = 0; |
| | 595 | while (ptr[i] != sentinel) { |
| | 596 | i += 1; |
| | 597 | } |
| | 598 | return i; |
| | 599 | } |
| | 600 | |
| 487 | /// Returns true if all elements in a slice are equal to the scalar value provided | 601 | /// Returns true if all elements in a slice are equal to the scalar value provided |
| 488 | pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool { | 602 | pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool { |
| 489 | for (slice) |item| { | 603 | for (slice) |item| { |