| ... | @@ -1910,72 +1910,117 @@ test "byteSwapAllFields" { | ... | @@ -1910,72 +1910,117 @@ test "byteSwapAllFields" { |
| 1910 | }, s); | 1910 | }, s); |
| 1911 | } | 1911 | } |
| 1912 | | 1912 | |
| | 1913 | /// Deprecated: use `tokenizeAny`, `tokenizeFull`, or `tokenizeScalar` |
| | 1914 | pub const tokenize = tokenizeAny; |
| | 1915 | |
| 1913 | /// Returns an iterator that iterates over the slices of `buffer` that are not | 1916 | /// Returns an iterator that iterates over the slices of `buffer` that are not |
| 1914 | /// any of the bytes in `delimiter_bytes`. | 1917 | /// any of the items in `delimiters`. |
| 1915 | /// | 1918 | /// |
| 1916 | /// `tokenize(u8, " abc def ghi ", " ")` will return slices | 1919 | /// `tokenizeAny(u8, " abc|def || ghi ", " |")` will return slices |
| 1917 | /// for "abc", "def", "ghi", null, in that order. | 1920 | /// for "abc", "def", "ghi", null, in that order. |
| 1918 | /// | 1921 | /// |
| 1919 | /// If `buffer` is empty, the iterator will return null. | 1922 | /// If `buffer` is empty, the iterator will return null. |
| 1920 | /// If `delimiter_bytes` does not exist in buffer, | 1923 | /// If none of `delimiters` exist in buffer, |
| | 1924 | /// the iterator will return `buffer`, null, in that order. |
| | 1925 | /// |
| | 1926 | /// See also: `tokenizeFull`, `tokenizeScalar`, |
| | 1927 | /// `splitFull`,`splitAny`, `splitScalar`, |
| | 1928 | /// `splitBackwardsFull`, `splitBackwardsAny`, and `splitBackwardsScalar` |
| | 1929 | pub fn tokenizeAny(comptime T: type, buffer: []const T, delimiters: []const T) TokenIterator(T, .any) { |
| | 1930 | return .{ |
| | 1931 | .index = 0, |
| | 1932 | .buffer = buffer, |
| | 1933 | .delimiter = delimiters, |
| | 1934 | }; |
| | 1935 | } |
| | 1936 | |
| | 1937 | /// Returns an iterator that iterates over the slices of `buffer` that are not |
| | 1938 | /// the sequence in `delimiter`. |
| | 1939 | /// |
| | 1940 | /// `tokenizeFull(u8, "<>abc><def<><>ghi", "<>")` will return slices |
| | 1941 | /// for "abc><def", "ghi", null, in that order. |
| | 1942 | /// |
| | 1943 | /// If `buffer` is empty, the iterator will return null. |
| | 1944 | /// If `delimiter` does not exist in buffer, |
| 1921 | /// the iterator will return `buffer`, null, in that order. | 1945 | /// the iterator will return `buffer`, null, in that order. |
| | 1946 | /// The delimiter length must not be zero. |
| 1922 | /// | 1947 | /// |
| 1923 | /// See also: `split` and `splitBackwards`. | 1948 | /// See also: `tokenizeAny`, `tokenizeScalar`, |
| 1924 | pub fn tokenize(comptime T: type, buffer: []const T, delimiter_bytes: []const T) TokenIterator(T) { | 1949 | /// `splitFull`,`splitAny`, and `splitScalar` |
| | 1950 | /// `splitBackwardsFull`, `splitBackwardsAny`, and `splitBackwardsScalar` |
| | 1951 | pub fn tokenizeFull(comptime T: type, buffer: []const T, delimiter: []const T) TokenIterator(T, .full) { |
| | 1952 | assert(delimiter.len != 0); |
| 1925 | return .{ | 1953 | return .{ |
| 1926 | .index = 0, | 1954 | .index = 0, |
| 1927 | .buffer = buffer, | 1955 | .buffer = buffer, |
| 1928 | .delimiter_bytes = delimiter_bytes, | 1956 | .delimiter = delimiter, |
| 1929 | }; | 1957 | }; |
| 1930 | } | 1958 | } |
| 1931 | | 1959 | |
| 1932 | test "tokenize" { | 1960 | /// Returns an iterator that iterates over the slices of `buffer` that are not |
| 1933 | var it = tokenize(u8, " abc def ghi ", " "); | 1961 | /// `delimiter`. |
| | 1962 | /// |
| | 1963 | /// `tokenizeScalar(u8, " abc def ghi ", ' ')` will return slices |
| | 1964 | /// for "abc", "def", "ghi", null, in that order. |
| | 1965 | /// |
| | 1966 | /// If `buffer` is empty, the iterator will return null. |
| | 1967 | /// If `delimiter` does not exist in buffer, |
| | 1968 | /// the iterator will return `buffer`, null, in that order. |
| | 1969 | /// |
| | 1970 | /// See also: `tokenizeAny`, `tokenizeFull`, |
| | 1971 | /// `splitFull`,`splitAny`, and `splitScalar` |
| | 1972 | /// `splitBackwardsFull`, `splitBackwardsAny`, and `splitBackwardsScalar` |
| | 1973 | pub fn tokenizeScalar(comptime T: type, buffer: []const T, delimiter: T) TokenIterator(T, .scalar) { |
| | 1974 | return .{ |
| | 1975 | .index = 0, |
| | 1976 | .buffer = buffer, |
| | 1977 | .delimiter = delimiter, |
| | 1978 | }; |
| | 1979 | } |
| | 1980 | |
| | 1981 | test "tokenizeScalar" { |
| | 1982 | var it = tokenizeScalar(u8, " abc def ghi ", ' '); |
| 1934 | try testing.expect(eql(u8, it.next().?, "abc")); | 1983 | try testing.expect(eql(u8, it.next().?, "abc")); |
| 1935 | try testing.expect(eql(u8, it.peek().?, "def")); | 1984 | try testing.expect(eql(u8, it.peek().?, "def")); |
| 1936 | try testing.expect(eql(u8, it.next().?, "def")); | 1985 | try testing.expect(eql(u8, it.next().?, "def")); |
| 1937 | try testing.expect(eql(u8, it.next().?, "ghi")); | 1986 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| 1938 | try testing.expect(it.next() == null); | 1987 | try testing.expect(it.next() == null); |
| 1939 | | 1988 | |
| 1940 | it = tokenize(u8, "..\\bob", "\\"); | 1989 | it = tokenizeScalar(u8, "..\\bob", '\\'); |
| 1941 | try testing.expect(eql(u8, it.next().?, "..")); | 1990 | try testing.expect(eql(u8, it.next().?, "..")); |
| 1942 | try testing.expect(eql(u8, "..", "..\\bob"[0..it.index])); | 1991 | try testing.expect(eql(u8, "..", "..\\bob"[0..it.index])); |
| 1943 | try testing.expect(eql(u8, it.next().?, "bob")); | 1992 | try testing.expect(eql(u8, it.next().?, "bob")); |
| 1944 | try testing.expect(it.next() == null); | 1993 | try testing.expect(it.next() == null); |
| 1945 | | 1994 | |
| 1946 | it = tokenize(u8, "//a/b", "/"); | 1995 | it = tokenizeScalar(u8, "//a/b", '/'); |
| 1947 | try testing.expect(eql(u8, it.next().?, "a")); | 1996 | try testing.expect(eql(u8, it.next().?, "a")); |
| 1948 | try testing.expect(eql(u8, it.next().?, "b")); | 1997 | try testing.expect(eql(u8, it.next().?, "b")); |
| 1949 | try testing.expect(eql(u8, "//a/b", "//a/b"[0..it.index])); | 1998 | try testing.expect(eql(u8, "//a/b", "//a/b"[0..it.index])); |
| 1950 | try testing.expect(it.next() == null); | 1999 | try testing.expect(it.next() == null); |
| 1951 | | 2000 | |
| 1952 | it = tokenize(u8, "|", "|"); | 2001 | it = tokenizeScalar(u8, "|", '|'); |
| 1953 | try testing.expect(it.next() == null); | 2002 | try testing.expect(it.next() == null); |
| 1954 | try testing.expect(it.peek() == null); | 2003 | try testing.expect(it.peek() == null); |
| 1955 | | 2004 | |
| 1956 | it = tokenize(u8, "", "|"); | 2005 | it = tokenizeScalar(u8, "", '|'); |
| 1957 | try testing.expect(it.next() == null); | 2006 | try testing.expect(it.next() == null); |
| 1958 | try testing.expect(it.peek() == null); | 2007 | try testing.expect(it.peek() == null); |
| 1959 | | 2008 | |
| 1960 | it = tokenize(u8, "hello", ""); | 2009 | it = tokenizeScalar(u8, "hello", ' '); |
| 1961 | try testing.expect(eql(u8, it.next().?, "hello")); | | |
| 1962 | try testing.expect(it.next() == null); | | |
| 1963 | | | |
| 1964 | it = tokenize(u8, "hello", " "); | | |
| 1965 | try testing.expect(eql(u8, it.next().?, "hello")); | 2010 | try testing.expect(eql(u8, it.next().?, "hello")); |
| 1966 | try testing.expect(it.next() == null); | 2011 | try testing.expect(it.next() == null); |
| 1967 | | 2012 | |
| 1968 | var it16 = tokenize( | 2013 | var it16 = tokenizeScalar( |
| 1969 | u16, | 2014 | u16, |
| 1970 | std.unicode.utf8ToUtf16LeStringLiteral("hello"), | 2015 | std.unicode.utf8ToUtf16LeStringLiteral("hello"), |
| 1971 | std.unicode.utf8ToUtf16LeStringLiteral(" "), | 2016 | ' ', |
| 1972 | ); | 2017 | ); |
| 1973 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("hello"))); | 2018 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("hello"))); |
| 1974 | try testing.expect(it16.next() == null); | 2019 | try testing.expect(it16.next() == null); |
| 1975 | } | 2020 | } |
| 1976 | | 2021 | |
| 1977 | test "tokenize (multibyte)" { | 2022 | test "tokenizeAny (multibyte)" { |
| 1978 | var it = tokenize(u8, "a|b,c/d e", " /,|"); | 2023 | var it = tokenizeAny(u8, "a|b,c/d e", " /,|"); |
| 1979 | try testing.expect(eql(u8, it.next().?, "a")); | 2024 | try testing.expect(eql(u8, it.next().?, "a")); |
| 1980 | try testing.expect(eql(u8, it.peek().?, "b")); | 2025 | try testing.expect(eql(u8, it.peek().?, "b")); |
| 1981 | try testing.expect(eql(u8, it.next().?, "b")); | 2026 | try testing.expect(eql(u8, it.next().?, "b")); |
| ... | @@ -1985,7 +2030,11 @@ test "tokenize (multibyte)" { | ... | @@ -1985,7 +2030,11 @@ test "tokenize (multibyte)" { |
| 1985 | try testing.expect(it.next() == null); | 2030 | try testing.expect(it.next() == null); |
| 1986 | try testing.expect(it.peek() == null); | 2031 | try testing.expect(it.peek() == null); |
| 1987 | | 2032 | |
| 1988 | var it16 = tokenize( | 2033 | it = tokenizeAny(u8, "hello", ""); |
| | 2034 | try testing.expect(eql(u8, it.next().?, "hello")); |
| | 2035 | try testing.expect(it.next() == null); |
| | 2036 | |
| | 2037 | var it16 = tokenizeAny( |
| 1989 | u16, | 2038 | u16, |
| 1990 | std.unicode.utf8ToUtf16LeStringLiteral("a|b,c/d e"), | 2039 | std.unicode.utf8ToUtf16LeStringLiteral("a|b,c/d e"), |
| 1991 | std.unicode.utf8ToUtf16LeStringLiteral(" /,|"), | 2040 | std.unicode.utf8ToUtf16LeStringLiteral(" /,|"), |
| ... | @@ -1998,18 +2047,68 @@ test "tokenize (multibyte)" { | ... | @@ -1998,18 +2047,68 @@ test "tokenize (multibyte)" { |
| 1998 | try testing.expect(it16.next() == null); | 2047 | try testing.expect(it16.next() == null); |
| 1999 | } | 2048 | } |
| 2000 | | 2049 | |
| | 2050 | test "tokenizeFull" { |
| | 2051 | var it = tokenizeFull(u8, "a<>b<><>c><>d><", "<>"); |
| | 2052 | try testing.expectEqualStrings("a", it.next().?); |
| | 2053 | try testing.expectEqualStrings("b", it.peek().?); |
| | 2054 | try testing.expectEqualStrings("b", it.next().?); |
| | 2055 | try testing.expectEqualStrings("c>", it.next().?); |
| | 2056 | try testing.expectEqualStrings("d><", it.next().?); |
| | 2057 | try testing.expect(it.next() == null); |
| | 2058 | try testing.expect(it.peek() == null); |
| | 2059 | |
| | 2060 | var it16 = tokenizeFull( |
| | 2061 | u16, |
| | 2062 | std.unicode.utf8ToUtf16LeStringLiteral("a<>b<><>c><>d><"), |
| | 2063 | std.unicode.utf8ToUtf16LeStringLiteral("<>"), |
| | 2064 | ); |
| | 2065 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("a"))); |
| | 2066 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("b"))); |
| | 2067 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("c>"))); |
| | 2068 | try testing.expect(eql(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("d><"))); |
| | 2069 | try testing.expect(it16.next() == null); |
| | 2070 | } |
| | 2071 | |
| 2001 | test "tokenize (reset)" { | 2072 | test "tokenize (reset)" { |
| 2002 | var it = tokenize(u8, " abc def ghi ", " "); | 2073 | { |
| 2003 | try testing.expect(eql(u8, it.next().?, "abc")); | 2074 | var it = tokenizeAny(u8, " abc def ghi ", " "); |
| 2004 | try testing.expect(eql(u8, it.next().?, "def")); | 2075 | try testing.expect(eql(u8, it.next().?, "abc")); |
| 2005 | try testing.expect(eql(u8, it.next().?, "ghi")); | 2076 | try testing.expect(eql(u8, it.next().?, "def")); |
| | 2077 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| 2006 | | 2078 | |
| 2007 | it.reset(); | 2079 | it.reset(); |
| 2008 | | 2080 | |
| 2009 | try testing.expect(eql(u8, it.next().?, "abc")); | 2081 | try testing.expect(eql(u8, it.next().?, "abc")); |
| 2010 | try testing.expect(eql(u8, it.next().?, "def")); | 2082 | try testing.expect(eql(u8, it.next().?, "def")); |
| 2011 | try testing.expect(eql(u8, it.next().?, "ghi")); | 2083 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| 2012 | try testing.expect(it.next() == null); | 2084 | try testing.expect(it.next() == null); |
| | 2085 | } |
| | 2086 | { |
| | 2087 | var it = tokenizeFull(u8, "<><>abc<>def<><>ghi<>", "<>"); |
| | 2088 | try testing.expect(eql(u8, it.next().?, "abc")); |
| | 2089 | try testing.expect(eql(u8, it.next().?, "def")); |
| | 2090 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| | 2091 | |
| | 2092 | it.reset(); |
| | 2093 | |
| | 2094 | try testing.expect(eql(u8, it.next().?, "abc")); |
| | 2095 | try testing.expect(eql(u8, it.next().?, "def")); |
| | 2096 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| | 2097 | try testing.expect(it.next() == null); |
| | 2098 | } |
| | 2099 | { |
| | 2100 | var it = tokenizeScalar(u8, " abc def ghi ", ' '); |
| | 2101 | try testing.expect(eql(u8, it.next().?, "abc")); |
| | 2102 | try testing.expect(eql(u8, it.next().?, "def")); |
| | 2103 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| | 2104 | |
| | 2105 | it.reset(); |
| | 2106 | |
| | 2107 | try testing.expect(eql(u8, it.next().?, "abc")); |
| | 2108 | try testing.expect(eql(u8, it.next().?, "def")); |
| | 2109 | try testing.expect(eql(u8, it.next().?, "ghi")); |
| | 2110 | try testing.expect(it.next() == null); |
| | 2111 | } |
| 2013 | } | 2112 | } |
| 2014 | | 2113 | |
| 2015 | /// Deprecated: use `splitFull`, `splitAny`, or `splitScalar` | 2114 | /// Deprecated: use `splitFull`, `splitAny`, or `splitScalar` |
| ... | @@ -2026,8 +2125,8 @@ pub const split = splitFull; | ... | @@ -2026,8 +2125,8 @@ pub const split = splitFull; |
| 2026 | /// The delimiter length must not be zero. | 2125 | /// The delimiter length must not be zero. |
| 2027 | /// | 2126 | /// |
| 2028 | /// See also: `splitAny`, `splitScalar`, `splitBackwardsFull`, | 2127 | /// See also: `splitAny`, `splitScalar`, `splitBackwardsFull`, |
| 2029 | /// `splitBackwardsAny`,`splitBackwardsScalar`, and | 2128 | /// `splitBackwardsAny`,`splitBackwardsScalar`, |
| 2030 | /// `tokenize`. | 2129 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2031 | pub fn splitFull(comptime T: type, buffer: []const T, delimiter: []const T) SplitIterator(T, .full) { | 2130 | pub fn splitFull(comptime T: type, buffer: []const T, delimiter: []const T) SplitIterator(T, .full) { |
| 2032 | assert(delimiter.len != 0); | 2131 | assert(delimiter.len != 0); |
| 2033 | return .{ | 2132 | return .{ |
| ... | @@ -2047,8 +2146,8 @@ pub fn splitFull(comptime T: type, buffer: []const T, delimiter: []const T) Spli | ... | @@ -2047,8 +2146,8 @@ pub fn splitFull(comptime T: type, buffer: []const T, delimiter: []const T) Spli |
| 2047 | /// the iterator will return `buffer`, null, in that order. | 2146 | /// the iterator will return `buffer`, null, in that order. |
| 2048 | /// | 2147 | /// |
| 2049 | /// See also: `splitFull`, `splitScalar`, `splitBackwardsFull`, | 2148 | /// See also: `splitFull`, `splitScalar`, `splitBackwardsFull`, |
| 2050 | /// `splitBackwardsAny`,`splitBackwardsScalar`, and | 2149 | /// `splitBackwardsAny`,`splitBackwardsScalar`, |
| 2051 | /// `tokenize`. | 2150 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2052 | pub fn splitAny(comptime T: type, buffer: []const T, delimiters: []const T) SplitIterator(T, .any) { | 2151 | pub fn splitAny(comptime T: type, buffer: []const T, delimiters: []const T) SplitIterator(T, .any) { |
| 2053 | return .{ | 2152 | return .{ |
| 2054 | .index = 0, | 2153 | .index = 0, |
| ... | @@ -2067,8 +2166,8 @@ pub fn splitAny(comptime T: type, buffer: []const T, delimiters: []const T) Spli | ... | @@ -2067,8 +2166,8 @@ pub fn splitAny(comptime T: type, buffer: []const T, delimiters: []const T) Spli |
| 2067 | /// the iterator will return `buffer`, null, in that order. | 2166 | /// the iterator will return `buffer`, null, in that order. |
| 2068 | /// | 2167 | /// |
| 2069 | /// See also: `splitFull`, `splitAny`, `splitBackwardsFull`, | 2168 | /// See also: `splitFull`, `splitAny`, `splitBackwardsFull`, |
| 2070 | /// `splitBackwardsAny`,`splitBackwardsScalar`, and | 2169 | /// `splitBackwardsAny`,`splitBackwardsScalar`, |
| 2071 | /// `tokenize`. | 2170 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2072 | pub fn splitScalar(comptime T: type, buffer: []const T, delimiter: T) SplitIterator(T, .scalar) { | 2171 | pub fn splitScalar(comptime T: type, buffer: []const T, delimiter: T) SplitIterator(T, .scalar) { |
| 2073 | return .{ | 2172 | return .{ |
| 2074 | .index = 0, | 2173 | .index = 0, |
| ... | @@ -2224,8 +2323,8 @@ pub const splitBackwards = splitBackwardsFull; | ... | @@ -2224,8 +2323,8 @@ pub const splitBackwards = splitBackwardsFull; |
| 2224 | /// The delimiter length must not be zero. | 2323 | /// The delimiter length must not be zero. |
| 2225 | /// | 2324 | /// |
| 2226 | /// See also: `splitBackwardsAny`, `splitBackwardsScalar`, | 2325 | /// See also: `splitBackwardsAny`, `splitBackwardsScalar`, |
| 2227 | /// `splitFull`, `splitAny`,`splitScalar`, and | 2326 | /// `splitFull`, `splitAny`,`splitScalar`, |
| 2228 | /// `tokenize`. | 2327 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2229 | pub fn splitBackwardsFull(comptime T: type, buffer: []const T, delimiter: []const T) SplitBackwardsIterator(T, .full) { | 2328 | pub fn splitBackwardsFull(comptime T: type, buffer: []const T, delimiter: []const T) SplitBackwardsIterator(T, .full) { |
| 2230 | assert(delimiter.len != 0); | 2329 | assert(delimiter.len != 0); |
| 2231 | return .{ | 2330 | return .{ |
| ... | @@ -2245,8 +2344,8 @@ pub fn splitBackwardsFull(comptime T: type, buffer: []const T, delimiter: []cons | ... | @@ -2245,8 +2344,8 @@ pub fn splitBackwardsFull(comptime T: type, buffer: []const T, delimiter: []cons |
| 2245 | /// the iterator will return `buffer`, null, in that order. | 2344 | /// the iterator will return `buffer`, null, in that order. |
| 2246 | /// | 2345 | /// |
| 2247 | /// See also: `splitBackwardsFull`, `splitBackwardsScalar`, | 2346 | /// See also: `splitBackwardsFull`, `splitBackwardsScalar`, |
| 2248 | /// `splitFull`, `splitAny`,`splitScalar`, and | 2347 | /// `splitFull`, `splitAny`,`splitScalar`, |
| 2249 | /// `tokenize`. | 2348 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2250 | pub fn splitBackwardsAny(comptime T: type, buffer: []const T, delimiters: []const T) SplitBackwardsIterator(T, .any) { | 2349 | pub fn splitBackwardsAny(comptime T: type, buffer: []const T, delimiters: []const T) SplitBackwardsIterator(T, .any) { |
| 2251 | return .{ | 2350 | return .{ |
| 2252 | .index = buffer.len, | 2351 | .index = buffer.len, |
| ... | @@ -2265,8 +2364,8 @@ pub fn splitBackwardsAny(comptime T: type, buffer: []const T, delimiters: []cons | ... | @@ -2265,8 +2364,8 @@ pub fn splitBackwardsAny(comptime T: type, buffer: []const T, delimiters: []cons |
| 2265 | /// the iterator will return `buffer`, null, in that order. | 2364 | /// the iterator will return `buffer`, null, in that order. |
| 2266 | /// | 2365 | /// |
| 2267 | /// See also: `splitBackwardsFull`, `splitBackwardsAny`, | 2366 | /// See also: `splitBackwardsFull`, `splitBackwardsAny`, |
| 2268 | /// `splitFull`, `splitAny`,`splitScalar`, and | 2367 | /// `splitFull`, `splitAny`,`splitScalar`, |
| 2269 | /// `tokenize`. | 2368 | /// `tokenizeAny`, `tokenizeFull`, and `tokenizeScalar`. |
| 2270 | pub fn splitBackwardsScalar(comptime T: type, buffer: []const T, delimiter: T) SplitBackwardsIterator(T, .scalar) { | 2369 | pub fn splitBackwardsScalar(comptime T: type, buffer: []const T, delimiter: T) SplitBackwardsIterator(T, .scalar) { |
| 2271 | return .{ | 2370 | return .{ |
| 2272 | .index = buffer.len, | 2371 | .index = buffer.len, |
| ... | @@ -2596,10 +2695,13 @@ test "endsWith" { | ... | @@ -2596,10 +2695,13 @@ test "endsWith" { |
| 2596 | | 2695 | |
| 2597 | pub const DelimiterType = enum { full, any, scalar }; | 2696 | pub const DelimiterType = enum { full, any, scalar }; |
| 2598 | | 2697 | |
| 2599 | pub fn TokenIterator(comptime T: type) type { | 2698 | pub fn TokenIterator(comptime T: type, comptime delimiter_type: DelimiterType) type { |
| 2600 | return struct { | 2699 | return struct { |
| 2601 | buffer: []const T, | 2700 | buffer: []const T, |
| 2602 | delimiter_bytes: []const T, | 2701 | delimiter: switch (delimiter_type) { |
| | 2702 | .full, .any => []const T, |
| | 2703 | .scalar => T, |
| | 2704 | }, |
| 2603 | index: usize, | 2705 | index: usize, |
| 2604 | | 2706 | |
| 2605 | const Self = @This(); | 2707 | const Self = @This(); |
| ... | @@ -2616,7 +2718,10 @@ pub fn TokenIterator(comptime T: type) type { | ... | @@ -2616,7 +2718,10 @@ pub fn TokenIterator(comptime T: type) type { |
| 2616 | /// complete. Does not advance to the next token. | 2718 | /// complete. Does not advance to the next token. |
| 2617 | pub fn peek(self: *Self) ?[]const T { | 2719 | pub fn peek(self: *Self) ?[]const T { |
| 2618 | // move to beginning of token | 2720 | // move to beginning of token |
| 2619 | while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {} | 2721 | while (self.index < self.buffer.len and self.isDelimiter(self.index)) : (self.index += switch (delimiter_type) { |
| | 2722 | .full => self.delimiter.len, |
| | 2723 | .any, .scalar => 1, |
| | 2724 | }) {} |
| 2620 | const start = self.index; | 2725 | const start = self.index; |
| 2621 | if (start == self.buffer.len) { | 2726 | if (start == self.buffer.len) { |
| 2622 | return null; | 2727 | return null; |
| ... | @@ -2624,7 +2729,7 @@ pub fn TokenIterator(comptime T: type) type { | ... | @@ -2624,7 +2729,7 @@ pub fn TokenIterator(comptime T: type) type { |
| 2624 | | 2729 | |
| 2625 | // move to end of token | 2730 | // move to end of token |
| 2626 | var end = start; | 2731 | var end = start; |
| 2627 | while (end < self.buffer.len and !self.isSplitByte(self.buffer[end])) : (end += 1) {} | 2732 | while (end < self.buffer.len and !self.isDelimiter(end)) : (end += 1) {} |
| 2628 | | 2733 | |
| 2629 | return self.buffer[start..end]; | 2734 | return self.buffer[start..end]; |
| 2630 | } | 2735 | } |
| ... | @@ -2633,7 +2738,10 @@ pub fn TokenIterator(comptime T: type) type { | ... | @@ -2633,7 +2738,10 @@ pub fn TokenIterator(comptime T: type) type { |
| 2633 | pub fn rest(self: Self) []const T { | 2738 | pub fn rest(self: Self) []const T { |
| 2634 | // move to beginning of token | 2739 | // move to beginning of token |
| 2635 | var index: usize = self.index; | 2740 | var index: usize = self.index; |
| 2636 | while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {} | 2741 | while (index < self.buffer.len and self.isDelimiter(index)) : (index += switch (delimiter_type) { |
| | 2742 | .full => self.delimiter.len, |
| | 2743 | .any, .scalar => 1, |
| | 2744 | }) {} |
| 2637 | return self.buffer[index..]; | 2745 | return self.buffer[index..]; |
| 2638 | } | 2746 | } |
| 2639 | | 2747 | |
| ... | @@ -2642,13 +2750,20 @@ pub fn TokenIterator(comptime T: type) type { | ... | @@ -2642,13 +2750,20 @@ pub fn TokenIterator(comptime T: type) type { |
| 2642 | self.index = 0; | 2750 | self.index = 0; |
| 2643 | } | 2751 | } |
| 2644 | | 2752 | |
| 2645 | fn isSplitByte(self: Self, byte: T) bool { | 2753 | fn isDelimiter(self: Self, index: usize) bool { |
| 2646 | for (self.delimiter_bytes) |delimiter_byte| { | 2754 | switch (delimiter_type) { |
| 2647 | if (byte == delimiter_byte) { | 2755 | .full => return startsWith(T, self.buffer[index..], self.delimiter), |
| 2648 | return true; | 2756 | .any => { |
| 2649 | } | 2757 | const item = self.buffer[index]; |
| | 2758 | for (self.delimiter) |delimiter_item| { |
| | 2759 | if (item == delimiter_item) { |
| | 2760 | return true; |
| | 2761 | } |
| | 2762 | } |
| | 2763 | return false; |
| | 2764 | }, |
| | 2765 | .scalar => return self.buffer[index] == self.delimiter, |
| 2650 | } | 2766 | } |
| 2651 | return false; | | |
| 2652 | } | 2767 | } |
| 2653 | }; | 2768 | }; |
| 2654 | } | 2769 | } |