Skip to content

Commit

Permalink
jq: Object, Index(Iter); fixes: Comma, Seek
Browse files Browse the repository at this point in the history
  • Loading branch information
nikandfor committed Aug 15, 2024
1 parent 461f559 commit 03b9d94
Show file tree
Hide file tree
Showing 15 changed files with 1,044 additions and 455 deletions.
8 changes: 8 additions & 0 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ func init() {
}
}

func (e *Encoder) AppendKey(w, s []byte) []byte {
w = append(w, '"')
w = append(w, s...)
w = append(w, '"')

return w
}

// EncodeString encodes string in a JSON compatible way.
func (e *Encoder) AppendString(w, s []byte) []byte {
w = append(w, '"')
Expand Down
6 changes: 3 additions & 3 deletions jq/benchmarks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ func BenchmarkIndex(b *testing.B) {
{
Name: "Small",
Data: benchmarks_data.SmallFixture,
Filter: &Index{"uuid"},
Filter: NewIndex("uuid"),
Result: []byte(`"de305d54-75b4-431b-adb2-eb6b9e546014"`),
},
{
Name: "Medium",
Data: benchmarks_data.MediumFixture,
Filter: &Index{"person", "gravatar", "avatars", 0, "url"},
Filter: NewIndex("person", "gravatar", "avatars", 0, "url"),
Result: []byte(`"http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510"`),
},
{
Name: "Large",
Data: benchmarks_data.LargeFixture,
Filter: &Index{"topics", "topics", 28, "posters", 0, "user_id"},
Filter: NewIndex("topics", "topics", 28, "posters", 0, "user_id"),
Result: []byte(`52`),
},
} {
Expand Down
85 changes: 85 additions & 0 deletions jq/comma.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package jq

import (
"nikand.dev/go/json"
)

type (
// Comma passes the same input to each of the Filters and combines returned values.
Comma struct {
Filters []Filter
pool []*commaState
}

commaState struct {
st int
fi int
sub State
}
)

func NewComma(fs ...Filter) *Comma {
return &Comma{
Filters: fs,
}
}

func (f *Comma) Next(w, r []byte, st int, state State) (_ []byte, i int, _ State, err error) {
st = json.SkipSpaces(r, st)
if st == len(r) {
return w, st, nil, nil
}

i = st
wreset := len(w)

ss, _ := state.(*commaState)
if ss == nil {
ss = f.state()
ss.st = st
state = ss
}

for {
w, i, ss.sub, err = f.Filters[ss.fi].Next(w, r, i, ss.sub)
// log.Printf("comma filter %d %d->%d %v %v => %s", ss.fi, st, i, ss.sub, err, w[wreset:])
if err != nil {
return w, i, state, err
}

if ss.sub == nil {
ss.fi++
}

if ss.sub == nil && ss.fi < len(f.Filters) {
i = ss.st
}

if ss.sub == nil && ss.fi < len(f.Filters) && len(w) == wreset {
continue
}

break
}

if ss.fi == len(f.Filters) {
state = nil
f.pool = append(f.pool, ss)
}

return w, i, state, nil
}

func (f *Comma) state() (ss *commaState) {
l := len(f.pool)
if l == 0 {
ss = &commaState{}
} else {
ss = f.pool[l-1]
f.pool = f.pool[:l-1]

ss.fi = 0
}

return ss
}
92 changes: 92 additions & 0 deletions jq/comma_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package jq

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestComma(t *testing.T) {
data := `{"a":"b","c":4,"d":["e",null,true,false,{"f":3.4}]}`

f := NewComma(
NewIndex("a"),
NewIndex("c"),
NewIndex("d", 0),
)

var state State

b, i, state, err := f.Next(nil, []byte(data), 0, state)
assert.NoError(t, err)
assert.NotNil(t, state)
assert.Equal(t, `"b"`, string(b))

b, i, state, err = f.Next(nil, []byte(data), i, state)
assert.NoError(t, err)
assert.NotNil(t, state)
assert.Equal(t, `4`, string(b))

b, i, state, err = f.Next(nil, []byte(data), i, state)
assert.NoError(t, err)
assert.Nil(t, state)
assert.Len(t, data, i)
assert.Equal(t, `"e"`, string(b))
}

func TestCommaPipe(t *testing.T) {
data := `{"a":"b","c":4,"d":["e",null,true,false,{"f":3.4}]}`

f := NewComma(
NewPipe(NewIndex("a")),
NewPipe(NewIndex("c")),
NewPipe(NewIndex("d"), NewIndex(0)),
)

b, i, state, err := f.Next(nil, []byte(data), 0, nil)
assert.NoError(t, err)
assert.NotNil(t, state)
// assert.Len(t, data, i)
assert.Equal(t, `"b"`, string(b))

b, i, state, err = f.Next(nil, []byte(data), i, state)
assert.NoError(t, err)
assert.NotNil(t, state)
// assert.Len(t, data, i)
assert.Equal(t, `4`, string(b))

b, i, state, err = f.Next(nil, []byte(data), i, state)
assert.NoError(t, err)
assert.Nil(t, state)
assert.Len(t, data, i)
assert.Equal(t, `"e"`, string(b))
}

func TestCommaIter(t *testing.T) {
r := []byte(`{"a":[1,2,3],"b":[4,5]}`)

// f := NewArray(
f := NewComma(
NewIndex("a", Iter{}),
NewIndex("b", Iter{}),
// ),
)

var err error
var state State
var w []byte
i := 0

for _, tc := range []string{`1`, `2`, `3`, `4`, `5`} {
w, i, state, err = f.Next(w[:0], r, i, state)
t.Logf("comma iter %s %+v %v", w, state, err)
assert.NoError(t, err)
assert.NotNil(t, state)
assert.Equal(t, tc, string(w))
}

w, i, state, err = f.Next(w[:0], r, i, state)

Check failure on line 88 in jq/comma_test.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to i (ineffassign)
assert.NoError(t, err)
assert.Nil(t, state)
assert.Equal(t, []byte{}, w)
}
8 changes: 4 additions & 4 deletions jq/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func ExampleIndex() {
data := []byte(`{"key0":"skip it", "key1": {"next_key": ["array", null, {"obj":"val"}, "trailing element"]}} "next"`)

f := jq.Index{"key1", "next_key", 2} // string keys and int array indexes are supported
f := jq.NewIndex("key1", "next_key", 2) // string keys and int array indexes are supported

var res []byte // reusable buffer
var i int // start index
Expand All @@ -37,14 +37,14 @@ func ExampleBase64d() {
data := []byte(`{"key1":"eyJrZXkyIjoie1wia2V5M1wiOlwidmFsdWVcIn0ifQ=="}`)

f := jq.NewPipe(
jq.Index{"key1"},
jq.NewIndex("key1"),
&jq.Base64d{
Encoding: base64.StdEncoding,
},
&jq.JSONDecoder{},
jq.Index{"key2"},
jq.NewIndex("key2"),
&jq.JSONDecoder{},
jq.Index{"key3"},
jq.NewIndex("key3"),
)

res, _, _, err := f.Next(nil, data, 0, nil)
Expand Down
Loading

0 comments on commit 03b9d94

Please # to comment.