summaryrefslogtreecommitdiffstats
path: root/pkg/utils/lines.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/utils/lines.go')
-rw-r--r--pkg/utils/lines.go59
1 files changed, 58 insertions, 1 deletions
diff --git a/pkg/utils/lines.go b/pkg/utils/lines.go
index 662ba2f9b..c70d02ffc 100644
--- a/pkg/utils/lines.go
+++ b/pkg/utils/lines.go
@@ -1,6 +1,9 @@
package utils
-import "strings"
+import (
+ "bytes"
+ "strings"
+)
// SplitLines takes a multiline string and splits it on newlines
// currently we are also stripping \r's which may have adverse effects for
@@ -43,3 +46,57 @@ func EscapeSpecialChars(str string) string {
"\v", "\\v",
).Replace(str)
}
+
+func dropCR(data []byte) []byte {
+ if len(data) > 0 && data[len(data)-1] == '\r' {
+ return data[0 : len(data)-1]
+ }
+ return data
+}
+
+// ScanLinesAndTruncateWhenLongerThanBuffer returns a split function that can be
+// used with bufio.Scanner.Split(). It is very similar to bufio.ScanLines,
+// except that it will truncate lines that are longer than the scanner's read
+// buffer (whereas bufio.ScanLines will return an error in that case, which is
+// often difficult to handle).
+//
+// If you are using your own buffer for the scanner, you must set maxBufferSize
+// to the same value as the max parameter that you passed to scanner.Buffer().
+// Otherwise, maxBufferSize must be set to bufio.MaxScanTokenSize.
+func ScanLinesAndTruncateWhenLongerThanBuffer(maxBufferSize int) func(data []byte, atEOF bool) (int, []byte, error) {
+ skipOverRemainderOfLongLine := false
+
+ return func(data []byte, atEOF bool) (int, []byte, error) {
+ if atEOF && len(data) == 0 {
+ // Done
+ return 0, nil, nil
+ }
+ if i := bytes.IndexByte(data, '\n'); i >= 0 {
+ if skipOverRemainderOfLongLine {
+ skipOverRemainderOfLongLine = false
+ return i + 1, nil, nil
+ }
+ return i + 1, dropCR(data[0:i]), nil
+ }
+ if atEOF {
+ if skipOverRemainderOfLongLine {
+ return len(data), nil, nil
+ }
+
+ return len(data), dropCR(data), nil
+ }
+
+ // Buffer is full, so we can't get more data
+ if len(data) >= maxBufferSize {
+ if skipOverRemainderOfLongLine {
+ return len(data), nil, nil
+ }
+
+ skipOverRemainderOfLongLine = true
+ return len(data), data, nil
+ }
+
+ // Request more data.
+ return 0, nil, nil
+ }
+}