1 // Copyright 2024 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package bytes
6 7 import (
8 "iter"
9 "unicode"
10 "unicode/utf8"
11 )
12 13 // Lines returns an iterator over the newline-terminated lines in the byte slice s.
14 // The lines yielded by the iterator include their terminating newlines.
15 // If s is empty, the iterator yields no lines at all.
16 // If s does not end in a newline, the final yielded line will not end in a newline.
17 // It returns a single-use iterator.
18 func Lines(s []byte) iter.Seq[[]byte] {
19 return func(yield func([]byte) bool) {
20 for len(s) > 0 {
21 var line []byte
22 if i := IndexByte(s, '\n'); i >= 0 {
23 line, s = s[:i+1], s[i+1:]
24 } else {
25 line, s = s, nil
26 }
27 if !yield(line[:len(line):len(line)]) {
28 return
29 }
30 }
31 }
32 }
33 34 // splitSeq is SplitSeq or SplitAfterSeq, configured by how many
35 // bytes of sep to include in the results (none or all).
36 func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] {
37 return func(yield func([]byte) bool) {
38 if len(sep) == 0 {
39 for len(s) > 0 {
40 _, size := utf8.DecodeRune(s)
41 if !yield(s[:size:size]) {
42 return
43 }
44 s = s[size:]
45 }
46 return
47 }
48 for {
49 i := Index(s, sep)
50 if i < 0 {
51 break
52 }
53 frag := s[:i+sepSave]
54 if !yield(frag[:len(frag):len(frag)]) {
55 return
56 }
57 s = s[i+len(sep):]
58 }
59 yield(s[:len(s):len(s)])
60 }
61 }
62 63 // SplitSeq returns an iterator over all subslices of s separated by sep.
64 // The iterator yields the same subslices that would be returned by [Split](s, sep),
65 // but without constructing a new slice containing the subslices.
66 // It returns a single-use iterator.
67 func SplitSeq(s, sep []byte) iter.Seq[[]byte] {
68 return splitSeq(s, sep, 0)
69 }
70 71 // SplitAfterSeq returns an iterator over subslices of s split after each instance of sep.
72 // The iterator yields the same subslices that would be returned by [SplitAfter](s, sep),
73 // but without constructing a new slice containing the subslices.
74 // It returns a single-use iterator.
75 func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] {
76 return splitSeq(s, sep, len(sep))
77 }
78 79 // FieldsSeq returns an iterator over subslices of s split around runs of
80 // whitespace characters, as defined by [unicode.IsSpace].
81 // The iterator yields the same subslices that would be returned by [Fields](s),
82 // but without constructing a new slice containing the subslices.
83 func FieldsSeq(s []byte) iter.Seq[[]byte] {
84 return func(yield func([]byte) bool) {
85 start := -1
86 for i := 0; i < len(s); {
87 size := 1
88 r := rune(s[i])
89 isSpace := asciiSpace[s[i]] != 0
90 if r >= utf8.RuneSelf {
91 r, size = utf8.DecodeRune(s[i:])
92 isSpace = unicode.IsSpace(r)
93 }
94 if isSpace {
95 if start >= 0 {
96 if !yield(s[start:i:i]) {
97 return
98 }
99 start = -1
100 }
101 } else if start < 0 {
102 start = i
103 }
104 i += size
105 }
106 if start >= 0 {
107 yield(s[start:len(s):len(s)])
108 }
109 }
110 }
111 112 // FieldsFuncSeq returns an iterator over subslices of s split around runs of
113 // Unicode code points satisfying f(c).
114 // The iterator yields the same subslices that would be returned by [FieldsFunc](s),
115 // but without constructing a new slice containing the subslices.
116 func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
117 return func(yield func([]byte) bool) {
118 start := -1
119 for i := 0; i < len(s); {
120 size := 1
121 r := rune(s[i])
122 if r >= utf8.RuneSelf {
123 r, size = utf8.DecodeRune(s[i:])
124 }
125 if f(r) {
126 if start >= 0 {
127 if !yield(s[start:i:i]) {
128 return
129 }
130 start = -1
131 }
132 } else if start < 0 {
133 start = i
134 }
135 i += size
136 }
137 if start >= 0 {
138 yield(s[start:len(s):len(s)])
139 }
140 }
141 }
142