| ... | @@ -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 3 | 3019 | // 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()); |
| 3027 | | 3027 | |
| 3028 | // multibyte | 3028 | // 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 | } |
| 3037 | | 3037 | |
| 3038 | { | 3038 | { |
| 3039 | // chunk/split every 3 | 3039 | // 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 | } |
| 3046 | | 3046 | |
| 3047 | { | 3047 | { |
| 3048 | // pick even | 3048 | // 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 | } |
| 3056 | | 3063 | |
| 3057 | { | 3064 | { |
| 3058 | // empty | 3065 | // 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); | | |
| 3062 | | 3068 | |
| 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); | | |
| 3066 | | 3071 | |
| 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); | | |
| 3070 | | 3074 | |
| 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 | } |
| 3075 | | 3078 | |
| 3076 | { | 3079 | { |
| 3077 | // first | 3080 | // 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 | } |
| 3083 | | 3086 | |
| 3084 | { | 3087 | { |
| 3085 | // reset | 3088 | // 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()); |
| 3091 | | 3094 | |
| 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 | } |
| 3099 | | 3138 | |
| ... | @@ -3107,27 +3146,17 @@ pub fn WindowIterator(comptime T: type) type { | ... | @@ -3107,27 +3146,17 @@ pub fn WindowIterator(comptime T: type) type { |
| 3107 | | 3146 | |
| 3108 | const Self = @This(); | 3147 | const Self = @This(); |
| 3109 | | 3148 | |
| 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 | } |
| 3133 | | 3162 | |