From b5798d67b7f371dbffbe0591471d7f2ea733de7a Mon Sep 17 00:00:00 2001 From: Walter Schulze Date: Mon, 13 Jan 2025 18:48:25 +0000 Subject: [PATCH] delete parser This way the xml parser is independent of other parsers --- .github/workflows/build.yml | 14 +- COPIED_FROM_GO | 2 +- README.md | 6 +- go.mod | 4 +- go.sum | 2 + parser/debug/doc.go | 2 - parser/debug/example.go | 70 ---- parser/debug/log.go | 154 ------- parser/debug/node.go | 36 -- parser/debug/type.go | 25 -- parser/debug/value.go | 129 ------ parser/debug/walk.go | 178 -------- parser/errors.go | 37 -- parser/json/json.go | 627 ----------------------------- parser/json/json_test.go | 163 -------- parser/json/unquote.go | 149 ------- parser/parser.go | 74 ---- parser/reflect/reflect.go | 199 --------- parser/reflect/reflect_test.go | 41 -- {parser/xml => xml}/bytes_decl.go | 0 {parser/xml => xml}/marshal.go | 0 {parser/xml => xml}/min.go | 0 {parser/xml => xml}/parser.go | 0 {parser/xml => xml}/parser_test.go | 0 {parser/xml => xml}/read.go | 0 {parser/xml => xml}/typeinfo.go | 0 {parser/xml => xml}/xml.go | 0 27 files changed, 15 insertions(+), 1897 deletions(-) delete mode 100644 parser/debug/doc.go delete mode 100644 parser/debug/example.go delete mode 100644 parser/debug/log.go delete mode 100644 parser/debug/node.go delete mode 100644 parser/debug/type.go delete mode 100644 parser/debug/value.go delete mode 100644 parser/debug/walk.go delete mode 100644 parser/errors.go delete mode 100644 parser/json/json.go delete mode 100644 parser/json/json_test.go delete mode 100644 parser/json/unquote.go delete mode 100644 parser/parser.go delete mode 100644 parser/reflect/reflect.go delete mode 100644 parser/reflect/reflect_test.go rename {parser/xml => xml}/bytes_decl.go (100%) rename {parser/xml => xml}/marshal.go (100%) rename {parser/xml => xml}/min.go (100%) rename {parser/xml => xml}/parser.go (100%) rename {parser/xml => xml}/parser_test.go (100%) rename {parser/xml => xml}/read.go (100%) rename {parser/xml => xml}/typeinfo.go (100%) rename {parser/xml => xml}/xml.go (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a13ec9b..f8cd986 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,18 +9,18 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - path: gopath/github.com/katydid/parser-go + path: gopath/github.com/katydid/parser-go-xml - name: Setup Go uses: actions/setup-go@v3 with: go-version: 1.23 - name: Fetch dependencies run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml go mod download -x - name: Install tools run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml go install -x github.com/awalterschulze/checklicense - name: env run: env && go env && pwd @@ -28,17 +28,17 @@ jobs: run: tree - name: Build run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml make build - name: Test run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml make test - name: Checklicencse run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml make checklicense - name: Diff run: | - cd gopath/github.com/katydid/parser-go + cd gopath/github.com/katydid/parser-go-xml make diff diff --git a/COPIED_FROM_GO b/COPIED_FROM_GO index 6aa5cfd..3e46ab6 100644 --- a/COPIED_FROM_GO +++ b/COPIED_FROM_GO @@ -1,4 +1,4 @@ -Parts of the code in parser/xml and parser/json have been copied from the go standard library +Parts of the code in the xml folder have been copied from the go standard library Copyright (c) 2012 The Go Authors. All rights reserved. diff --git a/README.md b/README.md index dd41b8f..48d48cf 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -## parser-go +## parser-go-xml -Parser interface for Go. - -This includes tools for developing implementations of the parser interface, for example the `debug` package. +Parser for XML in Go diff --git a/go.mod b/go.mod index edafcc5..5539e79 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,7 @@ -module github.com/katydid/parser-go +module github.com/katydid/parser-go-xml go 1.23 +require github.com/katydid/parser-go v0.5.0 + require github.com/awalterschulze/checklicense v1.0.0 diff --git a/go.sum b/go.sum index 9467359..07f4fa1 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/awalterschulze/checklicense v1.0.0 h1:SiRilt26Q+2M238VbXw+e5826mxPypvsj/xgglHDHW8= github.com/awalterschulze/checklicense v1.0.0/go.mod h1:oUHvoD4crryzAwDwtdQqCnaZRznAvZE64edH9ukb1K4= +github.com/katydid/parser-go v0.5.0 h1:47Q2bnGzEwRTdb1q8IjC3t7FGtxHd/LDF9q7ASuk7as= +github.com/katydid/parser-go v0.5.0/go.mod h1:1BwRfDlyRgDlAaURZ4FXi7IzHqWKTsrCdsstLsFeQho= diff --git a/parser/debug/doc.go b/parser/debug/doc.go deleted file mode 100644 index 5d2cb1f..0000000 --- a/parser/debug/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -//The debug package is great for testing and debugging of parser.Interface implementations. -package debug diff --git a/parser/debug/example.go b/parser/debug/example.go deleted file mode 100644 index 5bcf7f4..0000000 --- a/parser/debug/example.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -// Input is a sample instance of the Debug struct. -var Input = &Debug{ - A: int64(1), - B: []string{"b2", "b3"}, - C: &Debug{ - A: int64(2), - D: ptr(int32(3)), - E: []*Debug{ - { - B: []string{"b4"}, - }, - { - B: []string{"b5"}, - }, - }, - }, - D: ptr(int32(4)), - F: []uint32{5}, -} - -// Output is a sample instance of Nodes that repesents the Input variable after it has been parsed by Walk. -var Output = Nodes{ - Field(`A`, `1`), - Nested(`B`, - Field(`0`, `b2`), - Field(`1`, `b3`), - ), - Nested(`C`, - Field(`A`, `2`), - Field(`D`, `3`), - Nested(`E`, - Nested(`0`, - Field(`A`, `0`), - Nested(`B`, - Field(`0`, `b4`), - ), - ), - Nested(`1`, - Field(`A`, `0`), - Nested(`B`, - Field(`0`, `b5`), - ), - ), - ), - ), - Field(`D`, `4`), - Nested(`F`, - Field(`0`, `5`), - ), -} - -func ptr[A any](a A) *A { - return &a -} diff --git a/parser/debug/log.go b/parser/debug/log.go deleted file mode 100644 index c24aa35..0000000 --- a/parser/debug/log.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -import ( - "log" - "os" - "path/filepath" - "runtime" - "strconv" - "time" - - "github.com/katydid/parser-go/parser" -) - -// Logger is an interface for a type that is made to log debug info. -type Logger interface { - Printf(format string, v ...interface{}) -} - -// NewLineLogger returns a logger that logs the line at which the Printf method was called to stderr. -func NewLineLogger() Logger { - return &line{log.New(os.Stderr, "", 0)} -} - -type line struct { - l Logger -} - -func (l *line) Printf(format string, v ...interface{}) { - _, thisfile, _, ok := runtime.Caller(0) - if !ok { - l.l.Printf(":0: "+format, v...) - return - } - i := 0 - for { - i++ - _, file, line, ok := runtime.Caller(i) - if !ok { - l.l.Printf(":"+strconv.Itoa(i)+": "+format, v...) - return - } - if file == thisfile { - continue - } - _, name := filepath.Split(file) - l.l.Printf(name+":"+strconv.Itoa(line)+": "+format, v...) - return - } -} - -// NewDelayLogger returns a logger that sleeps after every log. -// This is useful for debugging infinite loops. -func NewDelayLogger(delay time.Duration) Logger { - return &d{ - delay: delay, - log: NewLineLogger(), - } -} - -type d struct { - log Logger - delay time.Duration -} - -func (d *d) Printf(format string, v ...interface{}) { - d.log.Printf(format, v...) - time.Sleep(d.delay) -} - -type l struct { - name string - s parser.Interface - l Logger - copies int -} - -// NewLogger returns a parser that when called returns and logs the value returned by the argument parser to the argument logger. -func NewLogger(s parser.Interface, logger Logger) parser.Interface { - return &l{"parser", s, logger, 0} -} - -func (l *l) Double() (float64, error) { - v, err := l.s.Double() - l.l.Printf(l.name+".Double() (%v, %v)", v, err) - return v, err -} - -func (l *l) Int() (int64, error) { - v, err := l.s.Int() - l.l.Printf(l.name+".Int() (%v, %v)", v, err) - return v, err -} - -func (l *l) Uint() (uint64, error) { - v, err := l.s.Uint() - l.l.Printf(l.name+".Uint() (%v, %v)", v, err) - return v, err -} - -func (l *l) Bool() (bool, error) { - v, err := l.s.Bool() - l.l.Printf(l.name+".Bool() (%v, %v)", v, err) - return v, err -} - -func (l *l) String() (string, error) { - v, err := l.s.String() - l.l.Printf(l.name+".String() (%v, %v)", v, err) - return v, err -} - -func (l *l) Bytes() ([]byte, error) { - v, err := l.s.Bytes() - l.l.Printf(l.name+".Bytes() (%v, %v)", v, err) - return v, err -} - -func (l *l) Next() error { - err := l.s.Next() - l.l.Printf(l.name+".Next() (%v)", err) - return err -} - -func (l *l) IsLeaf() bool { - v := l.s.IsLeaf() - l.l.Printf(l.name+".IsLeaf() (%v)", v) - return v -} - -func (l *l) Up() { - l.s.Up() - l.l.Printf(l.name + ".Up()") - return -} - -func (l *l) Down() { - l.s.Down() - l.l.Printf(l.name + ".Down()") - return -} diff --git a/parser/debug/node.go b/parser/debug/node.go deleted file mode 100644 index 268ccf2..0000000 --- a/parser/debug/node.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -// Field is a helper function for creating a Node with a label and one child label. -// This is how a field with a value is typically represented. -func Field(name string, value string) Node { - return Node{ - Label: name, - Children: Nodes{ - Node{ - Label: value, - }, - }, - } -} - -// Nested is a helper function for creating a Node. -func Nested(name string, fs ...Node) Node { - return Node{ - Label: name, - Children: Nodes(fs), - } -} diff --git a/parser/debug/type.go b/parser/debug/type.go deleted file mode 100644 index ade7711..0000000 --- a/parser/debug/type.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -type Debug struct { - A int64 - B []string `json:"B,omitempty"` - C *Debug `json:"C,omitempty"` - D *int32 `json:"D,omitempty"` - E []*Debug `json:"E,omitempty"` - F []uint32 `json:"F,omitempty"` - G *float64 `json:"G,omitempty"` -} diff --git a/parser/debug/value.go b/parser/debug/value.go deleted file mode 100644 index c9683e0..0000000 --- a/parser/debug/value.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -import ( - "github.com/katydid/parser-go/parser" -) - -type errValue struct{} - -func (*errValue) Double() (float64, error) { - return 0, parser.ErrNotDouble -} - -func (*errValue) Bytes() ([]byte, error) { - return nil, parser.ErrNotBytes -} - -func (*errValue) Int() (int64, error) { - return 0, parser.ErrNotInt -} - -func (*errValue) Bool() (bool, error) { - return false, parser.ErrNotBool -} - -func (*errValue) Uint() (uint64, error) { - return 0, parser.ErrNotUint -} - -func (*errValue) String() (string, error) { - return "", parser.ErrNotString -} - -type doubleValue struct { - *errValue - v float64 -} - -// NewDoubleValue wraps a native go type into a parser.Value. -func NewDoubleValue(v float64) parser.Value { - return &doubleValue{&errValue{}, v} -} - -func (v *doubleValue) Double() (float64, error) { - return v.v, nil -} - -type intValue struct { - *errValue - v int64 -} - -// NewIntValue wraps a native go type into a parser.Value. -func NewIntValue(v int64) parser.Value { - return &intValue{&errValue{}, v} -} - -func (v *intValue) Int() (int64, error) { - return v.v, nil -} - -type uintValue struct { - *errValue - v uint64 -} - -// NewUintValue wraps a native go type into a parser.Value. -func NewUintValue(v uint64) parser.Value { - return &uintValue{&errValue{}, v} -} - -func (v *uintValue) Uint() (uint64, error) { - return v.v, nil -} - -type boolValue struct { - *errValue - v bool -} - -// NewBoolValue wraps a native go type into a parser.Value. -func NewBoolValue(v bool) parser.Value { - return &boolValue{&errValue{}, v} -} - -func (v *boolValue) Bool() (bool, error) { - return v.v, nil -} - -type stringValue struct { - *errValue - v string -} - -// NewStringValue wraps a native go type into a parser.Value. -func NewStringValue(v string) parser.Value { - return &stringValue{&errValue{}, v} -} - -func (v *stringValue) String() (string, error) { - return v.v, nil -} - -type bytesValue struct { - *errValue - v []byte -} - -// NewBytesValue wraps a native go type into a parser.Value. -func NewBytesValue(v []byte) parser.Value { - return &bytesValue{&errValue{}, v} -} - -func (v *bytesValue) Bytes() ([]byte, error) { - return v.v, nil -} diff --git a/parser/debug/walk.go b/parser/debug/walk.go deleted file mode 100644 index 01e36b6..0000000 --- a/parser/debug/walk.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package debug - -import ( - "fmt" - "io" - "math/rand" - "strings" - "time" - - "github.com/katydid/parser-go/parser" -) - -func getValue(p parser.Interface) interface{} { - var v interface{} - var err error - v, err = p.Int() - if err == nil { - return v - } - v, err = p.Uint() - if err == nil { - return v - } - v, err = p.Double() - if err == nil { - return v - } - v, err = p.Bool() - if err == nil { - return v - } - v, err = p.String() - if err == nil { - return v - } - v, err = p.Bytes() - if err == nil { - return v - } - return nil -} - -// Node is a type that represents a node in a tree. -// It has a label an children nodes. -type Node struct { - Label string - Children Nodes -} - -// String returns a string representation of Node. -func (this Node) String() string { - if len(this.Children) == 0 { - return this.Label - } - return this.Label + ":" + this.Children.String() -} - -// Equal returns whether two Nodes are the same. -func (this Node) Equal(that Node) bool { - if this.Label != that.Label { - return false - } - if !this.Children.Equal(that.Children) { - return false - } - return true -} - -// Nodes is a list of Node. -type Nodes []Node - -// String returns a string representation of Nodes. -func (this Nodes) String() string { - ss := make([]string, len(this)) - for i := range this { - ss[i] = this[i].String() - } - return "{" + strings.Join(ss, ",") + "}" -} - -// Equal returns whether two Node lists are equal. -func (this Nodes) Equal(that Nodes) bool { - if len(this) != len(that) { - return false - } - for i := range this { - if !this[i].Equal(that[i]) { - return false - } - } - return true -} - -// Walk walks through the whole parser in a top down manner and records the values into a Nodes structute. -func Walk(p parser.Interface) Nodes { - a := make(Nodes, 0) - for { - if err := p.Next(); err != nil { - if err == io.EOF { - break - } else { - panic(err) - } - } - value := getValue(p) - if p.IsLeaf() { - a = append(a, Node{fmt.Sprintf("%v", value), nil}) - } else { - name := fmt.Sprintf("%v", value) - p.Down() - v := Walk(p) - p.Up() - a = append(a, Node{name, v}) - } - } - return a -} - -// NewRand returns a random integer generator, that can be used with RandomWalk. -// Its seed is the current time. -func NewRand() Rand { - return rand.New(rand.NewSource(time.Now().UnixNano())) -} - -// Rand is a subset of the interface that is implemented by math/rand representing only the methods used by the RandomWalk function. -type Rand interface { - Intn(n int) int -} - -// RandomWalk does a random walk of the parser, given two probabilities. -// -// next is passed to r.Intn and when a zero value is returned the Next method on the parser is called. -// down is passed to r.Intn and when a non zero value is returned the Down method on the parser is called. -// -// RandomWalk is great for testing that the implemented parser can handle random skipping of parts of the tree. -func RandomWalk(p parser.Interface, r Rand, next, down int) Nodes { - a := make(Nodes, 0) - for { - if r.Intn(next) == 0 { - break - } - if err := p.Next(); err != nil { - if err == io.EOF { - break - } else { - panic(err) - } - } - value := getValue(p) - if p.IsLeaf() { - a = append(a, Node{fmt.Sprintf("%#v", value), nil}) - } else { - name := fmt.Sprintf("%#v", value) - var v Nodes - if r.Intn(down) != 0 { - p.Down() - v = RandomWalk(p, r, next, down) - p.Up() - } - a = append(a, Node{name, v}) - } - } - return a -} diff --git a/parser/errors.go b/parser/errors.go deleted file mode 100644 index 9bd7d69..0000000 --- a/parser/errors.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package parser - -import ( - "fmt" -) - -//ErrNotDouble is an error that represents a type error. -var ErrNotDouble = fmt.Errorf("value is not a double") - -//ErrNotInt is an error that represents a type error. -var ErrNotInt = fmt.Errorf("value is not a int") - -//ErrNotUint is an error that represents a type error. -var ErrNotUint = fmt.Errorf("value is not a uint") - -//ErrNotBool is an error that represents a type error. -var ErrNotBool = fmt.Errorf("value is not a bool") - -//ErrNotString is an error that represents a type error. -var ErrNotString = fmt.Errorf("value is not a string") - -//ErrNotBytes is an error that represents a type error. -var ErrNotBytes = fmt.Errorf("value is not a bytes") diff --git a/parser/json/json.go b/parser/json/json.go deleted file mode 100644 index 421cb6a..0000000 --- a/parser/json/json.go +++ /dev/null @@ -1,627 +0,0 @@ -// Copyright 2013 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package json contains the implementation of a JSON parser. -package json - -import ( - "bytes" - "fmt" - "io" - "strconv" - - "github.com/katydid/parser-go/parser" -) - -// ErrUnquote returns an error that resulted from trying to unquote a string. -var ErrUnquote = fmt.Errorf("json: error unquoting string") - -func errInString(buf []byte) error { - return fmt.Errorf("katydid/json error in json string: %s", string(buf)) -} - -func isString(buf []byte) bool { - return buf[0] == '"' -} - -func scanString(buf []byte) (int, error) { - escaped := false - udigits := -1 - if buf[0] != '"' { - return 0, errInString(buf) - } - for i, c := range buf[1:] { - if escaped { - switch c { - case 'b', 'f', 'n', 'r', 't', '\\', '/', '"': - escaped = false - continue - case 'u': - udigits = 0 - continue - } - return 0, errInString(buf) - } - if udigits >= 0 { - if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { - udigits++ - } else { - return 0, errInString(buf) - } - if udigits == 4 { - udigits = -1 - } - continue - } - if c == '"' { - return i + 2, nil - } - if c == '\\' { - escaped = true - continue - } - if c < 0x20 { - return 0, errInString(buf) - } - } - panic("unreachable") -} - -func isNumber(c byte) bool { - return (c == '-') || ((c >= '0') && (c <= '9')) -} - -func isSpace(c byte) bool { - return (c == ' ') || (c == '\n') || (c == '\r') || (c == '\t') -} - -func skipSpace(buf []byte) int { - for i, c := range buf { - if !isSpace(c) { - return i - } - } - return len(buf) -} - -func (s *jsonParser) expected(expected string) error { - return fmt.Errorf("katydid/json/parser: expected '%s' at offset %d, but got '%c'", expected, s.offset, s.buf[s.offset]) -} - -func (s *jsonParser) scanOpenObject() error { - if s.buf[s.offset] == '{' { - s.offset++ - } else { - return s.expected("{") - } - return s.skipSpace() -} - -func (s *jsonParser) scanOpenArray() error { - if s.buf[s.offset] == '[' { - s.offset++ - } else { - return s.expected("[") - } - return s.skipSpace() -} - -func (s *jsonParser) scanString() error { - s.startValueOffset = s.offset - n, err := scanString(s.buf[s.offset:]) - if err != nil { - return err - } - s.offset += n - if s.offset >= len(s.buf) { - s.offset = len(s.buf) - } - s.endValueOffset = s.offset - return s.skipSpace() -} - -func (s *jsonParser) scanName() error { - startOffset := s.offset - n, err := scanString(s.buf[s.offset:]) - if err != nil { - return err - } - s.offset += n - var ok bool - s.name, ok = unquote(s.buf[startOffset:s.offset]) - if !ok { - return ErrUnquote - } - return s.skipSpace() -} - -func (s *jsonParser) skipSpace() error { - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - s.offset += skipSpace(s.buf[s.offset:]) - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - return nil -} - -func (s *jsonParser) scanTrue() error { - if s.offset+4 > len(s.buf) { - return io.ErrShortBuffer - } - if !bytes.Equal(s.buf[s.offset:s.offset+4], []byte("true")) { - return s.expected("true") - } - s.startValueOffset = s.offset - s.endValueOffset = s.offset + 4 - s.offset += 4 - return s.skipSpace() -} - -func (s *jsonParser) scanFalse() error { - if s.offset+5 > len(s.buf) { - return io.ErrShortBuffer - } - if !bytes.Equal(s.buf[s.offset:s.offset+5], []byte("false")) { - return s.expected("false") - } - s.startValueOffset = s.offset - s.endValueOffset = s.offset + 5 - s.offset += 5 - return s.skipSpace() -} - -func (s *jsonParser) scanNull() error { - if s.offset+4 > len(s.buf) { - return io.ErrShortBuffer - } - if !bytes.Equal(s.buf[s.offset:s.offset+4], []byte("null")) { - return s.expected("null") - } - s.startValueOffset = s.offset - s.endValueOffset = s.offset + 4 - s.offset += 4 - return s.skipSpace() -} - -func (s *jsonParser) scanArray() error { - count := 0 - index := 0 - for i, c := range s.buf[s.offset:] { - if c == '[' { - count++ - } - if c == ']' { - count-- - } - if count == 0 { - index = i - break - } - } - if count != 0 { - return s.expected("]") - } - s.startValueOffset = s.offset - s.endValueOffset = s.offset + index + 1 - s.offset += index + 1 - s.isValueArray = true - return s.skipSpace() -} - -func (s *jsonParser) scanObject() error { - count := 0 - index := 0 - for i, c := range s.buf[s.offset:] { - if c == '{' { - count++ - } - if c == '}' { - count-- - } - if count == 0 { - index = i - break - } - } - if count != 0 { - return s.expected("}") - } - s.startValueOffset = s.offset - s.endValueOffset = s.offset + index + 1 - s.offset += index + 1 - s.isValueObject = true - return s.skipSpace() -} - -func isDigit(c byte) bool { - return c >= '0' && c <= '9' -} - -func isDigit19(c byte) bool { - return c >= '1' && c <= '9' -} - -func (s *jsonParser) scanNumber() error { - s.startValueOffset = s.offset - if s.buf[s.offset] == '-' { - s.offset++ - if s.offset >= len(s.buf) { - return io.ErrShortBuffer - } - } - if s.buf[s.offset] == '0' { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - } else if isDigit19(s.buf[s.offset]) { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - for s.offset < len(s.buf) && isDigit(s.buf[s.offset]) { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - } - } - if s.offset < len(s.buf) && s.buf[s.offset] == '.' { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - for s.offset < len(s.buf) && isDigit(s.buf[s.offset]) { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - } - } - if s.offset < len(s.buf) && - (s.buf[s.offset] == 'e' || s.buf[s.offset] == 'E') { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - if s.offset < len(s.buf) { - if s.buf[s.offset] == '+' || s.buf[s.offset] == '-' { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - } - } - for s.offset < len(s.buf) && isDigit(s.buf[s.offset]) { - s.offset++ - if s.offset > len(s.buf) { - return io.ErrShortBuffer - } - } - } - s.endValueOffset = s.offset - return nil -} - -func (s *jsonParser) scanValue() error { - c := s.buf[s.offset] - if isNumber(c) { - return s.scanNumber() - } - switch c { - case '"': - return s.scanString() - case '{': - return s.scanObject() - case '[': - return s.scanArray() - case 't': - return s.scanTrue() - case 'f': - return s.scanFalse() - case 'n': - return s.scanNull() - } - return s.expected("value") -} - -func (s *jsonParser) scanColon() error { - if s.buf[s.offset] != ':' { - return s.expected(":") - } - s.offset++ - return s.skipSpace() -} - -func (s *jsonParser) scanCloseObject() error { - if s.buf[s.offset] == '}' { - return io.EOF - } - return s.expected("}") -} - -func (s *jsonParser) scanCloseArray() error { - if s.buf[s.offset] == ']' { - return io.EOF - } - return s.expected("]") -} - -func (s *jsonParser) scanComma() error { - if s.buf[s.offset] != ',' { - return s.expected(",") - } - s.offset++ - return s.skipSpace() -} - -func (s *jsonParser) nextValueInArray() error { - if s.firstArrayValue { - if err := s.scanOpenArray(); err != nil { - return err - } - s.firstArrayValue = false - } else { - if s.buf[s.offset] == ',' { - if err := s.scanComma(); err != nil { - return err - } - } else { - return s.scanCloseArray() - } - } - if s.buf[s.offset] == ']' { - return s.scanCloseArray() - } - return s.scanValue() -} - -func (s *jsonParser) nextValueInObject() error { - if s.firstObjectValue { - if err := s.scanOpenObject(); err != nil { - return err - } - s.firstObjectValue = false - } else { - if s.buf[s.offset] == ',' { - if err := s.scanComma(); err != nil { - return err - } - } else { - if err := s.scanCloseObject(); err != nil { - return err - } - } - } - if isString(s.buf[s.offset:]) { - if err := s.scanName(); err != nil { - return err - } - if err := s.scanColon(); err != nil { - return err - } - if err := s.scanValue(); err != nil { - return err - } - return nil - } - return s.scanCloseObject() -} - -func (s *jsonParser) Next() error { - if s.isLeaf { - if s.firstObjectValue { - s.firstObjectValue = false - return nil - } - return io.EOF - } - s.isValueObject = false - s.isValueArray = false - if err := s.skipSpace(); err != nil { - return err - } - if s.inArray { - if !s.firstArrayValue { - s.arrayIndex++ - } - return s.nextValueInArray() - } - return s.nextValueInObject() -} - -func (s *jsonParser) IsLeaf() bool { - return s.isLeaf -} - -func (s *jsonParser) Value() []byte { - return s.buf[s.startValueOffset:s.endValueOffset] -} - -func (s *jsonParser) Double() (float64, error) { - if s.isLeaf { - v := string(s.Value()) - i, err := strconv.ParseFloat(v, 64) - return i, err - } - return 0, parser.ErrNotDouble -} - -func (s *jsonParser) Int() (int64, error) { - if s.isLeaf { - v := string(s.Value()) - i, err := strconv.ParseInt(v, 10, 64) - if err != nil { - f, ferr := strconv.ParseFloat(v, 64) - if ferr != nil { - return i, err - } - if float64(int64(f)) == f { - return int64(f), nil - } - } - return i, err - } - if s.inArray { - return int64(s.arrayIndex), nil - } - return 0, parser.ErrNotInt -} - -func (s *jsonParser) Uint() (uint64, error) { - if s.isLeaf { - v := string(s.Value()) - i, err := strconv.ParseUint(v, 10, 64) - return uint64(i), err - } - return 0, parser.ErrNotUint -} - -func (s *jsonParser) Bool() (bool, error) { - if s.isLeaf { - v := string(s.Value()) - if v == "true" { - return true, nil - } - if v == "false" { - return false, nil - } - } - return false, parser.ErrNotBool -} - -func (s *jsonParser) String() (string, error) { - if s.isLeaf { - v := s.Value() - if v[0] != '"' { - return "", parser.ErrNotString - } - res, ok := unquote(v) - if !ok { - return "", ErrUnquote - } - return res, nil - } - if s.inArray { - return "", parser.ErrNotString - } - return s.name, nil -} - -func (s *jsonParser) Bytes() ([]byte, error) { - return nil, parser.ErrNotBytes -} - -// JsonParser is a parser for JSON -type JsonParser interface { - parser.Interface - //Init initialises the parser with a byte buffer containing JSON. - Init(buf []byte) error - Reset() error -} - -// NewJsonParser returns a new JSON parser. -func NewJsonParser() JsonParser { - return &jsonParser{ - state: state{ - firstObjectValue: true, - }, - stack: make([]state, 0, 10), - } -} - -func (s *jsonParser) Init(buf []byte) error { - s.state = state{ - firstObjectValue: true, - buf: buf, - } - s.stack = s.stack[:0] - if err := s.skipSpace(); err != nil { - return err - } - if s.buf[s.offset] == '{' { - //do nothing - } else if s.buf[s.offset] == '[' { - if err := s.scanValue(); err != nil { - return err - } - s.inArray = true - s.firstArrayValue = true - s.buf = s.buf[s.startValueOffset:s.endValueOffset] - s.offset = 0 - } else { - if err := s.scanValue(); err != nil { - return err - } - s.state.isLeaf = true - s.state.firstObjectValue = true - } - return nil -} - -func (s *jsonParser) Reset() error { - if len(s.stack) > 0 { - return s.Init(s.stack[0].buf) - } - return s.Init(s.buf) -} - -type jsonParser struct { - state - stack []state -} - -type state struct { - buf []byte - offset int - name string - startValueOffset int - endValueOffset int - inArray bool - firstObjectValue bool - firstArrayValue bool - isValueObject bool - isValueArray bool - isLeaf bool - arrayIndex int -} - -func (s *jsonParser) Up() { - top := len(s.stack) - 1 - s.state = s.stack[top] - s.stack = s.stack[:top] -} - -func (s *jsonParser) Down() { - if s.isValueObject { - s.stack = append(s.stack, s.state) - s.state = state{ - buf: s.buf[s.startValueOffset:s.endValueOffset], - firstObjectValue: true, - } - } else if s.isValueArray { - s.stack = append(s.stack, s.state) - s.state = state{ - buf: s.buf[s.startValueOffset:s.endValueOffset], - firstArrayValue: true, - inArray: true, - } - } else { - s.stack = append(s.stack, s.state) - s.state.isLeaf = true - s.state.firstObjectValue = true - } -} diff --git a/parser/json/json_test.go b/parser/json/json_test.go deleted file mode 100644 index 866e342..0000000 --- a/parser/json/json_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package json_test - -import ( - "encoding/json" - "testing" - - "github.com/katydid/parser-go/parser/debug" - sjson "github.com/katydid/parser-go/parser/json" -) - -func TestDebug(t *testing.T) { - p := sjson.NewJsonParser() - data, err := json.Marshal(debug.Input) - if err != nil { - t.Fatal(err) - } - if err := p.Init(data); err != nil { - t.Fatal(err) - } - m := debug.Walk(p) - if !m.Equal(debug.Output) { - t.Fatalf("expected %s but got %s", debug.Output, m) - } -} - -func TestRandomDebug(t *testing.T) { - p := sjson.NewJsonParser() - data, err := json.Marshal(debug.Input) - if err != nil { - t.Fatal(err) - } - for i := 0; i < 10; i++ { - if err := p.Init(data); err != nil { - t.Fatal(err) - } - //l := debug.NewLogger(p, debug.NewLineLogger()) - debug.RandomWalk(p, debug.NewRand(), 10, 3) - //t.Logf("original %v vs random %v", debug.Output, m) - } -} - -func TestEscapedChar(t *testing.T) { - j := map[string][]interface{}{ - `a\"`: {1}, - } - data, err := json.Marshal(j) - if err != nil { - t.Fatal(err) - } - t.Logf("%s", string(data)) - parser := sjson.NewJsonParser() - if err := parser.Init(data); err != nil { - t.Fatal(err) - } - m := debug.Walk(parser) - name := m[0].Label - if name != `a\"` { - t.Fatalf("wrong escaped name %s", name) - } -} - -func TestMultiLineArray(t *testing.T) { - s := `{ - "A":[1] - }` - parser := sjson.NewJsonParser() - if err := parser.Init([]byte(s)); err != nil { - t.Fatal(err) - } - jout := debug.Walk(parser) - t.Logf("%v", jout) -} - -func TestIntWithExponent(t *testing.T) { - s := `{"A":1e+08}` - parser := sjson.NewJsonParser() - if err := parser.Init([]byte(s)); err != nil { - t.Fatal(err) - } - if err := parser.Next(); err != nil { - t.Fatal(err) - } - parser.Down() - if err := parser.Next(); err != nil { - t.Fatal(err) - } - if !parser.IsLeaf() { - t.Fatal("incorrect walk, please adjust the path above") - } - if i, err := parser.Int(); err != nil { - t.Fatalf("did not expect error %v", err) - } else if i != 1e+08 { - t.Fatalf("got %d", i) - } -} - -func testValue(t *testing.T, input, output string) { - parser := sjson.NewJsonParser() - if err := parser.Init([]byte(input)); err != nil { - t.Fatalf("init error: %v", err) - } - jout := debug.Walk(parser) - if len(jout) != 1 { - t.Fatalf("expected one node") - } - if len(jout[0].Children) != 0 { - t.Fatalf("did not expected any children") - } - if jout[0].Label != output { - t.Fatalf("expected %s got %s", output, jout[0].Label) - } -} - -func TestValues(t *testing.T) { - testValue(t, "0", "0") - testValue(t, "1", "1") - testValue(t, "-1", "-1") - testValue(t, "123", "123") - testValue(t, "1.1", "1.1") - testValue(t, "1.123", "1.123") - testValue(t, "1.1e1", "11") - testValue(t, "1.1e-1", "0.11") - testValue(t, "1.1e10", "11000000000") - testValue(t, "1.1e+10", "11000000000") - testValue(t, `"a"`, "a") - testValue(t, `"abc"`, "abc") - testValue(t, `""`, "") - testValue(t, `"\b"`, "\b") - testValue(t, `true`, "true") - testValue(t, `false`, "false") - testValue(t, `null`, "") -} - -func testArray(t *testing.T, s string) { - parser := sjson.NewJsonParser() - if err := parser.Init([]byte(s)); err != nil { - t.Fatal(err) - } - jout := debug.Walk(parser) - t.Logf("%v", jout) -} - -func TestArray(t *testing.T) { - testArray(t, `[1]`) - testArray(t, `[1,2.3e5]`) - testArray(t, `[1,"a"]`) - testArray(t, `[true, false, null]`) - testArray(t, `[{"a": true, "b": [1,2]}]`) -} diff --git a/parser/json/unquote.go b/parser/json/unquote.go deleted file mode 100644 index c9b21de..0000000 --- a/parser/json/unquote.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code has been copied from https://golang.org/src/encoding/json/decode.go - -package json - -import ( - "strconv" - "unicode" - "unicode/utf16" - "unicode/utf8" -) - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) rune { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - r, err := strconv.ParseUint(string(s[2:6]), 16, 64) - if err != nil { - return -1 - } - return rune(r) -} - -// unquote converts a quoted JSON string literal s into an actual string t. -// The rules are different than for Go, so cannot use strconv.Unquote. -func unquote(s []byte) (t string, ok bool) { - s, ok = unquoteBytes(s) - t = string(s) - return -} - -func unquoteBytes(s []byte) (t []byte, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - s = s[1 : len(s)-1] - - // Check for unusual characters. If there are none, - // then no unquoting is needed, so return a slice of the - // original bytes. - r := 0 - for r < len(s) { - c := s[r] - if c == '\\' || c == '"' || c < ' ' { - break - } - if c < utf8.RuneSelf { - r++ - continue - } - rr, size := utf8.DecodeRune(s[r:]) - if rr == utf8.RuneError && size == 1 { - break - } - r += size - } - if r == len(s) { - return s, true - } - - b := make([]byte, len(s)+2*utf8.UTFMax) - w := copy(b, s[0:r]) - for r < len(s) { - // Out of room? Can only happen if s is full of - // malformed UTF-8 and we're replacing each - // byte with RuneError. - if w >= len(b)-2*utf8.UTFMax { - nb := make([]byte, (len(b)+utf8.UTFMax)*2) - copy(nb, b[0:w]) - b = nb - } - switch c := s[r]; { - case c == '\\': - r++ - if r >= len(s) { - return - } - switch s[r] { - default: - return - case '"', '\\', '/', '\'': - b[w] = s[r] - r++ - w++ - case 'b': - b[w] = '\b' - r++ - w++ - case 'f': - b[w] = '\f' - r++ - w++ - case 'n': - b[w] = '\n' - r++ - w++ - case 'r': - b[w] = '\r' - r++ - w++ - case 't': - b[w] = '\t' - r++ - w++ - case 'u': - r-- - rr := getu4(s[r:]) - if rr < 0 { - return - } - r += 6 - if utf16.IsSurrogate(rr) { - rr1 := getu4(s[r:]) - if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { - // A valid pair; consume. - r += 6 - w += utf8.EncodeRune(b[w:], dec) - break - } - // Invalid surrogate; fall back to replacement rune. - rr = unicode.ReplacementChar - } - w += utf8.EncodeRune(b[w:], rr) - } - - // Quote, control characters are invalid. - case c == '"', c < ' ': - return - - // ASCII - case c < utf8.RuneSelf: - b[w] = c - r++ - w++ - - // Coerce to well-formed UTF-8. - default: - rr, size := utf8.DecodeRune(s[r:]) - r += size - w += utf8.EncodeRune(b[w:], rr) - } - } - return b[0:w], true -} diff --git a/parser/parser.go b/parser/parser.go deleted file mode 100644 index ee2bff8..0000000 --- a/parser/parser.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//Package parser represents the parser.Interface and some errors for implementing parsers. -package parser - -import "fmt" - -//A type conforming to the parser.Interface interface, abstracts away the implementation details of a parser. -type Interface interface { - Next() error - IsLeaf() bool - Up() - Down() - Value -} - -//A type confirming to the parser.Value interface, repesents one native value, tree node label (field name) or some repesentation a node label. -//Typically only one of the methods returns a value without an error, but more than one method can return without an error. -//For example a positive json number can return an errorless value for the Double, Int and Uint methods. -type Value interface { - Double() (float64, error) - Int() (int64, error) - Uint() (uint64, error) - Bool() (bool, error) - String() (string, error) - Bytes() ([]byte, error) -} - -//Sprint returns a value printed as a string. -func Sprint(value Value) string { - return fmt.Sprintf("%#v", getValue(value)) -} - -func getValue(value Value) interface{} { - var v interface{} - var err error - v, err = value.Bool() - if err == nil { - return v - } - v, err = value.Bytes() - if err == nil { - return v - } - v, err = value.String() - if err == nil { - return v - } - v, err = value.Int() - if err == nil { - return v - } - v, err = value.Uint() - if err == nil { - return v - } - v, err = value.Double() - if err == nil { - return v - } - return nil -} diff --git a/parser/reflect/reflect.go b/parser/reflect/reflect.go deleted file mode 100644 index 16f0966..0000000 --- a/parser/reflect/reflect.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2013 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package reflect contains an implementation of a parser for a reflected go structure. -package reflect - -import ( - "io" - "reflect" - - "github.com/katydid/parser-go/parser" -) - -type state struct { - parent reflect.Value - typ reflect.StructField - value reflect.Value - field int - maxField int - isLeaf bool - isArray bool -} - -type reflectParser struct { - state - stack []state -} - -func deref(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Ptr { - return v.Elem() - } - return v -} - -func newState(val reflect.Value) state { - value := deref(val) - if value.Kind() == reflect.Struct { - return state{ - parent: value, - maxField: value.NumField(), - } - } - if isSlice(value) { - return state{ - parent: value, - maxField: value.Len(), - isArray: true, - } - } - return state{ - value: val, - isLeaf: true, - maxField: 1, - } -} - -func isSlice(v reflect.Value) bool { - return v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 -} - -// ReflectParser is a parser for a reflected go structure. -type ReflectParser interface { - parser.Interface - //Init initialises the parser with a value of reflected go structure. - Init(value reflect.Value) ReflectParser -} - -// NewReflectParser returns a new reflect parser. -func NewReflectParser() ReflectParser { - return &reflectParser{stack: make([]state, 0, 10)} -} - -func (s *reflectParser) Init(value reflect.Value) ReflectParser { - s.state = newState(value) - return s -} - -func (s *reflectParser) Next() error { - if s.field >= s.maxField { - return io.EOF - } - if !s.isLeaf && !s.isArray { - s.typ = s.parent.Type().Field(s.field) - s.value = s.parent.Field(s.field) - if s.value.Kind() == reflect.Ptr || s.value.Kind() == reflect.Slice { - if s.value.IsNil() { - s.field++ - return s.Next() - } - } - } - s.field++ - return nil -} - -func (s *reflectParser) IsLeaf() bool { - return s.isLeaf -} - -func (s *reflectParser) getValue() reflect.Value { - return deref(s.value) -} - -func (s *reflectParser) Double() (float64, error) { - if s.isLeaf { - value := s.getValue() - switch value.Kind() { - case reflect.Float64, reflect.Float32: - return value.Float(), nil - } - } - return 0, parser.ErrNotDouble -} - -func (s *reflectParser) Int() (int64, error) { - if s.isArray { - return int64(s.field - 1), nil - } - if s.isLeaf { - value := s.getValue() - switch value.Kind() { - case reflect.Int64, reflect.Int32: - return value.Int(), nil - } - } - return 0, parser.ErrNotInt -} - -func (s *reflectParser) Uint() (uint64, error) { - if s.isLeaf { - value := s.getValue() - switch value.Kind() { - case reflect.Uint64, reflect.Uint32: - return value.Uint(), nil - } - } - return 0, parser.ErrNotUint -} - -func (s *reflectParser) Bool() (bool, error) { - if s.isLeaf { - value := s.getValue() - switch value.Kind() { - case reflect.Bool: - return value.Bool(), nil - } - } - return false, parser.ErrNotBool -} - -func (s *reflectParser) String() (string, error) { - if !s.isLeaf { - return s.typ.Name, nil - } - value := s.getValue() - switch value.Kind() { - case reflect.String: - return value.String(), nil - } - return "", parser.ErrNotString -} - -func (s *reflectParser) Bytes() ([]byte, error) { - if s.isLeaf { - value := s.getValue() - switch value.Kind() { - case reflect.Slice, reflect.Uint8, reflect.Int8: - return value.Bytes(), nil - } - } - return nil, parser.ErrNotBytes -} - -func (s *reflectParser) Up() { - top := len(s.stack) - 1 - s.state = s.stack[top] - s.stack = s.stack[:top] -} - -func (s *reflectParser) Down() { - s.stack = append(s.stack, s.state) - if s.isArray { - s.state = newState(s.state.parent.Index(s.field - 1)) - } else { - s.state = newState(s.state.value) - } -} diff --git a/parser/reflect/reflect_test.go b/parser/reflect/reflect_test.go deleted file mode 100644 index b19f139..0000000 --- a/parser/reflect/reflect_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 Walter Schulze -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package reflect - -import ( - "reflect" - "testing" - - "github.com/katydid/parser-go/parser/debug" -) - -func TestDebug(t *testing.T) { - p := NewReflectParser() - p.Init(reflect.ValueOf(debug.Input)) - m := debug.Walk(p) - if !m.Equal(debug.Output) { - t.Fatalf("expected %s but got %s", debug.Output, m) - } -} - -func TestRandomDebug(t *testing.T) { - p := NewReflectParser() - for i := 0; i < 10; i++ { - p.Init(reflect.ValueOf(debug.Input)) - //l := debug.NewLogger(p, debug.NewLineLogger()) - debug.RandomWalk(p, debug.NewRand(), 10, 3) - //t.Logf("original %v vs random %v", debug.Output, m) - } -} diff --git a/parser/xml/bytes_decl.go b/xml/bytes_decl.go similarity index 100% rename from parser/xml/bytes_decl.go rename to xml/bytes_decl.go diff --git a/parser/xml/marshal.go b/xml/marshal.go similarity index 100% rename from parser/xml/marshal.go rename to xml/marshal.go diff --git a/parser/xml/min.go b/xml/min.go similarity index 100% rename from parser/xml/min.go rename to xml/min.go diff --git a/parser/xml/parser.go b/xml/parser.go similarity index 100% rename from parser/xml/parser.go rename to xml/parser.go diff --git a/parser/xml/parser_test.go b/xml/parser_test.go similarity index 100% rename from parser/xml/parser_test.go rename to xml/parser_test.go diff --git a/parser/xml/read.go b/xml/read.go similarity index 100% rename from parser/xml/read.go rename to xml/read.go diff --git a/parser/xml/typeinfo.go b/xml/typeinfo.go similarity index 100% rename from parser/xml/typeinfo.go rename to xml/typeinfo.go diff --git a/parser/xml/xml.go b/xml/xml.go similarity index 100% rename from parser/xml/xml.go rename to xml/xml.go