Change layout to more go-style-ish, replace some modules
* Deejay files, split them to achieve go-style project layout * Replace logrus with log/slog module to reduce dependencies * Replace gopkg.in/ini.v1 with github.com/wlevene/ini to make sure all modules BSD licensed * Update linter config && fix tons of linter warnings * Update .gitignore * Update README.md
This commit is contained in:
21
vendor/github.com/wlevene/ini/LICENSE
generated
vendored
Normal file
21
vendor/github.com/wlevene/ini/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 levene
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
420
vendor/github.com/wlevene/ini/README.md
generated
vendored
Normal file
420
vendor/github.com/wlevene/ini/README.md
generated
vendored
Normal file
@@ -0,0 +1,420 @@
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
# INI Parser & Write Library
|
||||
|
||||
ini parser and write library for Golang,easy-use,fast
|
||||
|
||||
|
||||
[](https://github.com/wlevene/ini)
|
||||

|
||||
|
||||
# Features
|
||||
|
||||
* Can be read by []byte
|
||||
* Can be read by file
|
||||
* Supports file monitoring and takes effect in real time without reloading
|
||||
* Unmarshal to Struct
|
||||
* Marshal to Json
|
||||
* Write ini to File
|
||||
|
||||
|
||||
# Installation
|
||||
|
||||
```shell
|
||||
go get github.com/wlevene/ini
|
||||
```
|
||||
|
||||
|
||||
# Example
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wlevene/ini"
|
||||
)
|
||||
```
|
||||
|
||||
### GetValue
|
||||
|
||||
```go
|
||||
doc := `
|
||||
[section]
|
||||
k=v
|
||||
|
||||
[section1]
|
||||
k1=v1
|
||||
k2=1
|
||||
k3=3.5
|
||||
k4=0.0.0.0
|
||||
`
|
||||
v1 := ini.New().Load([]byte(doc)).Section("section1").Get("k1")
|
||||
fmt.Println(v1)
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
v1
|
||||
```
|
||||
|
||||
|
||||
```go
|
||||
i := ini.New().Load([]byte(doc))
|
||||
v1 := i.Section("section1").Get("k1")
|
||||
v2 := i.GetInt("k2")
|
||||
v3 := i.GetFloat64("k3")
|
||||
v4 := i.Get("k4")
|
||||
v5 := i.GetIntDef("keyint", 10)
|
||||
v6 := i.GetDef("keys", "defualt")
|
||||
|
||||
fmt.Printf("v1:%v v2:%v v3:%v v4:%v v5:%v v6:%v\n", v1, v2, v3, v4, v5, v6)
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
v1:v1 v2:1 v3:3.5 v4:0.0.0.0 v5:10 v6:defualt
|
||||
```
|
||||
|
||||
|
||||
### Marshal2Json
|
||||
|
||||
```go
|
||||
fmt.Println(string(i.Marshal2Json()))
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```json
|
||||
{"section":{"k":"v"},"section1":{"k1":"v1","k2":"1","k3":"3.5","k4":"0.0.0.0"}}
|
||||
```
|
||||
|
||||
### Unmarshal Struct
|
||||
|
||||
```go
|
||||
type TestConfig struct {
|
||||
K string `ini:"k" json:"k,omitempty"`
|
||||
K1 int `ini:"k1" json:"k1,omitempty"`
|
||||
K2 float64 `ini:"k2"`
|
||||
K3 int64 `ini:"k3"`
|
||||
User User `ini:"user"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string `ini:"name"`
|
||||
Age int `ini:"age"`
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```go
|
||||
doc := `
|
||||
k=v
|
||||
k1=2
|
||||
k2=2.2
|
||||
k3=3
|
||||
|
||||
[user]
|
||||
name=tom
|
||||
age=-23
|
||||
`
|
||||
|
||||
cfg := TestConfig{}
|
||||
|
||||
ini.Unmarshal([]byte(doc), &cfg)
|
||||
fmt.Println("cfg:", cfg)
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
cfg: {v 2 2.2 3 {tom -23}}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Parse File
|
||||
|
||||
ini file
|
||||
|
||||
```ini
|
||||
; this is comment
|
||||
; author levene
|
||||
; date 2021-8-1
|
||||
|
||||
|
||||
a='23'34?::'<>,.'
|
||||
c=d
|
||||
|
||||
[s1]
|
||||
k=67676
|
||||
k1 =fdasf
|
||||
k2= sdafj3490&@)34 34w2
|
||||
|
||||
# comment
|
||||
# 12.0.0.1
|
||||
[s2]
|
||||
|
||||
k=3
|
||||
|
||||
|
||||
k2=945
|
||||
k3=-435
|
||||
k4=0.0.0.0
|
||||
|
||||
k5=127.0.0.1
|
||||
k6=levene@github.com
|
||||
|
||||
k7=~/.path.txt
|
||||
k8=./34/34/uh.txt
|
||||
|
||||
k9=234@!@#$%^&*()324
|
||||
k10='23'34?::'<>,.'
|
||||
|
||||
```
|
||||
|
||||
```go
|
||||
file := "./test.ini"
|
||||
ini.New().LoadFile(file).Section("s2").Get("k2")
|
||||
|
||||
fmt.Println(string(ini.Marshal2Json()))
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
945
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Watch File
|
||||
|
||||
```go
|
||||
file := "./test.ini"
|
||||
|
||||
idoc := ini.New().WatchFile(file)
|
||||
v := idoc.Section("s2").Get("k1")
|
||||
fmt.Println("v:", v1)
|
||||
|
||||
// modify k1=v1 ==> k1=v2
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
v = idoc.Section("s2").Get("k1")
|
||||
fmt.Println("v:", v1)
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```
|
||||
v: v1
|
||||
v: v2
|
||||
```
|
||||
|
||||
|
||||
|
||||
Print file with json
|
||||
|
||||
```go
|
||||
file := "./test.ini"
|
||||
fmt.Println(string(ini.New().LoadFile(file).Marshal2Json()))
|
||||
```
|
||||
|
||||
Output
|
||||
|
||||
```json
|
||||
{
|
||||
"a": "'23'34?::'<>,.'",
|
||||
"c": "d",
|
||||
"s1": {
|
||||
"k": "67676",
|
||||
"k2": "34w2"
|
||||
},
|
||||
"s2": {
|
||||
"k": "3",
|
||||
"k10": "'23'34?::'<>,.'",
|
||||
"k2": "945",
|
||||
"k3": "-435",
|
||||
"k4": "0.0.0.0",
|
||||
"k5": "127.0.0.1",
|
||||
"k6": "levene@github.com",
|
||||
"k7": "~/.path.txt",
|
||||
"k8": "./34/34/uh.txt",
|
||||
"k9": "234@!@#$%^&*()324"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Set Ini
|
||||
```go
|
||||
doc := `
|
||||
k =v
|
||||
[section]
|
||||
a=b
|
||||
c=d
|
||||
`
|
||||
ini := New().Load([]byte(doc)).Section("section")
|
||||
fmt.Println("--------------------------------")
|
||||
ini.Dump()
|
||||
|
||||
fmt.Println("--------------------------------")
|
||||
ini.Set("a", 11).Set("c", 12.3).Section("").Set("k", "SET")
|
||||
ini.Dump()
|
||||
|
||||
v := ini.Section("section").GetInt("a")
|
||||
|
||||
if v != 11 {
|
||||
t.Errorf("Error: %d", v)
|
||||
}
|
||||
|
||||
v1 := ini.GetFloat64("c")
|
||||
|
||||
if v1 != 12.3 {
|
||||
t.Errorf("Error: %f", v1)
|
||||
}
|
||||
|
||||
v2 := ini.Section("").Get("k")
|
||||
if v2 != "SET" {
|
||||
t.Errorf("Error: %s", v2)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Wirte Ini
|
||||
|
||||
```go
|
||||
filename := "./save.ini"
|
||||
ini := New().Set("a1", 1)
|
||||
ini.Save(filename)
|
||||
fmt.Println(ini.Err())
|
||||
|
||||
ini2 := New().Set("a1", 1).Section("s1").Set("a2", "v2")
|
||||
ini2.Save(filename)
|
||||
fmt.Println(ini2.Err())
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Dump AST struct
|
||||
|
||||
```
|
||||
INIDocNode {
|
||||
CommentNode {
|
||||
Comment: ; this is comment
|
||||
Line: 0
|
||||
}
|
||||
CommentNode {
|
||||
Comment: ; author levene
|
||||
Line: 1
|
||||
}
|
||||
CommentNode {
|
||||
Comment: ; date 2021-8-1
|
||||
Line: 2
|
||||
}
|
||||
KVNode {
|
||||
Key: a
|
||||
Value: '23'34?::'<>,.'
|
||||
Line: 5
|
||||
}
|
||||
KVNode {
|
||||
Key: c
|
||||
Value: d
|
||||
Line: 6
|
||||
}
|
||||
Section {
|
||||
Section: [s1]
|
||||
Line: 8
|
||||
KVNode {
|
||||
Value: 67676
|
||||
Line: 9
|
||||
Key: k
|
||||
}
|
||||
KVNode {
|
||||
Key: k1
|
||||
Value: fdasf
|
||||
Line: 10
|
||||
}
|
||||
KVNode {
|
||||
Value: 4w2
|
||||
Line: 11
|
||||
Key: k2
|
||||
}
|
||||
}
|
||||
CommentNode {
|
||||
Comment: # comment
|
||||
Line: 13
|
||||
}
|
||||
CommentNode {
|
||||
Line: 14
|
||||
Comment: # 12.0.0.1
|
||||
}
|
||||
Section {
|
||||
Section: [s2]
|
||||
Line: 15
|
||||
KVNode {
|
||||
Value: 3
|
||||
Line: 17
|
||||
Key: k
|
||||
}
|
||||
KVNode {
|
||||
Value: 945
|
||||
Line: 20
|
||||
Key: k2
|
||||
}
|
||||
KVNode {
|
||||
Key: k3
|
||||
Value: -435
|
||||
Line: 21
|
||||
}
|
||||
KVNode {
|
||||
Line: 22
|
||||
Key: k4
|
||||
Value: 0.0.0.0
|
||||
}
|
||||
KVNode {
|
||||
Line: 24
|
||||
Key: k5
|
||||
Value: 127.0.0.1
|
||||
}
|
||||
KVNode {
|
||||
Key: k6
|
||||
Value: levene@github.com
|
||||
Line: 25
|
||||
}
|
||||
KVNode {
|
||||
Key: k7
|
||||
Value: ~/.path.txt
|
||||
Line: 27
|
||||
}
|
||||
KVNode {
|
||||
Line: 28
|
||||
Key: k8
|
||||
Value: ./34/34/uh.txt
|
||||
}
|
||||
KVNode {
|
||||
Key: k9
|
||||
Value: 234@!@#$%^&*()324
|
||||
Line: 30
|
||||
}
|
||||
KVNode {
|
||||
Key: k10
|
||||
Value: '23'34?::'<>,.'
|
||||
Line: 31
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/RichardLitt/standard-readme/blob/master/LICENSE)
|
||||
551
vendor/github.com/wlevene/ini/ast/ast.go
generated
vendored
Normal file
551
vendor/github.com/wlevene/ini/ast/ast.go
generated
vendored
Normal file
@@ -0,0 +1,551 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type NodeType int
|
||||
type NodeKind int
|
||||
|
||||
const (
|
||||
// TypeBlock indicates that a node is kind of block nodes.
|
||||
TypeBlock NodeType = iota + 1
|
||||
// TypeDocument indicates that a node is kind of document nodes.
|
||||
TypeDocNode
|
||||
)
|
||||
|
||||
var kindMax NodeKind
|
||||
var kindNames = []string{""}
|
||||
|
||||
// NewNodeKind returns a new Kind value.
|
||||
func NewNodeKind(name string) NodeKind {
|
||||
kindMax++
|
||||
kindNames = append(kindNames, name)
|
||||
return kindMax
|
||||
}
|
||||
|
||||
func (k NodeKind) String() string {
|
||||
return kindNames[k]
|
||||
// return ""
|
||||
}
|
||||
|
||||
// A Node interface defines basic AST node functionalities.
|
||||
type Node interface {
|
||||
// Type returns a type of this node.
|
||||
Type() NodeType
|
||||
|
||||
// Kind returns a kind of this node.
|
||||
Kind() NodeKind
|
||||
|
||||
// NextSibling returns a next sibling node of this node.
|
||||
NextSibling() Node
|
||||
|
||||
// PreviousSibling returns a previous sibling node of this node.
|
||||
PreviousSibling() Node
|
||||
|
||||
// Parent returns a parent node of this node.
|
||||
Parent() Node
|
||||
|
||||
// SetParent sets a parent node to this node.
|
||||
SetParent(Node)
|
||||
|
||||
// SetPreviousSibling sets a previous sibling node to this node.
|
||||
SetPreviousSibling(Node)
|
||||
|
||||
// SetNextSibling sets a next sibling node to this node.
|
||||
SetNextSibling(Node)
|
||||
|
||||
// HasChildren returns true if this node has any children, otherwise false.
|
||||
HasChildren() bool
|
||||
|
||||
// ChildCount returns a total number of children.
|
||||
ChildCount() int
|
||||
|
||||
// FirstChild returns a first child of this node.
|
||||
FirstChild() Node
|
||||
|
||||
// LastChild returns a last child of this node.
|
||||
LastChild() Node
|
||||
|
||||
// AppendChild append a node child to the tail of the children.
|
||||
AppendChild(self, child Node)
|
||||
|
||||
// RemoveChild removes a node child from this node.
|
||||
// If a node child is not children of this node, RemoveChild nothing to do.
|
||||
RemoveChild(self, child Node)
|
||||
|
||||
// RemoveChildren removes all children from this node.
|
||||
RemoveChildren(self Node)
|
||||
|
||||
// SortChildren sorts childrens by comparator.
|
||||
SortChildren(comparator func(n1, n2 Node) int)
|
||||
|
||||
// ReplaceChild replace a node v1 with a node insertee.
|
||||
// If v1 is not children of this node, ReplaceChild append a insetee to the
|
||||
// tail of the children.
|
||||
ReplaceChild(self, v1, insertee Node)
|
||||
|
||||
// InsertBefore inserts a node insertee before a node v1.
|
||||
// If v1 is not children of this node, InsertBefore append a insetee to the
|
||||
// tail of the children.
|
||||
InsertBefore(self, v1, insertee Node)
|
||||
|
||||
// InsertAfterinserts a node insertee after a node v1.
|
||||
// If v1 is not children of this node, InsertBefore append a insetee to the
|
||||
// tail of the children.
|
||||
InsertAfter(self, v1, insertee Node)
|
||||
|
||||
IsRoot() bool
|
||||
Depth() int
|
||||
IsLeaf() bool
|
||||
|
||||
// OwnerDocument returns this node's owner document.
|
||||
// If this node is not a child of the Document node, OwnerDocument
|
||||
// returns nil.
|
||||
// OwnerDocument() *Document
|
||||
|
||||
// Dump dumps an AST tree structure to stdout.
|
||||
// This function completely aimed for debugging.
|
||||
// level is a indent level. Implementer should indent informations with
|
||||
// 2 * level spaces.
|
||||
Dump(source []byte, level int)
|
||||
|
||||
// Text returns text values of this node.
|
||||
Text(source []byte) []byte
|
||||
|
||||
// HasBlankPreviousLines returns true if the row before this node is blank,
|
||||
// otherwise false.
|
||||
// This method is valid only for block nodes.
|
||||
// HasBlankPreviousLines() bool
|
||||
|
||||
// SetBlankPreviousLines sets whether the row before this node is blank.
|
||||
// This method is valid only for block nodes.
|
||||
// SetBlankPreviousLines(v bool)
|
||||
|
||||
// Lines returns text segments that hold positions in a source.
|
||||
// This method is valid only for block nodes.
|
||||
// Lines() *textm.Segments
|
||||
|
||||
// SetLines sets text segments that hold positions in a source.
|
||||
// This method is valid only for block nodes.
|
||||
// SetLines(*textm.Segments)
|
||||
|
||||
// IsRaw returns true if contents should be rendered as 'raw' contents.
|
||||
IsRaw() bool
|
||||
|
||||
// SetAttribute sets the given value to the attributes.
|
||||
SetAttribute(name []byte, value interface{})
|
||||
|
||||
// SetAttributeString sets the given value to the attributes.
|
||||
SetAttributeString(name string, value interface{})
|
||||
|
||||
// Attribute returns a (attribute value, true) if an attribute
|
||||
// associated with the given name is found, otherwise
|
||||
// (nil, false)
|
||||
Attribute(name []byte) (interface{}, bool)
|
||||
|
||||
// AttributeString returns a (attribute value, true) if an attribute
|
||||
// associated with the given name is found, otherwise
|
||||
// (nil, false)
|
||||
AttributeString(name string) (interface{}, bool)
|
||||
|
||||
// Attributes returns a list of attributes.
|
||||
// This may be a nil if there are no attributes.
|
||||
Attributes() []Attribute
|
||||
|
||||
// RemoveAttributes removes all attributes from this node.
|
||||
RemoveAttributes()
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
Name []byte
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// A BaseNode struct implements the Node interface partialliy.
|
||||
type BaseNode struct {
|
||||
firstChild Node
|
||||
lastChild Node
|
||||
parent Node
|
||||
next Node
|
||||
prev Node
|
||||
childCount int
|
||||
attributes []Attribute
|
||||
}
|
||||
|
||||
func ensureIsolated(v Node) {
|
||||
if p := v.Parent(); p != nil {
|
||||
p.RemoveChild(p, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *BaseNode) Kind() NodeKind {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *BaseNode) Type() NodeType {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (n *BaseNode) Depth() int {
|
||||
depth := 0
|
||||
|
||||
var i_node Node
|
||||
i_node = n.Parent()
|
||||
|
||||
if i_node == nil {
|
||||
return depth
|
||||
}
|
||||
|
||||
for {
|
||||
i_node = i_node.Parent()
|
||||
if i_node == nil {
|
||||
break
|
||||
}
|
||||
depth = depth + 1
|
||||
}
|
||||
return depth
|
||||
}
|
||||
|
||||
// IsRoot checks if node is a root node
|
||||
func (n *BaseNode) IsRoot() bool {
|
||||
return n.Parent() != nil
|
||||
}
|
||||
|
||||
func (n *BaseNode) IsLeaf() bool {
|
||||
return n.childCount > 0
|
||||
}
|
||||
|
||||
// HasChildren implements Node.HasChildren .
|
||||
func (n *BaseNode) HasChildren() bool {
|
||||
return n.firstChild != nil
|
||||
}
|
||||
|
||||
// SetPreviousSibling implements Node.SetPreviousSibling .
|
||||
func (n *BaseNode) SetPreviousSibling(v Node) {
|
||||
n.prev = v
|
||||
}
|
||||
|
||||
// SetNextSibling implements Node.SetNextSibling .
|
||||
func (n *BaseNode) SetNextSibling(v Node) {
|
||||
n.next = v
|
||||
}
|
||||
|
||||
// PreviousSibling implements Node.PreviousSibling .
|
||||
func (n *BaseNode) PreviousSibling() Node {
|
||||
return n.prev
|
||||
}
|
||||
|
||||
// NextSibling implements Node.NextSibling .
|
||||
func (n *BaseNode) NextSibling() Node {
|
||||
return n.next
|
||||
}
|
||||
|
||||
// RemoveChild implements Node.RemoveChild .
|
||||
func (n *BaseNode) RemoveChild(self, v Node) {
|
||||
if v.Parent() != self {
|
||||
return
|
||||
}
|
||||
|
||||
n.childCount--
|
||||
prev := v.PreviousSibling()
|
||||
next := v.NextSibling()
|
||||
if prev != nil {
|
||||
prev.SetNextSibling(next)
|
||||
} else {
|
||||
n.firstChild = next
|
||||
}
|
||||
if next != nil {
|
||||
next.SetPreviousSibling(prev)
|
||||
} else {
|
||||
n.lastChild = prev
|
||||
}
|
||||
v.SetParent(nil)
|
||||
v.SetPreviousSibling(nil)
|
||||
v.SetNextSibling(nil)
|
||||
}
|
||||
|
||||
// RemoveChildren implements Node.RemoveChildren .
|
||||
func (n *BaseNode) RemoveChildren(self Node) {
|
||||
for c := n.firstChild; c != nil; {
|
||||
c.SetParent(nil)
|
||||
c.SetPreviousSibling(nil)
|
||||
next := c.NextSibling()
|
||||
c.SetNextSibling(nil)
|
||||
c = next
|
||||
}
|
||||
n.firstChild = nil
|
||||
n.lastChild = nil
|
||||
n.childCount = 0
|
||||
}
|
||||
|
||||
// SortChildren implements Node.SortChildren
|
||||
func (n *BaseNode) SortChildren(comparator func(n1, n2 Node) int) {
|
||||
var sorted Node
|
||||
current := n.firstChild
|
||||
for current != nil {
|
||||
next := current.NextSibling()
|
||||
if sorted == nil || comparator(sorted, current) >= 0 {
|
||||
current.SetNextSibling(sorted)
|
||||
if sorted != nil {
|
||||
sorted.SetPreviousSibling(current)
|
||||
}
|
||||
sorted = current
|
||||
sorted.SetPreviousSibling(nil)
|
||||
} else {
|
||||
c := sorted
|
||||
for c.NextSibling() != nil && comparator(c.NextSibling(), current) < 0 {
|
||||
c = c.NextSibling()
|
||||
}
|
||||
current.SetNextSibling(c.NextSibling())
|
||||
current.SetPreviousSibling(c)
|
||||
if c.NextSibling() != nil {
|
||||
c.NextSibling().SetPreviousSibling(current)
|
||||
}
|
||||
c.SetNextSibling(current)
|
||||
}
|
||||
current = next
|
||||
}
|
||||
n.firstChild = sorted
|
||||
for c := n.firstChild; c != nil; c = c.NextSibling() {
|
||||
n.lastChild = c
|
||||
}
|
||||
}
|
||||
|
||||
// FirstChild implements Node.FirstChild .
|
||||
func (n *BaseNode) FirstChild() Node {
|
||||
return n.firstChild
|
||||
}
|
||||
|
||||
// LastChild implements Node.LastChild .
|
||||
func (n *BaseNode) LastChild() Node {
|
||||
return n.lastChild
|
||||
}
|
||||
|
||||
// ChildCount implements Node.ChildCount .
|
||||
func (n *BaseNode) ChildCount() int {
|
||||
return n.childCount
|
||||
}
|
||||
|
||||
// Parent implements Node.Parent .
|
||||
func (n *BaseNode) Parent() Node {
|
||||
return n.parent
|
||||
}
|
||||
|
||||
// SetParent implements Node.SetParent .
|
||||
func (n *BaseNode) SetParent(v Node) {
|
||||
n.parent = v
|
||||
}
|
||||
|
||||
// AppendChild implements Node.AppendChild .
|
||||
func (n *BaseNode) AppendChild(self, v Node) {
|
||||
ensureIsolated(v)
|
||||
if n.firstChild == nil {
|
||||
n.firstChild = v
|
||||
v.SetNextSibling(nil)
|
||||
v.SetPreviousSibling(nil)
|
||||
} else {
|
||||
last := n.lastChild
|
||||
last.SetNextSibling(v)
|
||||
v.SetPreviousSibling(last)
|
||||
}
|
||||
v.SetParent(self)
|
||||
n.lastChild = v
|
||||
n.childCount++
|
||||
}
|
||||
|
||||
// ReplaceChild implements Node.ReplaceChild .
|
||||
func (n *BaseNode) ReplaceChild(self, v1, insertee Node) {
|
||||
n.InsertBefore(self, v1, insertee)
|
||||
n.RemoveChild(self, v1)
|
||||
}
|
||||
|
||||
// InsertAfter implements Node.InsertAfter .
|
||||
func (n *BaseNode) InsertAfter(self, v1, insertee Node) {
|
||||
n.InsertBefore(self, v1.NextSibling(), insertee)
|
||||
}
|
||||
|
||||
// InsertBefore implements Node.InsertBefore .
|
||||
func (n *BaseNode) InsertBefore(self, v1, insertee Node) {
|
||||
n.childCount++
|
||||
if v1 == nil {
|
||||
n.AppendChild(self, insertee)
|
||||
return
|
||||
}
|
||||
ensureIsolated(insertee)
|
||||
if v1.Parent() == self {
|
||||
c := v1
|
||||
prev := c.PreviousSibling()
|
||||
if prev != nil {
|
||||
prev.SetNextSibling(insertee)
|
||||
insertee.SetPreviousSibling(prev)
|
||||
} else {
|
||||
n.firstChild = insertee
|
||||
insertee.SetPreviousSibling(nil)
|
||||
}
|
||||
insertee.SetNextSibling(c)
|
||||
c.SetPreviousSibling(insertee)
|
||||
insertee.SetParent(self)
|
||||
}
|
||||
}
|
||||
|
||||
// // OwnerDocument implements Node.OwnerDocument
|
||||
// func (n *BaseNode) OwnerDocument() *Document {
|
||||
// d := n.Parent()
|
||||
// for {
|
||||
// p := d.Parent()
|
||||
// if p == nil {
|
||||
// if v, ok := d.(*Document); ok {
|
||||
// return v
|
||||
// }
|
||||
// break
|
||||
// }
|
||||
// d = p
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (n *BaseNode) IsRaw() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Text implements Node.Text .
|
||||
func (n *BaseNode) Text(source []byte) []byte {
|
||||
var buf bytes.Buffer
|
||||
for c := n.firstChild; c != nil; c = c.NextSibling() {
|
||||
buf.Write(c.Text(source))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// SetAttribute implements Node.SetAttribute.
|
||||
func (n *BaseNode) SetAttribute(name []byte, value interface{}) {
|
||||
if n.attributes == nil {
|
||||
n.attributes = make([]Attribute, 0, 10)
|
||||
} else {
|
||||
for i, a := range n.attributes {
|
||||
if bytes.Equal(a.Name, name) {
|
||||
n.attributes[i].Name = name
|
||||
n.attributes[i].Value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
n.attributes = append(n.attributes, Attribute{name, value})
|
||||
}
|
||||
|
||||
// SetAttributeString implements Node.SetAttributeString
|
||||
func (n *BaseNode) SetAttributeString(name string, value interface{}) {
|
||||
// n.SetAttribute(util.StringToReadOnlyBytes(name), value)
|
||||
}
|
||||
|
||||
// Attribute implements Node.Attribute.
|
||||
func (n *BaseNode) Attribute(name []byte) (interface{}, bool) {
|
||||
if n.attributes == nil {
|
||||
return nil, false
|
||||
}
|
||||
for i, a := range n.attributes {
|
||||
if bytes.Equal(a.Name, name) {
|
||||
return n.attributes[i].Value, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// AttributeString implements Node.AttributeString.
|
||||
func (n *BaseNode) AttributeString(s string) (interface{}, bool) {
|
||||
// return n.Attribute(util.StringToReadOnlyBytes(s))
|
||||
return nil, true
|
||||
}
|
||||
|
||||
// Attributes implements Node.Attributes
|
||||
func (n *BaseNode) Attributes() []Attribute {
|
||||
return n.attributes
|
||||
}
|
||||
|
||||
// RemoveAttributes implements Node.RemoveAttributes
|
||||
func (n *BaseNode) RemoveAttributes() {
|
||||
n.attributes = nil
|
||||
}
|
||||
|
||||
func (n *BaseNode) Dump(source []byte, level int) {
|
||||
}
|
||||
|
||||
// DumpHelper is a helper function to implement Node.Dump.
|
||||
// kv is pairs of an attribute name and an attribute value.
|
||||
// cb is a function called after wrote a name and attributes.
|
||||
func DumpHelper(v Node, source []byte, level int, kv map[string]string, cb func(int)) {
|
||||
name := v.Kind().String()
|
||||
indent := strings.Repeat(" ", level)
|
||||
fmt.Printf("%s%s {\n", indent, name)
|
||||
indent2 := strings.Repeat(" ", level+1)
|
||||
// if v.Type() == TypeBlock {
|
||||
// fmt.Printf("%sRawText: \"", indent2)
|
||||
// for i := 0; i < v.Lines().Len(); i++ {
|
||||
// line := v.Lines().At(i)
|
||||
// fmt.Printf("%s", line.Value(source))
|
||||
// }
|
||||
// fmt.Printf("\"\n")
|
||||
// fmt.Printf("%sHasBlankPreviousLines: %v\n", indent2, v.HasBlankPreviousLines())
|
||||
// }
|
||||
for name, value := range kv {
|
||||
fmt.Printf("%s%s: %s\n", indent2, name, value)
|
||||
}
|
||||
|
||||
if cb != nil {
|
||||
cb(level + 1)
|
||||
}
|
||||
|
||||
for c := v.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
c.Dump(source, level+1)
|
||||
}
|
||||
fmt.Printf("%s}\n", indent)
|
||||
}
|
||||
|
||||
// WalkStatus represents a current status of the Walk function.
|
||||
type WalkStatus int
|
||||
|
||||
const (
|
||||
// WalkStop indicates no more walking needed.
|
||||
WalkStop WalkStatus = iota + 1
|
||||
|
||||
// WalkSkipChildren indicates that Walk wont walk on children of current
|
||||
// node.
|
||||
WalkSkipChildren
|
||||
|
||||
// WalkContinue indicates that Walk can continue to walk.
|
||||
WalkContinue
|
||||
)
|
||||
|
||||
// Walker is a function that will be called when Walk find a
|
||||
// new node.
|
||||
// entering is set true before walks children, false after walked children.
|
||||
// If Walker returns error, Walk function immediately stop walking.
|
||||
type Walker func(n Node, entering bool) (WalkStatus, error)
|
||||
|
||||
// Walk walks a AST tree by the depth first search algorithm.
|
||||
func Walk(n Node, walker Walker) error {
|
||||
_, err := walkHelper(n, walker)
|
||||
return err
|
||||
}
|
||||
|
||||
func walkHelper(n Node, walker Walker) (WalkStatus, error) {
|
||||
status, err := walker(n, true)
|
||||
if err != nil || status == WalkStop {
|
||||
return status, err
|
||||
}
|
||||
if status != WalkSkipChildren {
|
||||
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if st, err := walkHelper(c, walker); err != nil || st == WalkStop {
|
||||
return WalkStop, err
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err = walker(n, false)
|
||||
if err != nil || status == WalkStop {
|
||||
return WalkStop, err
|
||||
}
|
||||
return WalkContinue, nil
|
||||
}
|
||||
121
vendor/github.com/wlevene/ini/ast/ast_node.go
generated
vendored
Normal file
121
vendor/github.com/wlevene/ini/ast/ast_node.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wlevene/ini/token"
|
||||
)
|
||||
|
||||
type SetcionNode struct {
|
||||
BaseNode
|
||||
Name token.Token
|
||||
}
|
||||
|
||||
var KindSetcion = NewNodeKind("Section")
|
||||
|
||||
// Kind implements Node.Kind.
|
||||
func (n *SetcionNode) Kind() NodeKind {
|
||||
return KindSetcion
|
||||
}
|
||||
|
||||
func (n *SetcionNode) Type() NodeType {
|
||||
return TypeDocNode
|
||||
}
|
||||
|
||||
func (n *SetcionNode) IsRaw() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Text implements Node.Text.
|
||||
func (n *SetcionNode) Text(source []byte) []byte {
|
||||
return []byte(n.Name.Literal)
|
||||
}
|
||||
|
||||
// Dump implements Node.Dump.
|
||||
func (n *SetcionNode) Dump(source []byte, level int) {
|
||||
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
name := n.Name.Literal
|
||||
m := map[string]string{
|
||||
"Section": fmt.Sprintf("[%v]", name),
|
||||
"Line": fmt.Sprintf("%v", n.Name.Line),
|
||||
}
|
||||
DumpHelper(n, source, level, m, nil)
|
||||
}
|
||||
|
||||
type KVNode struct {
|
||||
BaseNode
|
||||
Key token.Token
|
||||
Value token.Token
|
||||
Index int
|
||||
Line int
|
||||
}
|
||||
|
||||
var KindKVNode = NewNodeKind("KVNode")
|
||||
|
||||
// Kind implements Node.Kind.
|
||||
func (n *KVNode) Kind() NodeKind {
|
||||
return KindKVNode
|
||||
}
|
||||
|
||||
func (n *KVNode) Type() NodeType {
|
||||
return TypeDocNode
|
||||
}
|
||||
|
||||
func (n *KVNode) IsRaw() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *KVNode) Text(source []byte) []byte {
|
||||
return source
|
||||
}
|
||||
|
||||
// Dump implements Node.Dump.
|
||||
func (n *KVNode) Dump(source []byte, level int) {
|
||||
|
||||
m := map[string]string{
|
||||
"Key": fmt.Sprintf("%v", n.Key.Literal),
|
||||
"Value": fmt.Sprintf("%v", n.Value.Literal),
|
||||
"Line": fmt.Sprintf("%v", n.Key.Line),
|
||||
}
|
||||
|
||||
DumpHelper(n, source, level, m, nil)
|
||||
}
|
||||
|
||||
type CommentNode struct {
|
||||
BaseNode
|
||||
Comment token.Token
|
||||
}
|
||||
|
||||
var KindCommentNode = NewNodeKind("CommentNode")
|
||||
|
||||
// Kind implements Node.Kind.
|
||||
func (n *CommentNode) Kind() NodeKind {
|
||||
return KindCommentNode
|
||||
}
|
||||
|
||||
func (n *CommentNode) Type() NodeType {
|
||||
return TypeDocNode
|
||||
}
|
||||
|
||||
func (n *CommentNode) IsRaw() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *CommentNode) Text(source []byte) []byte {
|
||||
return source
|
||||
}
|
||||
|
||||
// Dump implements Node.Dump.
|
||||
func (n *CommentNode) Dump(source []byte, level int) {
|
||||
|
||||
m := map[string]string{
|
||||
"Comment": fmt.Sprintf("%v", n.Comment.Literal),
|
||||
"Line": fmt.Sprintf("%v", n.Comment.Line),
|
||||
}
|
||||
|
||||
DumpHelper(n, source, level, m, nil)
|
||||
}
|
||||
60
vendor/github.com/wlevene/ini/ast/doc.go
generated
vendored
Normal file
60
vendor/github.com/wlevene/ini/ast/doc.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package ast
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Doc struct {
|
||||
BaseNode
|
||||
|
||||
// KVs []*KVNode
|
||||
// SectS []*SetcionNode
|
||||
}
|
||||
|
||||
func NewDoc() *Doc {
|
||||
doc := &Doc{
|
||||
// KVs: make([]*KVNode, 0),
|
||||
// SectS: make([]*SetcionNode, 0),
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (doc *Doc) DumpV2() {
|
||||
|
||||
// for _, item := range doc.KVs {
|
||||
// item.Dump(nil, 0)
|
||||
// }
|
||||
|
||||
// for _, item := range doc.SectS {
|
||||
// item.Dump(nil, 0)
|
||||
// }
|
||||
DumpHelper(doc, nil, 0, nil, nil)
|
||||
}
|
||||
|
||||
var KindDocNode = NewNodeKind("INIDocNode")
|
||||
|
||||
// Kind implements Node.Kind.
|
||||
func (n *Doc) Kind() NodeKind {
|
||||
return KindDocNode
|
||||
}
|
||||
|
||||
func (n *Doc) Type() NodeType {
|
||||
return TypeDocNode
|
||||
}
|
||||
|
||||
func (n *Doc) IsRaw() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *Doc) Text(source []byte) []byte {
|
||||
return source
|
||||
}
|
||||
|
||||
// Dump implements Node.Dump.
|
||||
func (n *Doc) Dump(source []byte, level int) {
|
||||
|
||||
m := map[string]string{
|
||||
"doc": fmt.Sprintf("%v", string(source)),
|
||||
}
|
||||
|
||||
DumpHelper(n, source, level, m, nil)
|
||||
}
|
||||
597
vendor/github.com/wlevene/ini/ini.go
generated
vendored
Normal file
597
vendor/github.com/wlevene/ini/ini.go
generated
vendored
Normal file
@@ -0,0 +1,597 @@
|
||||
package ini
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/wlevene/ini/ast"
|
||||
"github.com/wlevene/ini/lexer"
|
||||
"github.com/wlevene/ini/parser"
|
||||
"github.com/wlevene/ini/token"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
// TODO: new section
|
||||
|
||||
type (
|
||||
Ini struct {
|
||||
currectSection *ast.SetcionNode
|
||||
src []byte // source
|
||||
l *lexer.Lexer
|
||||
p *parser.Parser
|
||||
doc *ast.Doc
|
||||
err error
|
||||
|
||||
watcher *fsnotify.Watcher
|
||||
exitWatchChan chan bool
|
||||
}
|
||||
)
|
||||
|
||||
func New() *Ini {
|
||||
|
||||
in := &Ini{
|
||||
doc: &ast.Doc{},
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
func (in *Ini) Err() error {
|
||||
return in.err
|
||||
}
|
||||
|
||||
func (in *Ini) LoadFile(file string) *Ini {
|
||||
|
||||
// read file content
|
||||
bts, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
in.err = err
|
||||
return in
|
||||
}
|
||||
|
||||
in.Load(bts)
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
func (in *Ini) WatchFile(file string) *Ini {
|
||||
|
||||
in.LoadFile(file)
|
||||
in.watch(file)
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
func (in *Ini) watch(file string) {
|
||||
if file == "" {
|
||||
return
|
||||
}
|
||||
|
||||
in.watcher, in.err = fsnotify.NewWatcher()
|
||||
in.exitWatchChan = make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-in.watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||
in.LoadFile(file)
|
||||
}
|
||||
case _, ok := <-in.watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case <-in.exitWatchChan:
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
in.err = in.watcher.Add(file)
|
||||
}
|
||||
|
||||
func (in *Ini) StopWatch() *Ini {
|
||||
|
||||
in.watcher.Close()
|
||||
in.exitWatchChan <- true
|
||||
return in
|
||||
}
|
||||
|
||||
func (in *Ini) Load(doc []byte) *Ini {
|
||||
|
||||
if len(doc) <= 0 {
|
||||
return in
|
||||
}
|
||||
|
||||
in.src = doc
|
||||
in.l = lexer.New(string(in.src))
|
||||
in.p = parser.New(in.l)
|
||||
|
||||
in.doc, in.err = in.p.ParseDocument()
|
||||
return in
|
||||
}
|
||||
|
||||
func (in *Ini) Dump() {
|
||||
|
||||
if in.doc == nil {
|
||||
return
|
||||
}
|
||||
|
||||
in.doc.DumpV2()
|
||||
}
|
||||
|
||||
func (this *Ini) Marshal2Map() map[string]interface{} {
|
||||
|
||||
if this.doc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if this.err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
kvMaps := make(map[string]interface{})
|
||||
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
kvMaps[kv_node.Key.Literal] = kv_node.Value.Literal
|
||||
}
|
||||
|
||||
if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
|
||||
secMap := make(map[string]interface{})
|
||||
|
||||
for kv := sect_node.FirstChild(); kv != nil; kv = kv.NextSibling() {
|
||||
if kvnode, ok := kv.(*ast.KVNode); ok {
|
||||
secMap[kvnode.Key.Literal] = kvnode.Value.Literal
|
||||
}
|
||||
}
|
||||
|
||||
kvMaps[sect_node.Name.Literal] = secMap
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return kvMaps
|
||||
}
|
||||
|
||||
func (this *Ini) Marshal2Json() []byte {
|
||||
|
||||
kvMaps := this.Marshal2Map()
|
||||
|
||||
if kvMaps == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := json.Marshal(kvMaps)
|
||||
this.err = err
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (this *Ini) Section(section string) *Ini {
|
||||
|
||||
if this.doc == nil {
|
||||
return this
|
||||
}
|
||||
|
||||
if this.err != nil {
|
||||
return this
|
||||
}
|
||||
|
||||
this.sectionForAstDoc(section)
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *Ini) Get(key string) string {
|
||||
return this.GetDef(key, "")
|
||||
}
|
||||
|
||||
func (this *Ini) GetDef(key string, def string) string {
|
||||
|
||||
if this.doc == nil ||
|
||||
this.err != nil {
|
||||
return def
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
return def
|
||||
}
|
||||
|
||||
tok := this.getToken(key)
|
||||
if tok.Type != token.TokenType_VALUE {
|
||||
return def
|
||||
}
|
||||
|
||||
return tok.Literal
|
||||
}
|
||||
|
||||
func (this *Ini) GetInt(key string) int {
|
||||
|
||||
return this.GetIntDef(key, 0)
|
||||
}
|
||||
|
||||
func (this *Ini) GetIntDef(key string, def int) int {
|
||||
|
||||
val := this.Get(key)
|
||||
if val == "" {
|
||||
return def
|
||||
}
|
||||
|
||||
ival, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return ival
|
||||
}
|
||||
|
||||
func (this *Ini) GetInt64(key string) int64 {
|
||||
|
||||
return this.GetInt64Def(key, 0)
|
||||
}
|
||||
|
||||
func (this *Ini) GetInt64Def(key string, def int64) int64 {
|
||||
|
||||
val := this.Get(key)
|
||||
if val == "" {
|
||||
return def
|
||||
}
|
||||
|
||||
ival, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return ival
|
||||
}
|
||||
|
||||
func (this *Ini) GetFloat64(key string) float64 {
|
||||
|
||||
return this.GetFloat64Def(key, 0)
|
||||
}
|
||||
|
||||
func (this *Ini) GetFloat64Def(key string, def float64) float64 {
|
||||
|
||||
val := this.Get(key)
|
||||
if val == "" {
|
||||
return def
|
||||
}
|
||||
|
||||
fval, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
return fval
|
||||
}
|
||||
|
||||
func (this *Ini) Set(key string, val interface{}) *Ini {
|
||||
|
||||
if this.doc == nil ||
|
||||
this.err != nil {
|
||||
return this
|
||||
}
|
||||
|
||||
if key == "" || val == nil {
|
||||
return this
|
||||
}
|
||||
|
||||
var val_str string
|
||||
switch val.(type) {
|
||||
case int:
|
||||
val_str = fmt.Sprintf("%d", val.(int))
|
||||
case int32:
|
||||
val_str = fmt.Sprintf("%d", val.(int32))
|
||||
case int64:
|
||||
val_str = fmt.Sprintf("%d", val.(int64))
|
||||
case float32:
|
||||
val_str = strconv.FormatFloat(float64(val.(float32)), 'f', -1, 32)
|
||||
case float64:
|
||||
val_str = strconv.FormatFloat(float64(val.(float64)), 'f', -1, 64)
|
||||
case string:
|
||||
val_str = val.(string)
|
||||
default:
|
||||
return this
|
||||
}
|
||||
|
||||
val_str = strings.Replace(val_str, "\n", "", -1)
|
||||
val_str = strings.Replace(val_str, "\t", "", -1)
|
||||
val_str = strings.Trim(val_str, " ")
|
||||
|
||||
this.setKVNode(key, val_str)
|
||||
|
||||
return this
|
||||
|
||||
}
|
||||
|
||||
func (this *Ini) Del(key string) *Ini {
|
||||
|
||||
if this.doc == nil ||
|
||||
this.err != nil {
|
||||
return this
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
return this
|
||||
}
|
||||
|
||||
if this.currectSection == nil {
|
||||
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
if kv_node.Key.Literal == key {
|
||||
this.doc.RemoveChild(this.doc, kv_node)
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
// continue
|
||||
// }
|
||||
}
|
||||
|
||||
} else {
|
||||
for c := this.currectSection.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
kvnodev2 := c.(*ast.KVNode)
|
||||
if kvnodev2.Key.Literal == key {
|
||||
this.currectSection.RemoveChild(this.currectSection, c)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *Ini) DelSection(section string) *Ini {
|
||||
if this.doc == nil ||
|
||||
this.err != nil {
|
||||
return this
|
||||
}
|
||||
|
||||
if section == "" {
|
||||
return this
|
||||
}
|
||||
|
||||
if this.currectSection == nil {
|
||||
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
|
||||
if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
if sect_node.Name.Literal == section {
|
||||
this.doc.RemoveChild(this.doc, sect_node)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// TODO: implement Save
|
||||
func (this *Ini) Save(filename string) *Ini {
|
||||
|
||||
if filename == "" {
|
||||
return this
|
||||
}
|
||||
|
||||
if this.doc == nil {
|
||||
return this
|
||||
}
|
||||
|
||||
var result string
|
||||
|
||||
is_last_type_comment := false
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
is_last_type_comment = false
|
||||
result = fmt.Sprintf("%s%s = %v\n", result, kv_node.Key.Literal, kv_node.Value.Literal)
|
||||
continue
|
||||
}
|
||||
|
||||
if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
|
||||
if !is_last_type_comment {
|
||||
result = fmt.Sprintf("%s\n", result)
|
||||
}
|
||||
|
||||
is_last_type_comment = false
|
||||
result = fmt.Sprintf("%s[%s]\n", result, sect_node.Name.Literal)
|
||||
|
||||
for c := sect_node.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
result = fmt.Sprintf("%s%s = %v\n", result, kv_node.Key.Literal, kv_node.Value.Literal)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if comm_node, ok := c.(*ast.CommentNode); ok {
|
||||
if !is_last_type_comment {
|
||||
result = fmt.Sprintf("%s\n", result)
|
||||
}
|
||||
|
||||
is_last_type_comment = true
|
||||
result = fmt.Sprintf("%s%s\n", result, comm_node.Comment.Literal)
|
||||
}
|
||||
}
|
||||
|
||||
this.err = os.Remove(filename)
|
||||
if this.err != nil {
|
||||
return this
|
||||
}
|
||||
|
||||
var data = []byte(result)
|
||||
this.err = ioutil.WriteFile(filename, data, 0666)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
func (this *Ini) sectionForAstDoc(section string) {
|
||||
|
||||
if this.doc == nil ||
|
||||
this.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
this.currectSection = nil
|
||||
if section == "" {
|
||||
return
|
||||
}
|
||||
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
|
||||
if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
|
||||
if sect_node.Name.Literal == section {
|
||||
this.currectSection = sect_node
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.currectSection = &ast.SetcionNode{
|
||||
Name: token.Token{
|
||||
Type: token.TokenType_SECTION,
|
||||
Literal: section,
|
||||
},
|
||||
}
|
||||
this.doc.AppendChild(this.doc, this.currectSection)
|
||||
}
|
||||
|
||||
func (this *Ini) getToken(key string) token.Token {
|
||||
|
||||
var tok token.Token
|
||||
|
||||
if key == "" {
|
||||
return tok
|
||||
}
|
||||
|
||||
if this.currectSection == nil {
|
||||
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
if kv_node.Key.Literal == key {
|
||||
tok = kv_node.Value
|
||||
return tok
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for c := this.currectSection.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
|
||||
kvnodev2 := c.(*ast.KVNode)
|
||||
if kvnodev2.Key.Literal == key {
|
||||
tok = kvnodev2.Value
|
||||
return tok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tok
|
||||
}
|
||||
|
||||
func (this *Ini) setKVNode(key string, val string) *Ini {
|
||||
|
||||
if key == "" || val == "" {
|
||||
return this
|
||||
}
|
||||
|
||||
line := 1
|
||||
found := false
|
||||
|
||||
if this.currectSection == nil {
|
||||
|
||||
var last_kv_node *ast.KVNode
|
||||
for c := this.doc.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
if kv_node, ok := c.(*ast.KVNode); ok {
|
||||
last_kv_node = kv_node
|
||||
if kv_node.Key.Literal == key {
|
||||
kv_node.Value.Literal = val
|
||||
return this
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// if sect_node, ok := c.(*ast.SetcionNode); ok {
|
||||
// continue
|
||||
// }
|
||||
}
|
||||
|
||||
kvnode := &ast.KVNode{
|
||||
Key: token.Token{
|
||||
Type: token.TokenType_KEY,
|
||||
Literal: key,
|
||||
Line: line,
|
||||
},
|
||||
Value: token.Token{
|
||||
Type: token.TokenType_VALUE,
|
||||
Literal: val,
|
||||
Line: line,
|
||||
},
|
||||
}
|
||||
|
||||
if last_kv_node == nil {
|
||||
this.doc.AppendChild(this.doc, kvnode)
|
||||
} else {
|
||||
this.doc.InsertAfter(this.doc, last_kv_node, kvnode)
|
||||
}
|
||||
|
||||
this.re_adjust_node_line()
|
||||
|
||||
} else {
|
||||
|
||||
for c := this.currectSection.FirstChild(); c != nil; c = c.NextSibling() {
|
||||
|
||||
kvnodev2 := c.(*ast.KVNode)
|
||||
line = kvnodev2.Key.Line + 1
|
||||
if kvnodev2.Key.Literal == key {
|
||||
kvnodev2.Value.Literal = val
|
||||
return this
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if found == false {
|
||||
|
||||
kvnode := &ast.KVNode{
|
||||
Key: token.Token{
|
||||
Type: token.TokenType_KEY,
|
||||
Literal: key,
|
||||
Line: line,
|
||||
},
|
||||
Value: token.Token{
|
||||
Type: token.TokenType_VALUE,
|
||||
Literal: val,
|
||||
Line: line,
|
||||
},
|
||||
}
|
||||
|
||||
this.currectSection.AppendChild(this.currectSection, kvnode)
|
||||
this.re_adjust_node_line()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// TODO: support
|
||||
func (this *Ini) re_adjust_node_line() {
|
||||
|
||||
}
|
||||
195
vendor/github.com/wlevene/ini/ini_tag.go
generated
vendored
Normal file
195
vendor/github.com/wlevene/ini/ini_tag.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
package ini
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
mp := New().Load(data).Marshal2Map()
|
||||
|
||||
fmt.Println("map:", mp)
|
||||
bindTag("ini", v, mp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bind binds the content of data into the struct s
|
||||
func bindTag(tagName string, s interface{}, data map[string]interface{}) interface{} {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := reflect.TypeOf(s)
|
||||
tk := t.Kind()
|
||||
|
||||
if tk != reflect.Ptr {
|
||||
return nil
|
||||
}
|
||||
|
||||
t = t.Elem()
|
||||
tk = t.Kind()
|
||||
|
||||
if tk != reflect.Struct {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(s).Elem()
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
fi := parseField(tagName, f)
|
||||
|
||||
fv := v.FieldByName(fi.Name)
|
||||
fk := fv.Kind()
|
||||
ft := fv.Type()
|
||||
|
||||
if v, ok := data[fi.Alias]; ok {
|
||||
vt := reflect.TypeOf(v)
|
||||
vk := vt.Kind()
|
||||
|
||||
if !vt.AssignableTo(ft) {
|
||||
|
||||
change_fun := func(k reflect.Kind, v interface{}) (val reflect.Value, err error) {
|
||||
|
||||
err = errors.New("unsupper kind")
|
||||
|
||||
var str_v string
|
||||
var ok bool
|
||||
if str_v, ok = v.(string); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// str_v = v.(string)
|
||||
|
||||
if k == reflect.Int {
|
||||
rv, er := strconv.Atoi(str_v)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Int8 {
|
||||
rv, er := strconv.ParseInt(str_v, 10, 8)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Int16 {
|
||||
rv, er := strconv.ParseInt(str_v, 10, 16)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Int32 {
|
||||
rv, er := strconv.ParseInt(str_v, 10, 32)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Int64 {
|
||||
rv, er := strconv.ParseInt(str_v, 10, 64)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Float32 {
|
||||
rv, er := strconv.ParseFloat(str_v, 32)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(float32(rv))
|
||||
err = nil
|
||||
}
|
||||
} else if k == reflect.Float64 {
|
||||
rv, er := strconv.ParseFloat(str_v, 64)
|
||||
if er == nil {
|
||||
val = reflect.ValueOf(rv)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
return val, err
|
||||
}
|
||||
|
||||
val, err := change_fun(fk, v)
|
||||
|
||||
if err == nil {
|
||||
fv.Set(val)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
fv.Set(reflect.ValueOf(v))
|
||||
continue
|
||||
}
|
||||
|
||||
if fk == reflect.Struct && vk == reflect.Map {
|
||||
|
||||
if fv.CanInterface() {
|
||||
bindTag(tagName, fv.Addr().Interface(), v.(map[string]interface{}))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func bindSlice(tagName string, s reflect.Value, data []interface{}) {
|
||||
// sk := s.Kind()
|
||||
et := s.Type().Elem()
|
||||
ek := et.Kind()
|
||||
|
||||
ret := reflect.MakeSlice(et, s.Len(), s.Cap())
|
||||
vet := reflect.TypeOf(data).Elem()
|
||||
if vet.AssignableTo(et) {
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
ret.Index(i).Set(reflect.ValueOf(data[i]))
|
||||
}
|
||||
} else if ek == reflect.Struct {
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
// v := Bind(tagName, ret.Index(i).Addr().Interface(), data[i].(map[string]interface{}))
|
||||
v := bindTag(tagName, ret.Index(i).Addr().Interface(), data[i].(map[string]interface{}))
|
||||
ret.Index(i).Set(reflect.ValueOf(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
Alias string
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
// ParseField parses [FieldInfo] for the given struct field [f] from struct tag with name [tagName]
|
||||
func parseField(tagName string, f reflect.StructField) *fieldInfo {
|
||||
var parts []string
|
||||
alias := f.Name
|
||||
|
||||
tag, tagOk := f.Tag.Lookup(tagName)
|
||||
if tagOk {
|
||||
partsTemp := strings.Split(tag, ",")
|
||||
parts = make([]string, 0, len(partsTemp))
|
||||
for i := 0; i < len(partsTemp); i++ {
|
||||
part := strings.TrimSpace(partsTemp[i])
|
||||
if len(part) != 0 {
|
||||
parts = append(parts, part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(parts) != 0 {
|
||||
alias = parts[0]
|
||||
// TODO parse other tags
|
||||
}
|
||||
|
||||
return &fieldInfo{
|
||||
Alias: alias,
|
||||
Name: f.Name,
|
||||
}
|
||||
}
|
||||
234
vendor/github.com/wlevene/ini/lexer/lexer.go
generated
vendored
Normal file
234
vendor/github.com/wlevene/ini/lexer/lexer.go
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
package lexer
|
||||
|
||||
import (
|
||||
"github.com/wlevene/ini/token"
|
||||
)
|
||||
|
||||
const (
|
||||
LineBreak = '\n'
|
||||
)
|
||||
|
||||
type Lexer struct {
|
||||
Input []byte
|
||||
char byte
|
||||
position int
|
||||
read_position int
|
||||
line int
|
||||
}
|
||||
|
||||
func New(input string) *Lexer {
|
||||
l := &Lexer{Input: []byte(input)}
|
||||
l.readChar()
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Lexer) peekChar() byte {
|
||||
if l.read_position >= len(l.Input) {
|
||||
return 0
|
||||
} else {
|
||||
return l.Input[l.read_position]
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) readChar() {
|
||||
if l.read_position >= len(l.Input) {
|
||||
l.char = 0
|
||||
} else {
|
||||
l.char = l.Input[l.read_position]
|
||||
}
|
||||
|
||||
if l.char == LineBreak {
|
||||
l.line++
|
||||
}
|
||||
|
||||
l.position = l.read_position
|
||||
l.read_position++
|
||||
|
||||
}
|
||||
|
||||
func (l *Lexer) readLine() []byte {
|
||||
position := l.position
|
||||
for {
|
||||
if l.char == LineBreak {
|
||||
break
|
||||
}
|
||||
l.readChar()
|
||||
}
|
||||
|
||||
return l.Input[position:l.position]
|
||||
}
|
||||
|
||||
func (l *Lexer) skipWhitespace() {
|
||||
for l.char == ' ' ||
|
||||
l.char == '\t' ||
|
||||
l.char == LineBreak ||
|
||||
l.char == '\r' {
|
||||
l.readChar()
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) skipspace() {
|
||||
for l.char == ' ' {
|
||||
l.readChar()
|
||||
}
|
||||
|
||||
// for l.char == ' ' ||
|
||||
// l.char == '\t' {
|
||||
// l.readChar()
|
||||
// }
|
||||
}
|
||||
|
||||
func (l *Lexer) skipline() {
|
||||
|
||||
for {
|
||||
if l.char == LineBreak {
|
||||
// l.line++
|
||||
break
|
||||
}
|
||||
l.readChar()
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) NextToken() token.Token {
|
||||
var tok token.Token
|
||||
var ch byte
|
||||
l.skipWhitespace()
|
||||
|
||||
switch l.char {
|
||||
case '[':
|
||||
tok = newToken(token.TokenType_LBRACKET, l.char, l.line)
|
||||
case '=':
|
||||
tok = newToken(token.TokenType_ASSIGN, l.char, l.line)
|
||||
case ']':
|
||||
tok = newToken(token.TokenType_RBRACKET, l.char, l.line)
|
||||
case 0:
|
||||
tok.Literal = ""
|
||||
tok.Type = token.TokenType_EOF
|
||||
return tok
|
||||
case '#':
|
||||
fallthrough
|
||||
case ';':
|
||||
tok.Line = l.line
|
||||
tok.Literal = string(l.readLine())
|
||||
tok.Type = token.TokenType_COMMENT
|
||||
|
||||
default:
|
||||
tok.Line = l.line
|
||||
tok.Literal = string(l.readStatement())
|
||||
l.skipspace()
|
||||
|
||||
ch = l.char
|
||||
|
||||
if ch == '=' {
|
||||
tok.Type = token.TokenType_KEY
|
||||
} else if ch == ']' {
|
||||
tok.Type = token.TokenType_SECTION
|
||||
} else if ch == LineBreak {
|
||||
tok.Type = token.TokenType_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
l.readChar()
|
||||
return tok
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
func (s *lexer) getNextToken() token.Token {
|
||||
reToken:
|
||||
ch := s.peek()
|
||||
switch {
|
||||
case isSpace(ch):
|
||||
s.skipWhitespace()
|
||||
goto reToken
|
||||
case isEOF(ch):
|
||||
return s.NewToken(token.EOF).Lit(string(s.read()))
|
||||
case ch == ';':
|
||||
return s.NewToken(token.Semicolon).Lit(string(s.read()))
|
||||
case ch == '{':
|
||||
return s.NewToken(token.BlockStart).Lit(string(s.read()))
|
||||
case ch == '}':
|
||||
return s.NewToken(token.BlockEnd).Lit(string(s.read()))
|
||||
case ch == '#':
|
||||
return s.scanComment()
|
||||
case ch == '$':
|
||||
return s.scanVariable()
|
||||
case isQuote(ch):
|
||||
return s.scanQuotedString(ch)
|
||||
default:
|
||||
return s.scanKeyword()
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
func isLetter(ch byte) bool {
|
||||
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
|
||||
}
|
||||
|
||||
func isDigit(ch byte) bool {
|
||||
return ('0' <= ch && ch <= '9') || ch == '.'
|
||||
}
|
||||
|
||||
func newToken(tokenType token.TokenType, ch byte, line int) token.Token {
|
||||
return token.Token{Type: tokenType,
|
||||
Literal: string(ch),
|
||||
Line: line,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lexer) readStatement() []byte {
|
||||
position := l.position
|
||||
for l.char != LineBreak &&
|
||||
l.char != '=' &&
|
||||
l.char != ']' &&
|
||||
l.char != ' ' {
|
||||
|
||||
l.readChar()
|
||||
}
|
||||
return l.Input[position:l.position]
|
||||
}
|
||||
|
||||
func (l *Lexer) readSection() token.Token {
|
||||
var tok token.Token
|
||||
if l.char != '[' {
|
||||
return tok
|
||||
}
|
||||
position := l.position
|
||||
|
||||
for {
|
||||
if l.char != ']' {
|
||||
l.readChar()
|
||||
}
|
||||
|
||||
if l.char == LineBreak {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return token.Token{
|
||||
Type: token.TokenType_SECTION,
|
||||
Literal: string(l.Input[position:l.position]),
|
||||
Line: l.line,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
func (s *lexer) read() rune {
|
||||
ch, _, err := s.reader.ReadRune()
|
||||
if err != nil {
|
||||
return rune(token.EOF)
|
||||
}
|
||||
|
||||
if ch == '\n' {
|
||||
s.column = 1
|
||||
s.line++
|
||||
} else {
|
||||
s.column++
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
*/
|
||||
BIN
vendor/github.com/wlevene/ini/logo.png
generated
vendored
Normal file
BIN
vendor/github.com/wlevene/ini/logo.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
113
vendor/github.com/wlevene/ini/parser/parser.go
generated
vendored
Normal file
113
vendor/github.com/wlevene/ini/parser/parser.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"github.com/wlevene/ini/ast"
|
||||
"github.com/wlevene/ini/lexer"
|
||||
"github.com/wlevene/ini/token"
|
||||
)
|
||||
|
||||
// type (
|
||||
// prefixParseFn func() ast.Expression
|
||||
// infixParseFn func(ast.Expression) ast.Expression
|
||||
// )
|
||||
|
||||
type Parser struct {
|
||||
lexer *lexer.Lexer
|
||||
errors []string
|
||||
currentToken token.Token
|
||||
peekToken token.Token
|
||||
|
||||
// prefixParseFns map[token.TokenType]prefixParseFn
|
||||
// infixParseFns map[token.TokenType]infixParseFn
|
||||
}
|
||||
|
||||
func New(l *lexer.Lexer) *Parser {
|
||||
p := &Parser{
|
||||
lexer: l,
|
||||
errors: []string{},
|
||||
}
|
||||
|
||||
// p.prefixParseFns = make(map[token.Type]prefixParseFn)
|
||||
// p.registerPrefix(token.INTEGER, p.parseIntegerLiteral)
|
||||
|
||||
// p.infixParseFns = make(map[token.Type]infixParseFn)
|
||||
// p.registerInfix(token.PLUS, p.parseInfixExpression)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) ParseDocument() (doc *ast.Doc, err error) {
|
||||
|
||||
doc = ast.NewDoc()
|
||||
|
||||
// Read two tokens, so currentToken and peekToken are both set.
|
||||
p.nextToken()
|
||||
p.nextToken()
|
||||
|
||||
var curSection *ast.SetcionNode
|
||||
var KV *ast.KVNode
|
||||
|
||||
for !p.curTokenIs(token.TokenType_EOF) {
|
||||
|
||||
if p.currentToken.Type == token.TokenType_SECTION {
|
||||
|
||||
curSection = nil
|
||||
curSection = &ast.SetcionNode{
|
||||
Name: p.currentToken,
|
||||
}
|
||||
|
||||
if curSection != nil {
|
||||
doc.AppendChild(doc, curSection)
|
||||
}
|
||||
|
||||
} else if p.currentToken.Type == token.TokenType_KEY {
|
||||
KV = nil
|
||||
KV = &ast.KVNode{}
|
||||
KV.Key = p.currentToken
|
||||
|
||||
} else if p.currentToken.Type == token.TokenType_VALUE {
|
||||
if KV != nil {
|
||||
KV.Value = p.currentToken
|
||||
if curSection != nil {
|
||||
curSection.AppendChild(curSection, KV)
|
||||
} else {
|
||||
doc.AppendChild(doc, KV)
|
||||
}
|
||||
}
|
||||
} else if p.currentToken.Type == token.TokenType_COMMENT {
|
||||
comment := &ast.CommentNode{
|
||||
Comment: p.currentToken,
|
||||
}
|
||||
doc.AppendChild(doc, comment)
|
||||
}
|
||||
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
return doc, nil
|
||||
}
|
||||
func (p *Parser) nextToken() {
|
||||
p.currentToken = p.peekToken
|
||||
p.peekToken = p.lexer.NextToken()
|
||||
|
||||
}
|
||||
|
||||
func (p *Parser) curTokenIs(t token.TokenType) bool {
|
||||
return p.currentToken.Type == t
|
||||
}
|
||||
|
||||
func (p *Parser) peekTokenIs(t token.TokenType) bool {
|
||||
return p.peekToken.Type == t
|
||||
}
|
||||
|
||||
// func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {
|
||||
// p.prefixParseFns[tokenType] = fn
|
||||
// }
|
||||
|
||||
// func (p *Parser) registerInfix(tokenType token.TokenType, fn infixParseFn) {
|
||||
// p.infixParseFns[tokenType] = fn
|
||||
// }
|
||||
|
||||
func (p *Parser) peekTokenAtSameLine() bool {
|
||||
return p.currentToken.Line == p.peekToken.Line && p.peekToken.Type != token.TokenType_EOF
|
||||
}
|
||||
4
vendor/github.com/wlevene/ini/save.ini
generated
vendored
Normal file
4
vendor/github.com/wlevene/ini/save.ini
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
a1 = 1
|
||||
|
||||
[s1]
|
||||
a2 = v2
|
||||
32
vendor/github.com/wlevene/ini/test.ini
generated
vendored
Normal file
32
vendor/github.com/wlevene/ini/test.ini
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
; this is comment
|
||||
; author levene
|
||||
; date 2021-8-1
|
||||
|
||||
|
||||
a='23'34?::'<>,.'
|
||||
c=d
|
||||
|
||||
[s1]
|
||||
k=67676
|
||||
k1 =fdasf
|
||||
k2= sdafj3490&@)34 34w2
|
||||
|
||||
# comment
|
||||
# 12.0.0.1
|
||||
[s2]
|
||||
|
||||
k=3
|
||||
|
||||
|
||||
k2=945
|
||||
k3=-435
|
||||
k4=0.0.0.0
|
||||
|
||||
k5=127.0.0.1
|
||||
k6=levene@github.com
|
||||
|
||||
k7=~/.path.txt
|
||||
k8=./34/34/uh.txt
|
||||
|
||||
k9=234@!@#$%^&*()324
|
||||
k10='23'34?::'<>,.'
|
||||
18
vendor/github.com/wlevene/ini/test2.ini
generated
vendored
Normal file
18
vendor/github.com/wlevene/ini/test2.ini
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
[s2]
|
||||
|
||||
k=3
|
||||
|
||||
|
||||
k2=945
|
||||
k3=-435
|
||||
k4=0.0.0.0
|
||||
|
||||
k5=127.0.0.1
|
||||
k6=levene@github.com
|
||||
|
||||
k7=~/.path.txt
|
||||
k8=./34/34/uh.txt
|
||||
|
||||
k9=234@!@#$%^&*()324
|
||||
k10='23'34?::'<>,.'
|
||||
52
vendor/github.com/wlevene/ini/token/token.go
generated
vendored
Normal file
52
vendor/github.com/wlevene/ini/token/token.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package token
|
||||
|
||||
import "fmt"
|
||||
|
||||
type TokenType string
|
||||
|
||||
const (
|
||||
TokenType_ILLEGAL = "ILLEGAL"
|
||||
TokenType_EOF = "EOF"
|
||||
Ident = "Ident"
|
||||
|
||||
TokenType_SECTION = "SECTION"
|
||||
TokenType_KEY = "KEY"
|
||||
TokenType_VALUE = "VALUE"
|
||||
TokenType_COMMENT = "#"
|
||||
TokenType_COMMENT2 = "#"
|
||||
|
||||
TokenType_ASSIGN = "="
|
||||
TokenType_LBRACKET = "["
|
||||
TokenType_RBRACKET = "]"
|
||||
|
||||
RETURN = "RETURN"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
Type TokenType
|
||||
Literal string
|
||||
Line int
|
||||
}
|
||||
|
||||
var keywords = map[string]TokenType{
|
||||
"return": RETURN,
|
||||
}
|
||||
|
||||
func LookupIdent(ident string) TokenType {
|
||||
if tok, ok := keywords[ident]; ok {
|
||||
return tok
|
||||
}
|
||||
return Ident
|
||||
}
|
||||
|
||||
func (t Token) String() string {
|
||||
return fmt.Sprintf("{Type:%s,Literal:\"%s\" Linie:%d}",
|
||||
t.Type,
|
||||
t.Literal,
|
||||
t.Line)
|
||||
}
|
||||
|
||||
//Is check type of a token
|
||||
func (t Token) Is(typ TokenType) bool {
|
||||
return t.Type == typ
|
||||
}
|
||||
Reference in New Issue
Block a user