mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-20 23:46:23 +01:00
110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
package ini
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
func parse(tokens []lineToken, path string) Sections {
|
|
parser := &parser{
|
|
path: path,
|
|
sections: NewSections(),
|
|
}
|
|
parser.parse(tokens)
|
|
return parser.sections
|
|
}
|
|
|
|
type parser struct {
|
|
csection, ckey string // current state
|
|
path string // source file path
|
|
sections Sections // parse result
|
|
}
|
|
|
|
func (p *parser) parse(tokens []lineToken) {
|
|
for _, otok := range tokens {
|
|
switch tok := otok.(type) {
|
|
case *lineTokenProfile:
|
|
p.handleProfile(tok)
|
|
case *lineTokenProperty:
|
|
p.handleProperty(tok)
|
|
case *lineTokenSubProperty:
|
|
p.handleSubProperty(tok)
|
|
case *lineTokenContinuation:
|
|
p.handleContinuation(tok)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *parser) handleProfile(tok *lineTokenProfile) {
|
|
name := tok.Name
|
|
if tok.Type != "" {
|
|
name = fmt.Sprintf("%s %s", tok.Type, tok.Name)
|
|
}
|
|
p.ckey = ""
|
|
p.csection = name
|
|
if _, ok := p.sections.container[name]; !ok {
|
|
p.sections.container[name] = NewSection(name)
|
|
}
|
|
}
|
|
|
|
func (p *parser) handleProperty(tok *lineTokenProperty) {
|
|
if p.csection == "" {
|
|
return // LEGACY: don't error on "global" properties
|
|
}
|
|
|
|
p.ckey = tok.Key
|
|
if _, ok := p.sections.container[p.csection].values[tok.Key]; ok {
|
|
section := p.sections.container[p.csection]
|
|
section.Logs = append(p.sections.container[p.csection].Logs,
|
|
fmt.Sprintf(
|
|
"For profile: %v, overriding %v value, with a %v value found in a duplicate profile defined later in the same file %v. \n",
|
|
p.csection, tok.Key, tok.Key, p.path,
|
|
),
|
|
)
|
|
p.sections.container[p.csection] = section
|
|
}
|
|
|
|
p.sections.container[p.csection].values[tok.Key] = Value{
|
|
str: tok.Value,
|
|
}
|
|
p.sections.container[p.csection].SourceFile[tok.Key] = p.path
|
|
}
|
|
|
|
func (p *parser) handleSubProperty(tok *lineTokenSubProperty) {
|
|
if p.csection == "" {
|
|
return // LEGACY: don't error on "global" properties
|
|
}
|
|
|
|
if p.ckey == "" || p.sections.container[p.csection].values[p.ckey].str != "" {
|
|
// This is an "orphaned" subproperty, either because it's at
|
|
// the beginning of a section or because the last property's
|
|
// value isn't empty. Either way we're lenient here and
|
|
// "promote" this to a normal property.
|
|
p.handleProperty(&lineTokenProperty{
|
|
Key: tok.Key,
|
|
Value: strings.TrimSpace(trimComment(tok.Value)),
|
|
})
|
|
return
|
|
}
|
|
|
|
if p.sections.container[p.csection].values[p.ckey].mp == nil {
|
|
p.sections.container[p.csection].values[p.ckey] = Value{
|
|
mp: map[string]string{},
|
|
}
|
|
}
|
|
p.sections.container[p.csection].values[p.ckey].mp[tok.Key] = tok.Value
|
|
}
|
|
|
|
func (p *parser) handleContinuation(tok *lineTokenContinuation) {
|
|
if p.ckey == "" {
|
|
return
|
|
}
|
|
|
|
value, _ := p.sections.container[p.csection].values[p.ckey]
|
|
if value.str != "" && value.mp == nil {
|
|
value.str = fmt.Sprintf("%s\n%s", value.str, tok.Value)
|
|
}
|
|
|
|
p.sections.container[p.csection].values[p.ckey] = value
|
|
}
|