]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/xml: expose decoder line and column
authorPatrick Gundlach <gundlach@speedata.de>
Mon, 19 Apr 2021 10:51:04 +0000 (12:51 +0200)
committerEmmanuel Odeke <emmanuel@orijtech.com>
Sun, 27 Mar 2022 20:26:46 +0000 (20:26 +0000)
The existing implementation of the xml decoder uses the line number
only for reporting syntax errors. The line number of the last read
token and the column within the line is useful for the users even
in non-error conditions.

Fixes #45628

Change-Id: I37b5033ff5ff8411793d8f5180f96aa4537e83f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/311270
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>

api/next/45628.txt [new file with mode: 0644]
src/encoding/xml/xml.go
src/encoding/xml/xml_test.go

diff --git a/api/next/45628.txt b/api/next/45628.txt
new file mode 100644 (file)
index 0000000..5065ae4
--- /dev/null
@@ -0,0 +1 @@
+pkg encoding/xml, method (*Decoder) InputPos() (int, int) #45628
index ef51252dcbbb1796fe1a32607573591484bdb70e..a7a02f5b571764389b849d8d74d5151f6bc9a47e 100644 (file)
@@ -216,6 +216,7 @@ type Decoder struct {
        ns             map[string]string
        err            error
        line           int
+       linestart      int64
        offset         int64
        unmarshalDepth int
 }
@@ -919,6 +920,7 @@ func (d *Decoder) getc() (b byte, ok bool) {
        }
        if b == '\n' {
                d.line++
+               d.linestart = d.offset + 1
        }
        d.offset++
        return b, true
@@ -931,6 +933,13 @@ func (d *Decoder) InputOffset() int64 {
        return d.offset
 }
 
+// InputPos retuns the line of the current decoder position and the 1 based
+// input position of the line. The position gives the location of the end of the
+// most recently returned token.
+func (d *Decoder) InputPos() (line, column int) {
+       return d.line, int(d.offset-d.linestart) + 1
+}
+
 // Return saved offset.
 // If we did ungetc (nextByte >= 0), have to back up one.
 func (d *Decoder) savedOffset() int {
index ab1dbf849bfd69e70ccf3b372833cba53305d96e..8f0d97b6a6c15cb6d35602058d098b9c164deb7e 100644 (file)
@@ -502,6 +502,45 @@ func TestSyntax(t *testing.T) {
        }
 }
 
+func TestInputLinePos(t *testing.T) {
+       testInput := `<root>
+<?pi
+ ?>  <elt
+att
+=
+"val">
+<![CDATA[
+]]><!--
+
+--></elt>
+</root>`
+       linePos := [][]int{
+               {1, 7},
+               {2, 1},
+               {3, 4},
+               {3, 6},
+               {6, 7},
+               {7, 1},
+               {8, 4},
+               {10, 4},
+               {10, 10},
+               {11, 1},
+               {11, 8},
+       }
+       dec := NewDecoder(strings.NewReader(testInput))
+       for _, want := range linePos {
+               if _, err := dec.Token(); err != nil {
+                       t.Errorf("Unexpected error: %v", err)
+                       continue
+               }
+
+               gotLine, gotCol := dec.InputPos()
+               if gotLine != want[0] || gotCol != want[1] {
+                       t.Errorf("dec.InputPos() = %d,%d, want %d,%d", gotLine, gotCol, want[0], want[1])
+               }
+       }
+}
+
 type allScalars struct {
        True1     bool
        True2     bool