Skip to content

Instantly share code, notes, and snippets.

@nskforward
Last active February 27, 2020 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nskforward/fd057c89f2d3523f3a596579207a3005 to your computer and use it in GitHub Desktop.
Save nskforward/fd057c89f2d3523f3a596579207a3005 to your computer and use it in GitHub Desktop.
Parser
package parser
import (
"bytes"
)
// Parser .
type Parser struct {
tail []byte
key []byte
value []byte
}
// NewParser .
func NewParser() *Parser {
return &Parser{
key: make([]byte, 0, 64),
value: make([]byte, 0, 512),
}
}
// Load .
func (p *Parser) Load(source []byte) {
p.tail = bytes.Trim(source, " ")
}
// Len .
func (p *Parser) Len() int {
return len(p.tail)
}
// Next .
func (p *Parser) Next() ([]byte, []byte) {
p.key = p.key[:0]
p.value = p.value[:0]
foundDecimal := false
firstValuePos := false
typeString := false
for i, c := range p.tail {
if c == '=' && !foundDecimal {
foundDecimal = true
firstValuePos = true
continue
}
if firstValuePos && c == ' ' {
continue
}
if firstValuePos && c == '\'' {
p.value = append(p.value, byte(c))
typeString = true
firstValuePos = false
continue
}
if firstValuePos && c != '\'' {
p.value = append(p.value, byte(c))
typeString = false
firstValuePos = false
continue
}
if c == ' ' && foundDecimal && !typeString && !firstValuePos {
p.tail = p.tail[i+1:]
break
}
if c == '\'' && foundDecimal && !firstValuePos && typeString {
p.value = append(p.value, byte(c))
p.tail = p.tail[i+1:]
break
}
if c == ' ' && !foundDecimal {
continue
}
if foundDecimal {
p.value = append(p.value, byte(c))
} else {
p.key = append(p.key, byte(c))
}
if i+1 == len(p.tail) {
p.tail = p.tail[:0]
break
}
}
return p.key, p.value
}
// Parse .
func (p *Parser) Parse(k, v [][]byte) ([][]byte, [][]byte) {
k = k[:0]
v = v[:0]
for p.Len() > 0 {
key, val := p.Next()
k = append(k, key)
v = append(v, val)
}
return k, v
}
package parser
import "testing"
func BenchmarkParser(b *testing.B) {
keysBuffer := make([][]byte, 0, 32)
valsBuffer := make([][]byte, 0, 32)
parser := NewParser()
input := []byte(" k1 =v1 k2= 'v2' k3 = 'v3' k4='v4' k5=v5")
for i := 0; i < b.N; i++ {
parser.Load(input)
parser.Parse(keysBuffer, valsBuffer)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment