diff --git a/keysparsing.go b/keysparsing.go index 4deed811..b67664f6 100644 --- a/keysparsing.go +++ b/keysparsing.go @@ -12,6 +12,7 @@ func parseKey(key string) ([]string, error) { groups := []string{} var buffer bytes.Buffer inQuotes := false + wasInQuotes := false escapeNext := false ignoreSpace := true expectDot := false @@ -33,16 +34,27 @@ func parseKey(key string) ([]string, error) { escapeNext = true continue case '"': + if inQuotes { + groups = append(groups, buffer.String()) + buffer.Reset() + wasInQuotes = true + } inQuotes = !inQuotes expectDot = false case '.': if inQuotes { buffer.WriteRune(char) } else { - groups = append(groups, buffer.String()) - buffer.Reset() + if !wasInQuotes { + if buffer.Len() == 0 { + return nil, fmt.Errorf("empty key group") + } + groups = append(groups, buffer.String()) + buffer.Reset() + } ignoreSpace = true expectDot = false + wasInQuotes = false } case ' ': if inQuotes { diff --git a/keysparsing_test.go b/keysparsing_test.go index ef7e2a51..1a9eccca 100644 --- a/keysparsing_test.go +++ b/keysparsing_test.go @@ -7,6 +7,7 @@ import ( func testResult(t *testing.T, key string, expected []string) { parsed, err := parseKey(key) + t.Logf("key=%s expected=%s parsed=%s", key, expected, parsed) if err != nil { t.Fatal("Unexpected error:", err) } @@ -43,7 +44,13 @@ func TestBaseKeyPound(t *testing.T) { testError(t, "hello#world", "invalid bare character: #") } +func TestQuotedKeys(t *testing.T) { + testResult(t, `hello."foo".bar`, []string{"hello", "foo", "bar"}) + testResult(t, `"hello!"`, []string{"hello!"}) +} + func TestEmptyKey(t *testing.T) { testError(t, "", "empty key") testError(t, " ", "empty key") + testResult(t, `""`, []string{""}) } diff --git a/parser_test.go b/parser_test.go index 7f32ea8c..8f80a149 100644 --- a/parser_test.go +++ b/parser_test.go @@ -177,6 +177,16 @@ func TestStringEscapables(t *testing.T) { }) } +func TestEmptyQuotedString(t *testing.T) { + tree, err := Load(`[""] +"" = 1`) + assertTree(t, tree, err, map[string]interface{}{ + "": map[string]interface{}{ + "": int64(1), + }, + }) +} + func TestBools(t *testing.T) { tree, err := Load("a = true\nb = false") assertTree(t, tree, err, map[string]interface{}{ @@ -446,7 +456,7 @@ func TestDuplicateKeys(t *testing.T) { func TestEmptyIntermediateTable(t *testing.T) { _, err := Load("[foo..bar]") - if err.Error() != "(1, 2): empty intermediate table" { + if err.Error() != "(1, 2): invalid group array key: empty key group" { t.Error("Bad error message:", err.Error()) } } diff --git a/toml.go b/toml.go index c0e1ad2e..ad23fe85 100644 --- a/toml.go +++ b/toml.go @@ -222,9 +222,6 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) { func (t *TomlTree) createSubTree(keys []string, pos Position) error { subtree := t for _, intermediateKey := range keys { - if intermediateKey == "" { - return fmt.Errorf("empty intermediate table") - } nextTree, exists := subtree.values[intermediateKey] if !exists { tree := newTomlTree()