authorgravatar for unerr@noreply.codeberg.orgunerr <unerr@noreply.codeberg.org> 2025-12-11 21:21:23+05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-27 20:45:26+01:00
log2e73288e6302cc405b8fbb0c4c0667d089775c55
treeacdc629a7ed56dbf2c5dfaef51c082d5e98ff042
parent6bf9499c0c5566962b76a767667212e5e20544d6

Fix #30167: std.mem.window returns slices smaller or equal to size


1 files changed, 80 insertions(+), 51 deletions(-)

lib/std/mem.zig+80-51
...@@ -3007,7 +3007,7 @@ pub fn window(comptime T: type, buffer: []const T, size: usize, advance: usize)...@@ -3007,7 +3007,7 @@ pub fn window(comptime T: type, buffer: []const T, size: usize, advance: usize)
3007 assert(size != 0);3007 assert(size != 0);
3008 assert(advance != 0);3008 assert(advance != 0);
3009 return .{3009 return .{
3010 .index = 0,3010 .index = if (buffer.len > 0) 0 else null,
3011 .buffer = buffer,3011 .buffer = buffer,
3012 .size = size,3012 .size = size,
3013 .advance = advance,3013 .advance = advance,
...@@ -3018,82 +3018,121 @@ test window {...@@ -3018,82 +3018,121 @@ test window {
3018 {3018 {
3019 // moving average size 33019 // moving average size 3
3020 var it = window(u8, "abcdefg", 3, 1);3020 var it = window(u8, "abcdefg", 3, 1);
3021 try testing.expectEqualSlices(u8, it.next().?, "abc");3021 try testing.expectEqualSlices(u8, "abc", it.next().?);
3022 try testing.expectEqualSlices(u8, it.next().?, "bcd");3022 try testing.expectEqualSlices(u8, "bcd", it.next().?);
3023 try testing.expectEqualSlices(u8, it.next().?, "cde");3023 try testing.expectEqualSlices(u8, "cde", it.next().?);
3024 try testing.expectEqualSlices(u8, it.next().?, "def");3024 try testing.expectEqualSlices(u8, "def", it.next().?);
3025 try testing.expectEqualSlices(u8, it.next().?, "efg");3025 try testing.expectEqualSlices(u8, "efg", it.next().?);
3026 try testing.expectEqual(it.next(), null);3026 try testing.expectEqual(null, it.next());
30273027
3028 // multibyte3028 // multibyte
3029 var it16 = window(u16, std.unicode.utf8ToUtf16LeStringLiteral("abcdefg"), 3, 1);3029 var it16 = window(u16, std.unicode.utf8ToUtf16LeStringLiteral("abcdefg"), 3, 1);
3030 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("abc"));3030 try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("abc"), it16.next().?);
3031 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("bcd"));3031 try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("bcd"), it16.next().?);
3032 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("cde"));3032 try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("cde"), it16.next().?);
3033 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("def"));3033 try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("def"), it16.next().?);
3034 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("efg"));3034 try testing.expectEqualSlices(u16, std.unicode.utf8ToUtf16LeStringLiteral("efg"), it16.next().?);
3035 try testing.expectEqual(it16.next(), null);3035 try testing.expectEqual(it16.next(), null);
3036 }3036 }
30373037
3038 {3038 {
3039 // chunk/split every 33039 // chunk/split every 3
3040 var it = window(u8, "abcdefg", 3, 3);3040 var it = window(u8, "abcdefg", 3, 3);
3041 try testing.expectEqualSlices(u8, it.next().?, "abc");3041 try testing.expectEqualSlices(u8, "abc", it.next().?);
3042 try testing.expectEqualSlices(u8, it.next().?, "def");3042 try testing.expectEqualSlices(u8, "def", it.next().?);
3043 try testing.expectEqualSlices(u8, it.next().?, "g");3043 try testing.expectEqualSlices(u8, "g", it.next().?);
3044 try testing.expectEqual(it.next(), null);3044 try testing.expectEqual(null, it.next());
3045 }3045 }
30463046
3047 {3047 {
3048 // pick even3048 // pick even
3049 var it = window(u8, "abcdefg", 1, 2);3049 var it = window(u8, "abcdefg", 1, 2);
3050 try testing.expectEqualSlices(u8, it.next().?, "a");3050 try testing.expectEqualSlices(u8, "a", it.next().?);
3051 try testing.expectEqualSlices(u8, it.next().?, "c");3051 try testing.expectEqualSlices(u8, "c", it.next().?);
3052 try testing.expectEqualSlices(u8, it.next().?, "e");3052 try testing.expectEqualSlices(u8, "e", it.next().?);
3053 try testing.expectEqualSlices(u8, it.next().?, "g");3053 try testing.expectEqualSlices(u8, "g", it.next().?);
3054 try testing.expectEqual(it.next(), null);3054 try testing.expectEqual(null, it.next());
3055
3056 it = window(u8, "abcdefgh", 1, 2);
3057 try testing.expectEqualSlices(u8, "a", it.next().?);
3058 try testing.expectEqualSlices(u8, "c", it.next().?);
3059 try testing.expectEqualSlices(u8, "e", it.next().?);
3060 try testing.expectEqualSlices(u8, "g", it.next().?);
3061 try testing.expectEqual(null, it.next());
3055 }3062 }
30563063
3057 {3064 {
3058 // empty3065 // empty
3059 var it = window(u8, "", 1, 1);3066 var it = window(u8, "", 1, 1);
3060 try testing.expectEqualSlices(u8, it.next().?, "");3067 try testing.expectEqual(null, it.next());
3061 try testing.expectEqual(it.next(), null);
30623068
3063 it = window(u8, "", 10, 1);3069 it = window(u8, "", 10, 1);
3064 try testing.expectEqualSlices(u8, it.next().?, "");3070 try testing.expectEqual(null, it.next());
3065 try testing.expectEqual(it.next(), null);
30663071
3067 it = window(u8, "", 1, 10);3072 it = window(u8, "", 1, 10);
3068 try testing.expectEqualSlices(u8, it.next().?, "");3073 try testing.expectEqual(null, it.next());
3069 try testing.expectEqual(it.next(), null);
30703074
3071 it = window(u8, "", 10, 10);3075 it = window(u8, "", 10, 10);
3072 try testing.expectEqualSlices(u8, it.next().?, "");3076 try testing.expectEqual(null, it.next());
3073 try testing.expectEqual(it.next(), null);
3074 }3077 }
30753078
3076 {3079 {
3077 // first3080 // first
3078 var it = window(u8, "abcdefg", 3, 3);3081 var it = window(u8, "abcdefg", 3, 3);
3079 try testing.expectEqualSlices(u8, it.first(), "abc");3082 try testing.expectEqualSlices(u8, "abc", it.next().?);
3080 it.reset();3083 it.reset();
3081 try testing.expectEqualSlices(u8, it.next().?, "abc");3084 try testing.expectEqualSlices(u8, "abc", it.next().?);
3082 }3085 }
30833086
3084 {3087 {
3085 // reset3088 // reset
3086 var it = window(u8, "abcdefg", 3, 3);3089 var it = window(u8, "abcdefg", 3, 3);
3087 try testing.expectEqualSlices(u8, it.next().?, "abc");3090 try testing.expectEqualSlices(u8, "abc", it.next().?);
3088 try testing.expectEqualSlices(u8, it.next().?, "def");3091 try testing.expectEqualSlices(u8, "def", it.next().?);
3089 try testing.expectEqualSlices(u8, it.next().?, "g");3092 try testing.expectEqualSlices(u8, "g", it.next().?);
3090 try testing.expectEqual(it.next(), null);3093 try testing.expectEqual(null, it.next());
30913094
3092 it.reset();3095 it.reset();
3093 try testing.expectEqualSlices(u8, it.next().?, "abc");3096 try testing.expectEqualSlices(u8, "abc", it.next().?);
3094 try testing.expectEqualSlices(u8, it.next().?, "def");3097 try testing.expectEqualSlices(u8, "def", it.next().?);
3095 try testing.expectEqualSlices(u8, it.next().?, "g");3098 try testing.expectEqualSlices(u8, "g", it.next().?);
3096 try testing.expectEqual(it.next(), null);3099 try testing.expectEqual(null, it.next());
3100 }
3101
3102 {
3103 // size > buffer.len
3104 var it = window(u8, "abcdefg", 100, 1);
3105 try testing.expectEqualSlices(u8, "abcdefg", it.next().?);
3106 try testing.expectEqual(null, it.next());
3107 }
3108
3109 {
3110 // advance >= buffer.len
3111 var it = window(u8, "abcdefg", 1, 7);
3112 try testing.expectEqualSlices(u8, "a", it.next().?);
3113 try testing.expectEqual(null, it.next());
3114 }
3115
3116 {
3117 // advance == 1 and size == 1
3118 var it = window(u8, "abcdefg", 1, 1);
3119 try testing.expectEqualSlices(u8, "a", it.next().?);
3120 try testing.expectEqualSlices(u8, "b", it.next().?);
3121 try testing.expectEqualSlices(u8, "c", it.next().?);
3122 try testing.expectEqualSlices(u8, "d", it.next().?);
3123 try testing.expectEqualSlices(u8, "e", it.next().?);
3124 try testing.expectEqualSlices(u8, "f", it.next().?);
3125 try testing.expectEqualSlices(u8, "g", it.next().?);
3126 try testing.expectEqual(null, it.next());
3127 }
3128
3129 {
3130 // advance > size
3131 var it = window(u8, "abcdefg", 2, 3);
3132 try testing.expectEqualSlices(u8, "ab", it.next().?);
3133 try testing.expectEqualSlices(u8, "de", it.next().?);
3134 try testing.expectEqualSlices(u8, "g", it.next().?);
3135 try testing.expectEqual(null, it.next());
3097 }3136 }
3098}3137}
30993138
...@@ -3107,27 +3146,17 @@ pub fn WindowIterator(comptime T: type) type {...@@ -3107,27 +3146,17 @@ pub fn WindowIterator(comptime T: type) type {
31073146
3108 const Self = @This();3147 const Self = @This();
31093148
3110 /// Returns a slice of the first window.
3111 /// Call this only to get the first window and then use `next` to get
3112 /// all subsequent windows.
3113 /// Asserts that iteration has not begun.
3114 pub fn first(self: *Self) []const T {
3115 assert(self.index.? == 0);
3116 return self.next().?;
3117 }
3118
3119 /// Returns a slice of the next window, or null if window is at end.3149 /// Returns a slice of the next window, or null if window is at end.
3120 pub fn next(self: *Self) ?[]const T {3150 pub fn next(self: *Self) ?[]const T {
3121 const start = self.index orelse return null;3151 const start = self.index orelse return null;
3122 const next_index = start + self.advance;3152 const next_index = start + self.advance;
3123 const end = if (start + self.size < self.buffer.len and next_index < self.buffer.len) blk: {3153 const end = if (start + self.size < self.buffer.len) blk: {
3124 self.index = next_index;3154 self.index = if (next_index < self.buffer.len) next_index else null;
3125 break :blk start + self.size;3155 break :blk start + self.size;
3126 } else blk: {3156 } else blk: {
3127 self.index = null;3157 self.index = null;
3128 break :blk self.buffer.len;3158 break :blk self.buffer.len;
3129 };3159 };
3130
3131 return self.buffer[start..end];3160 return self.buffer[start..end];
3132 }3161 }
31333162