86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Parsing keys handling both bare and quoted keys.
 | 
						|
 | 
						|
package toml
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"unicode"
 | 
						|
)
 | 
						|
 | 
						|
// Convert the bare key group string to an array.
 | 
						|
// The input supports double quotation to allow "." inside the key name,
 | 
						|
// but escape sequences are not supported. Lexers must unescape them beforehand.
 | 
						|
func parseKey(key string) ([]string, error) {
 | 
						|
	groups := []string{}
 | 
						|
	var buffer bytes.Buffer
 | 
						|
	inQuotes := false
 | 
						|
	wasInQuotes := false
 | 
						|
	ignoreSpace := true
 | 
						|
	expectDot := false
 | 
						|
 | 
						|
	for _, char := range key {
 | 
						|
		if ignoreSpace {
 | 
						|
			if char == ' ' {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			ignoreSpace = false
 | 
						|
		}
 | 
						|
		switch char {
 | 
						|
		case '"':
 | 
						|
			if inQuotes {
 | 
						|
				groups = append(groups, buffer.String())
 | 
						|
				buffer.Reset()
 | 
						|
				wasInQuotes = true
 | 
						|
			}
 | 
						|
			inQuotes = !inQuotes
 | 
						|
			expectDot = false
 | 
						|
		case '.':
 | 
						|
			if inQuotes {
 | 
						|
				buffer.WriteRune(char)
 | 
						|
			} else {
 | 
						|
				if !wasInQuotes {
 | 
						|
					if buffer.Len() == 0 {
 | 
						|
						return nil, errors.New("empty table key")
 | 
						|
					}
 | 
						|
					groups = append(groups, buffer.String())
 | 
						|
					buffer.Reset()
 | 
						|
				}
 | 
						|
				ignoreSpace = true
 | 
						|
				expectDot = false
 | 
						|
				wasInQuotes = false
 | 
						|
			}
 | 
						|
		case ' ':
 | 
						|
			if inQuotes {
 | 
						|
				buffer.WriteRune(char)
 | 
						|
			} else {
 | 
						|
				expectDot = true
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			if !inQuotes && !isValidBareChar(char) {
 | 
						|
				return nil, fmt.Errorf("invalid bare character: %c", char)
 | 
						|
			}
 | 
						|
			if !inQuotes && expectDot {
 | 
						|
				return nil, errors.New("what?")
 | 
						|
			}
 | 
						|
			buffer.WriteRune(char)
 | 
						|
			expectDot = false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if inQuotes {
 | 
						|
		return nil, errors.New("mismatched quotes")
 | 
						|
	}
 | 
						|
	if buffer.Len() > 0 {
 | 
						|
		groups = append(groups, buffer.String())
 | 
						|
	}
 | 
						|
	if len(groups) == 0 {
 | 
						|
		return nil, errors.New("empty key")
 | 
						|
	}
 | 
						|
	return groups, nil
 | 
						|
}
 | 
						|
 | 
						|
func isValidBareChar(r rune) bool {
 | 
						|
	return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r)
 | 
						|
}
 |