]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/csv: add Reader.InputOffset method
authorhopehook <hopehook.com@gmail.com>
Wed, 11 May 2022 14:42:00 +0000 (22:42 +0800)
committerGopher Robot <gobot@golang.org>
Sat, 14 May 2022 04:25:13 +0000 (04:25 +0000)
Fixes #43401.

Change-Id: I2498e77e41d845130d95012bc8623bfb29c0dda1
Reviewed-on: https://go-review.googlesource.com/c/go/+/405675
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
api/next/43401.txt [new file with mode: 0644]
src/encoding/csv/reader.go
src/encoding/csv/reader_test.go

diff --git a/api/next/43401.txt b/api/next/43401.txt
new file mode 100644 (file)
index 0000000..832e601
--- /dev/null
@@ -0,0 +1 @@
+pkg encoding/csv, method (*Reader) InputOffset() int64 #43401
index f860f4f25f546fa181cff2ff36e5ebba0dfca2e1..90a37e6074973bd83f22c226b46c505834c1b309 100644 (file)
@@ -149,6 +149,9 @@ type Reader struct {
        // numLine is the current line being read in the CSV file.
        numLine int
 
+       // offset is the input stream byte offset of the current reader position.
+       offset int64
+
        // rawBuffer is a line buffer only used by the readLine method.
        rawBuffer []byte
 
@@ -210,6 +213,13 @@ func (r *Reader) FieldPos(field int) (line, column int) {
        return p.line, p.col
 }
 
+// InputOffset returns the input stream byte offset of the current reader
+// position. The offset gives the location of the end of the most recently
+// read row and the beginning of the next row.
+func (r *Reader) InputOffset() int64 {
+       return r.offset
+}
+
 // pos holds the position of a field in the current line.
 type position struct {
        line, col int
@@ -247,14 +257,16 @@ func (r *Reader) readLine() ([]byte, error) {
                }
                line = r.rawBuffer
        }
-       if len(line) > 0 && err == io.EOF {
+       readSize := len(line)
+       if readSize > 0 && err == io.EOF {
                err = nil
                // For backwards compatibility, drop trailing \r before EOF.
-               if line[len(line)-1] == '\r' {
-                       line = line[:len(line)-1]
+               if line[readSize-1] == '\r' {
+                       line = line[:readSize-1]
                }
        }
        r.numLine++
+       r.offset += int64(readSize)
        // Normalize \r\n to \n on all input lines.
        if n := len(line); n >= 2 && line[n-2] == '\r' && line[n-1] == '\n' {
                line[n-2] = '\n'
index abe3fdfb394e226cc2daee4569dc9d386d26b17c..2e5d62330cd954cff2f1b9c85efbec039458ec26 100644 (file)
@@ -404,7 +404,7 @@ field"`,
 }}
 
 func TestRead(t *testing.T) {
-       newReader := func(tt readTest) (*Reader, [][][2]int, map[int][2]int) {
+       newReader := func(tt readTest) (*Reader, [][][2]int, map[int][2]int, string) {
                positions, errPositions, input := makePositions(tt.Input)
                r := NewReader(strings.NewReader(input))
 
@@ -420,12 +420,12 @@ func TestRead(t *testing.T) {
                r.LazyQuotes = tt.LazyQuotes
                r.TrimLeadingSpace = tt.TrimLeadingSpace
                r.ReuseRecord = tt.ReuseRecord
-               return r, positions, errPositions
+               return r, positions, errPositions, input
        }
 
        for _, tt := range readTests {
                t.Run(tt.Name, func(t *testing.T) {
-                       r, positions, errPositions := newReader(tt)
+                       r, positions, errPositions, input := newReader(tt)
                        out, err := r.ReadAll()
                        if wantErr := firstError(tt.Errors, positions, errPositions); wantErr != nil {
                                if !reflect.DeepEqual(err, wantErr) {
@@ -443,8 +443,15 @@ func TestRead(t *testing.T) {
                                }
                        }
 
+                       // Check input offset after call ReadAll()
+                       inputByteSize := len(input)
+                       inputOffset := r.InputOffset()
+                       if err == nil && int64(inputByteSize) != inputOffset {
+                               t.Errorf("wrong input offset after call ReadAll():\ngot:  %d\nwant: %d\ninput: %s", inputOffset, inputByteSize, input)
+                       }
+
                        // Check field and error positions.
-                       r, _, _ = newReader(tt)
+                       r, _, _, _ = newReader(tt)
                        for recNum := 0; ; recNum++ {
                                rec, err := r.Read()
                                var wantErr error