Skip to content

Commit

Permalink
refactor code using slices, maps, and cmp packages
Browse files Browse the repository at this point in the history
  • Loading branch information
itchyny committed Aug 15, 2024
1 parent 083fb39 commit 76eb23f
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 327 deletions.
4 changes: 2 additions & 2 deletions _tools/print_builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"os"
"reflect"
"sort"
"slices"
"strings"

"github.com/itchyny/gojq"
Expand All @@ -30,7 +30,7 @@ func main() {
names[i] = n
i++
}
sort.Strings(names)
slices.Sort(names)
for _, n := range names {
var sb strings.Builder
for _, fd := range fds[n] {
Expand Down
14 changes: 6 additions & 8 deletions cli/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package cli

import (
"bytes"
"cmp"
"fmt"
"io"
"math"
"math/big"
"sort"
"slices"
"strconv"
"strings"
"unicode/utf8"
)

Expand All @@ -33,11 +35,7 @@ func (e *encoder) flush() error {

func (e *encoder) marshal(v any, w io.Writer) error {
e.out = w
err := e.encode(v)
if ferr := e.flush(); ferr != nil && err == nil {
err = ferr
}
return err
return cmp.Or(e.encode(v), e.flush())

Check failure on line 38 in cli/encoder.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.23.x)

cmp.Or requires go1.22 or later (module is go1.21)
}

func (e *encoder) encode(v any) error {
Expand Down Expand Up @@ -194,8 +192,8 @@ func (e *encoder) encodeObject(vs map[string]any) error {
kvs[i] = keyVal{k, v}
i++
}
sort.Slice(kvs, func(i, j int) bool {
return kvs[i].key < kvs[j].key
slices.SortFunc(kvs, func(x, y keyVal) int {
return strings.Compare(x.key, y.key)
})
for i, kv := range kvs {
if i > 0 {
Expand Down
21 changes: 8 additions & 13 deletions cli/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"encoding/json"
"io"
"slices"
)

type jsonStream struct {
Expand Down Expand Up @@ -71,17 +72,17 @@ func (s *jsonStream) next() (any, error) {
if s.states[len(s.states)-1] == jsonStateArrayStart {
s.states[len(s.states)-1] = jsonStateArrayEmptyEnd
s.path = s.path[:len(s.path)-1]
return []any{s.copyPath(), []any{}}, nil
return []any{slices.Clone(s.path), []any{}}, nil
}
s.states[len(s.states)-1] = jsonStateArrayEnd
return []any{s.copyPath()}, nil
return []any{slices.Clone(s.path)}, nil
case '}':
if s.states[len(s.states)-1] == jsonStateObjectStart {
s.states[len(s.states)-1] = jsonStateObjectEmptyEnd
return []any{s.copyPath(), map[string]any{}}, nil
return []any{slices.Clone(s.path), map[string]any{}}, nil
}
s.states[len(s.states)-1] = jsonStateObjectEnd
return []any{s.copyPath()}, nil
return []any{slices.Clone(s.path)}, nil
default:
panic(d)
}
Expand All @@ -91,23 +92,17 @@ func (s *jsonStream) next() (any, error) {
s.states[len(s.states)-1] = jsonStateArrayValue
fallthrough
case jsonStateArrayValue:
return []any{s.copyPath(), token}, nil
return []any{slices.Clone(s.path), token}, nil
case jsonStateObjectStart, jsonStateObjectValue:
s.states[len(s.states)-1] = jsonStateObjectKey
s.path = append(s.path, token)
case jsonStateObjectKey:
s.states[len(s.states)-1] = jsonStateObjectValue
return []any{s.copyPath(), token}, nil
return []any{slices.Clone(s.path), token}, nil
default:
s.states[len(s.states)-1] = jsonStateTopValue
return []any{s.copyPath(), token}, nil
return []any{slices.Clone(s.path), token}, nil
}
}
}
}

func (s *jsonStream) copyPath() []any {
path := make([]any, len(s.path))
copy(path, s.path)
return path
}
88 changes: 38 additions & 50 deletions compare.go
Original file line number Diff line number Diff line change
@@ -1,68 +1,30 @@
package gojq

import (
"cmp"
"math"
"math/big"
"strings"
)

// Compare l and r, and returns jq-flavored comparison value.
// The result will be 0 if l == r, -1 if l < r, and +1 if l > r.
// This comparison is used by built-in operators and functions.
func Compare(l, r any) int {
return binopTypeSwitch(l, r,
compareInt,
func(l, r float64) any {
switch {
case l < r || math.IsNaN(l):
return -1
case l == r:
return 0
default:
return 1
}
},
func(l, r *big.Int) any {
return l.Cmp(r)
},
func(l, r string) any {
switch {
case l < r:
return -1
case l == r:
return 0
default:
return 1
}
},
func(l, r []any) any {
for i, n := 0, min(len(l), len(r)); i < n; i++ {
if cmp := Compare(l[i], r[i]); cmp != 0 {
return cmp
}
}
return compareInt(len(l), len(r))
},
func(l, r map[string]any) any {
lk, rk := funcKeys(l), funcKeys(r)
if cmp := Compare(lk, rk); cmp != 0 {
return cmp
}
for _, k := range lk.([]any) {
if cmp := Compare(l[k.(string)], r[k.(string)]); cmp != 0 {
return cmp
}
}
return 0
},
func(l, r any) any {
return compareInt(typeIndex(l), typeIndex(r))
},
).(int)
cmp.Compare,
compareFloat64,
(*big.Int).Cmp,
strings.Compare,
compareArray,
compareObject,
compareAny,
)
}

func compareInt(l, r int) any {
func compareFloat64(l, r float64) int {
switch {
case l < r:
case l < r || math.IsNaN(l):
return -1
case l == r:
return 0
Expand All @@ -71,6 +33,32 @@ func compareInt(l, r int) any {
}
}

func compareArray[T any](l, r []T) int {
for i, n := 0, min(len(l), len(r)); i < n; i++ {
if cmp := Compare(l[i], r[i]); cmp != 0 {
return cmp
}
}
return cmp.Compare(len(l), len(r))
}

func compareObject(l, r map[string]any) int {
lk, rk := keys(l), keys(r)
if cmp := compareArray(lk, rk); cmp != 0 {
return cmp
}
for _, k := range lk {
if cmp := Compare(l[k], r[k]); cmp != 0 {
return cmp
}
}
return 0
}

func compareAny(l, r any) int {
return cmp.Compare(typeIndex(l), typeIndex(r))
}

func typeIndex(v any) int {
switch v := v.(type) {
default:
Expand Down
19 changes: 7 additions & 12 deletions compiler.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package gojq

import (
"cmp"
"context"
"errors"
"fmt"
"sort"
"slices"
"strconv"
"strings"
)
Expand Down Expand Up @@ -1169,9 +1170,8 @@ func (c *compiler) funcBuiltins(any, []any) any {
}
}
}
sort.Slice(xs, func(i, j int) bool {
return xs[i].name < xs[j].name ||
xs[i].name == xs[j].name && xs[i].arity < xs[j].arity
slices.SortFunc(xs, func(x, y *funcNameArity) int {
return cmp.Or(cmp.Compare(x.name, y.name), cmp.Compare(x.arity, y.arity))

Check failure on line 1174 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.23.x)

cmp.Or requires go1.22 or later (module is go1.21)

Check failure on line 1174 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.21.x)

undefined: cmp.Or

Check failure on line 1174 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (macos-latest, 1.21.x)

undefined: cmp.Or
})
ys := make([]any, len(xs))
for i, x := range xs {
Expand Down Expand Up @@ -1231,9 +1231,8 @@ func listModuleDefs(q *Query) []any {
xs = append(xs, &funcNameArity{fd.Name, len(fd.Args)})
}
}
sort.Slice(xs, func(i, j int) bool {
return xs[i].name < xs[j].name ||
xs[i].name == xs[j].name && xs[i].arity < xs[j].arity
slices.SortFunc(xs, func(x, y *funcNameArity) int {
return cmp.Or(cmp.Compare(x.name, y.name), cmp.Compare(x.arity, y.arity))

Check failure on line 1235 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.23.x)

cmp.Or requires go1.22 or later (module is go1.21)

Check failure on line 1235 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.21.x)

undefined: cmp.Or

Check failure on line 1235 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (macos-latest, 1.21.x)

undefined: cmp.Or
})
defs := make([]any, len(xs))
for i, x := range xs {
Expand All @@ -1249,11 +1248,7 @@ func listModuleDeps(q *Query) []any {
if v == nil {
v = make(map[string]any)
}
relpath := i.ImportPath
if relpath == "" {
relpath = i.IncludePath
}
v["relpath"] = relpath
v["relpath"] = cmp.Or(i.ImportPath, i.IncludePath)

Check failure on line 1251 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.23.x)

cmp.Or requires go1.22 or later (module is go1.21)

Check failure on line 1251 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest, 1.21.x)

undefined: cmp.Or

Check failure on line 1251 in compiler.go

View workflow job for this annotation

GitHub Actions / Test (macos-latest, 1.21.x)

undefined: cmp.Or
if i.ImportAlias != "" {
v["as"] = strings.TrimPrefix(i.ImportAlias, "$")
}
Expand Down
4 changes: 2 additions & 2 deletions debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
"slices"
"strconv"
"strings"
)
Expand Down Expand Up @@ -53,8 +54,7 @@ func (c *compiler) appendCodeInfo(x any) {
func (c *compiler) deleteCodeInfo(name string) {
for i := 0; i < len(c.codeinfos); i++ {
if strings.HasSuffix(c.codeinfos[i].name, name) {
copy(c.codeinfos[i:], c.codeinfos[i+1:])
c.codeinfos = c.codeinfos[:len(c.codeinfos)-1]
c.codeinfos = slices.Delete(c.codeinfos, i, i+1)
i--
}
}
Expand Down
6 changes: 3 additions & 3 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"io"
"math"
"math/big"
"sort"
"slices"
"strconv"
"strings"
"unicode/utf8"
Expand Down Expand Up @@ -174,8 +174,8 @@ func (e *encoder) encodeObject(vs map[string]any) {
kvs[i] = keyVal{k, v}
i++
}
sort.Slice(kvs, func(i, j int) bool {
return kvs[i].key < kvs[j].key
slices.SortFunc(kvs, func(x, y keyVal) int {
return strings.Compare(x.key, y.key)
})
for i, kv := range kvs {
if i > 0 {
Expand Down
11 changes: 5 additions & 6 deletions execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import (
"context"
"math"
"reflect"
"sort"
"slices"
"strings"
)

func (env *env) execute(bc *Code, v any, vars ...any) Iter {
Expand Down Expand Up @@ -296,8 +297,8 @@ loop:
xs[i] = pathValue{path: k, value: v}
i++
}
sort.Slice(xs, func(i, j int) bool {
return xs[i].path.(string) < xs[j].path.(string)
slices.SortFunc(xs, func(x, y pathValue) int {
return strings.Compare(x.path.(string), y.path.(string))
})
case Iter:
if w, ok := v.Next(); ok {
Expand Down Expand Up @@ -436,8 +437,6 @@ func (env *env) poppaths() []any {
}
xs = append(xs, p.path)
}
for i, j := 0, len(xs)-1; i < j; i, j = i+1, j-1 {
xs[i], xs[j] = xs[j], xs[i]
}
slices.Reverse(xs)
return xs
}
Loading

0 comments on commit 76eb23f

Please sign in to comment.