authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2020-03-30 21:56:09+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-30 11:04:58-04:00
log3be720a729e20720a033f2cf1958311a0112d1f4
tree548ff5bcf2c39a920279968dcd464a202bbe4f1d
parentc1cc1ebc35f7a56669db2f88b6d4ff8f1603ec59

std: mem span functions can take an optional pointer


1 files changed, 38 insertions(+), 14 deletions(-)

lib/std/mem.zig+38-14
...@@ -512,36 +512,54 @@ pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {...@@ -512,36 +512,54 @@ pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
512/// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated,512/// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated,
513/// and assumed to not allow null.513/// and assumed to not allow null.
514pub fn Span(comptime T: type) type {514pub fn Span(comptime T: type) type {
515 var ptr_info = @typeInfo(T).Pointer;515 switch(@typeInfo(T)) {
516 switch (ptr_info.size) {516 .Optional => |optional_info| {
517 .One => switch (@typeInfo(ptr_info.child)) {517 return ?Span(optional_info.child);
518 .Array => |info| {
519 ptr_info.child = info.child;
520 ptr_info.sentinel = info.sentinel;
521 },
522 else => @compileError("invalid type given to std.mem.Span"),
523 },518 },
524 .C => {519 .Pointer => |ptr_info| {
525 ptr_info.sentinel = 0;520 var new_ptr_info = ptr_info;
526 ptr_info.is_allowzero = false;521 switch (ptr_info.size) {
522 .One => switch (@typeInfo(ptr_info.child)) {
523 .Array => |info| {
524 new_ptr_info.child = info.child;
525 new_ptr_info.sentinel = info.sentinel;
526 },
527 else => @compileError("invalid type given to std.mem.Span"),
528 },
529 .C => {
530 new_ptr_info.sentinel = 0;
531 new_ptr_info.is_allowzero = false;
532 },
533 .Many, .Slice => {},
534 }
535 new_ptr_info.size = .Slice;
536 return @Type(std.builtin.TypeInfo{ .Pointer = new_ptr_info });
527 },537 },
528 .Many, .Slice => {},538 else => @compileError("invalid type given to std.mem.Span"),
529 }539 }
530 ptr_info.size = .Slice;
531 return @Type(std.builtin.TypeInfo{ .Pointer = ptr_info });
532}540}
533541
534test "Span" {542test "Span" {
535 testing.expect(Span(*[5]u16) == []u16);543 testing.expect(Span(*[5]u16) == []u16);
544 testing.expect(Span(?*[5]u16) == ?[]u16);
536 testing.expect(Span(*const [5]u16) == []const u16);545 testing.expect(Span(*const [5]u16) == []const u16);
546 testing.expect(Span(?*const [5]u16) == ?[]const u16);
537 testing.expect(Span([]u16) == []u16);547 testing.expect(Span([]u16) == []u16);
548 testing.expect(Span(?[]u16) == ?[]u16);
538 testing.expect(Span([]const u8) == []const u8);549 testing.expect(Span([]const u8) == []const u8);
550 testing.expect(Span(?[]const u8) == ?[]const u8);
539 testing.expect(Span([:1]u16) == [:1]u16);551 testing.expect(Span([:1]u16) == [:1]u16);
552 testing.expect(Span(?[:1]u16) == ?[:1]u16);
540 testing.expect(Span([:1]const u8) == [:1]const u8);553 testing.expect(Span([:1]const u8) == [:1]const u8);
554 testing.expect(Span(?[:1]const u8) == ?[:1]const u8);
541 testing.expect(Span([*:1]u16) == [:1]u16);555 testing.expect(Span([*:1]u16) == [:1]u16);
556 testing.expect(Span(?[*:1]u16) == ?[:1]u16);
542 testing.expect(Span([*:1]const u8) == [:1]const u8);557 testing.expect(Span([*:1]const u8) == [:1]const u8);
558 testing.expect(Span(?[*:1]const u8) == ?[:1]const u8);
543 testing.expect(Span([*c]u16) == [:0]u16);559 testing.expect(Span([*c]u16) == [:0]u16);
560 testing.expect(Span(?[*c]u16) == ?[:0]u16);
544 testing.expect(Span([*c]const u8) == [:0]const u8);561 testing.expect(Span([*c]const u8) == [:0]const u8);
562 testing.expect(Span(?[*c]const u8) == ?[:0]const u8);
545}563}
546564
547/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and565/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
...@@ -553,6 +571,9 @@ test "Span" {...@@ -553,6 +571,9 @@ test "Span" {
553/// length value is used instead of the sentinel.571/// length value is used instead of the sentinel.
554pub fn span(ptr: var) Span(@TypeOf(ptr)) {572pub fn span(ptr: var) Span(@TypeOf(ptr)) {
555 const Result = Span(@TypeOf(ptr));573 const Result = Span(@TypeOf(ptr));
574 if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) {
575 return null;
576 }
556 const l = len(ptr);577 const l = len(ptr);
557 if (@typeInfo(Result).Pointer.sentinel) |s| {578 if (@typeInfo(Result).Pointer.sentinel) |s| {
558 return ptr[0..l :s];579 return ptr[0..l :s];
...@@ -573,6 +594,9 @@ test "span" {...@@ -573,6 +594,9 @@ test "span" {
573/// rather than using the length.594/// rather than using the length.
574pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) {595pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) {
575 const Result = Span(@TypeOf(ptr));596 const Result = Span(@TypeOf(ptr));
597 if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) {
598 return null;
599 }
576 const l = lenZ(ptr);600 const l = lenZ(ptr);
577 if (@typeInfo(Result).Pointer.sentinel) |s| {601 if (@typeInfo(Result).Pointer.sentinel) |s| {
578 return ptr[0..l :s];602 return ptr[0..l :s];