@@ -79,6 +79,7 @@ type entry struct {
|
|||||||
name []byte
|
name []byte
|
||||||
kind keyKind
|
kind keyKind
|
||||||
explicit bool
|
explicit bool
|
||||||
|
kv bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index of the child of parentIdx with key k. Returns -1 if
|
// Find the index of the child of parentIdx with key k. Returns -1 if
|
||||||
@@ -111,7 +112,7 @@ func (s *SeenTracker) clear(idx int) {
|
|||||||
s.entries[idx].child = -1
|
s.entries[idx].child = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool) int {
|
func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool, kv bool) int {
|
||||||
e := entry{
|
e := entry{
|
||||||
child: -1,
|
child: -1,
|
||||||
next: s.entries[parentIdx].child,
|
next: s.entries[parentIdx].child,
|
||||||
@@ -119,6 +120,7 @@ func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit
|
|||||||
name: name,
|
name: name,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
explicit: explicit,
|
explicit: explicit,
|
||||||
|
kv: kv,
|
||||||
}
|
}
|
||||||
var idx int
|
var idx int
|
||||||
if s.entries[0].next >= 0 {
|
if s.entries[0].next >= 0 {
|
||||||
@@ -137,7 +139,10 @@ func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit
|
|||||||
|
|
||||||
func (s *SeenTracker) setExplicitFlag(parentIdx int) {
|
func (s *SeenTracker) setExplicitFlag(parentIdx int) {
|
||||||
for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
|
for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
|
||||||
s.entries[i].explicit = true
|
if s.entries[i].kv {
|
||||||
|
s.entries[i].explicit = true
|
||||||
|
s.entries[i].kv = false
|
||||||
|
}
|
||||||
s.setExplicitFlag(i)
|
s.setExplicitFlag(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +188,7 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
|
|||||||
idx := s.find(parentIdx, k)
|
idx := s.find(parentIdx, k)
|
||||||
|
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
idx = s.create(parentIdx, k, tableKind, false)
|
idx = s.create(parentIdx, k, tableKind, false, false)
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if entry.kind == valueKind {
|
if entry.kind == valueKind {
|
||||||
@@ -206,7 +211,7 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
|
|||||||
}
|
}
|
||||||
s.entries[idx].explicit = true
|
s.entries[idx].explicit = true
|
||||||
} else {
|
} else {
|
||||||
idx = s.create(parentIdx, k, tableKind, true)
|
idx = s.create(parentIdx, k, tableKind, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentIdx = idx
|
s.currentIdx = idx
|
||||||
@@ -233,7 +238,7 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
|
|||||||
idx := s.find(parentIdx, k)
|
idx := s.find(parentIdx, k)
|
||||||
|
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
idx = s.create(parentIdx, k, tableKind, false)
|
idx = s.create(parentIdx, k, tableKind, false, false)
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if entry.kind == valueKind {
|
if entry.kind == valueKind {
|
||||||
@@ -254,7 +259,7 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
|
|||||||
}
|
}
|
||||||
s.clear(idx)
|
s.clear(idx)
|
||||||
} else {
|
} else {
|
||||||
idx = s.create(parentIdx, k, arrayTableKind, true)
|
idx = s.create(parentIdx, k, arrayTableKind, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentIdx = idx
|
s.currentIdx = idx
|
||||||
@@ -272,7 +277,7 @@ func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
|
|||||||
idx := s.find(parentIdx, k)
|
idx := s.find(parentIdx, k)
|
||||||
|
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
idx = s.create(parentIdx, k, tableKind, false)
|
idx = s.create(parentIdx, k, tableKind, false, true)
|
||||||
} else {
|
} else {
|
||||||
entry := s.entries[idx]
|
entry := s.entries[idx]
|
||||||
if it.IsLast() {
|
if it.IsLast() {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package tracker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEntrySize(t *testing.T) {
|
||||||
|
// Validate no regression on the size of entry{}. This is a critical bit for
|
||||||
|
// performance of unmarshaling documents. Should only be increased with care
|
||||||
|
// and a very good reason.
|
||||||
|
require.LessOrEqual(t, 48, int(unsafe.Sizeof(entry{})))
|
||||||
|
}
|
||||||
@@ -545,6 +545,35 @@ func TestUnmarshal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "issue 739 - table redefinition",
|
||||||
|
input: `
|
||||||
|
[foo.bar.baz]
|
||||||
|
wibble = 'wobble'
|
||||||
|
|
||||||
|
[foo]
|
||||||
|
|
||||||
|
[foo.bar]
|
||||||
|
huey = 'dewey'
|
||||||
|
`,
|
||||||
|
gen: func() test {
|
||||||
|
m := map[string]interface{}{}
|
||||||
|
|
||||||
|
return test{
|
||||||
|
target: &m,
|
||||||
|
expected: &map[string]interface{}{
|
||||||
|
`foo`: map[string]interface{}{
|
||||||
|
"bar": map[string]interface{}{
|
||||||
|
"huey": "dewey",
|
||||||
|
"baz": map[string]interface{}{
|
||||||
|
"wibble": "wobble",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "multiline basic string",
|
desc: "multiline basic string",
|
||||||
input: `A = """\
|
input: `A = """\
|
||||||
|
|||||||
Reference in New Issue
Block a user