Skip to content

Commit

Permalink
add from argues for Add()
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY committed Jan 19, 2024
1 parent 7430da8 commit 83facca
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 20 deletions.
56 changes: 38 additions & 18 deletions ast/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -780,18 +780,18 @@ func (self *Value) SetManyByIndex(ids []int, vals []Value) (bool, error) {
}
}

// Add appends the given node under self.
func (self *Value) AddAny(val interface{}) error {
return self.AddMany([]Value{NewValue(val)})
// Add inserts single val into the left of the node at `from` (-1 means last)
func (self *Value) AddAny(from int, val interface{}) error {
return self.AddMany(from, []Value{NewValue(val)})
}

// Add appends the given node under self.
func (self *Value) Add(val Value) error {
return self.AddMany([]Value{val})
// Add inserts single val into the left of the node at `from` (-1 means last)
func (self *Value) Add(from int, val Value) error {
return self.AddMany(from, []Value{val})
}

// Add appends the given node under self.
func (self *Value) AddMany(vals []Value) error {
// Add inserts multiple vals into the left of the node at `from` (-1 means last)
func (self *Value) AddMany(from int, vals []Value) error {
if self.Check() != nil {
return self
}
Expand All @@ -805,26 +805,46 @@ func (self *Value) AddMany(vals []Value) error {
return ErrUnsupportType
}

e := 1 // from == 0
if from > 0 {
p := NewParserObj(self.js)
_, err := p.searchIndex(from)
if err != 0 {
if err == _ERR_NOT_FOUND {
e = len(self.js) - 1 // end before ']'
} else {
return p.ExportError(err)
}
} else {
e = p.p
}
} else if from < 0 {
e = len(self.js) - 1
}

n := len(self.js)
for _, v := range vals {
n += len(v.js) + 1
}
b := make([]byte, 0, n)

s := len(self.js) - 2 // start before ']'
for ; s >= 0 && isSpace(self.js[s]); s-- {
}
empty := self.js[s] == '['
lastComma := self.js[e] != ']'
s := e - 1
for ;s>=0 && isSpace(self.js[s]); s++ {}
firstComma := self.js[s] != ',' && self.js[s] != '['

b = append(b, self.js[:s+1]...)
for _, val := range vals {
if !empty {
b = append(b, self.js[:e]...)
for i, val := range vals {
if i == 0 && firstComma {
b = append(b, ","...)
}
empty = false
b = append(b, val.js...)
if i < len(vals)-1 || lastComma {
b = append(b, ","...)
}
}
b = append(b, "]"...)
b = append(b, self.js[e:]...)

self.js = rt.Mem2Str(b)
return nil
}
Expand All @@ -840,7 +860,7 @@ var intsPool = sync.Pool{
},
}

// PopMany pops at most n trailling elements in the array.
// PopMany pops at most n trailling elements in the array. -1 means clears all
func (self *Value) PopMany(n int) error {
if self.Check() != nil {
return self
Expand Down
37 changes: 35 additions & 2 deletions ast/raw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,38 @@ func TestRawNode_UnsetMany(t *testing.T) {
}
}

func TestValue_Add(t *testing.T) {
tests := []struct{
name string
js string
adds []interface{}
from int
err string
out string
}{
{"empty +1", `[]`, []interface{}{1}, 0, "", `[1]`},
{"empty +1", `[]`, []interface{}{1}, 1, "", `[1]`},
{"empty +1", `[]`, []interface{}{1}, -1, "", `[1]`},
{"1+1", `[0]`, []interface{}{1}, 0, "", `[1,0]`},
{"1+1", `[0]`, []interface{}{1}, 1, "", `[0,1]`},
{"1+1", `[0]`, []interface{}{1}, -1, "", `[0,1]`},
{"2+1", `[-1,0]`, []interface{}{1}, 0, "", `[1,-1,0]`},
{"2+1", `[-1,0]`, []interface{}{1}, 1, "", `[-1,1,0]`},
{"2+1", `[-1,0]`, []interface{}{1}, 2, "", `[-1,0,1]`},
{"2+1", `[-1,0]`, []interface{}{1}, -1, "", `[-1,0,1]`},
}
for _, c := range tests {
println(c.name)
root := NewValueJSON(c.js)
vals := []Value{}
for _, val := range c.adds {
vals = append(vals, NewValue(val))
}
require.NoError(t, root.AddMany(c.from, vals))
require.Equal(t, c.out, root.js)
}
}

func TestValue_Add_Pop(t *testing.T) {
tests := []struct{
name string
Expand All @@ -692,6 +724,7 @@ func TestValue_Add_Pop(t *testing.T) {
{"1+1-0", `[0]`, []interface{}{1}, 0, "", `[0,1]`},
{"1+1-1", `[0]`, []interface{}{1}, 1, "", `[0]`},
{"1+1-2", `[0]`, []interface{}{1}, 2, "", `[]`},
{"1+1-3", `[0]`, []interface{}{1}, 3, "", `[]`},
{"1+2-0", `[0]`, []interface{}{1,2}, 0, "", `[0,1,2]`},
{"1+2-1", `[0]`, []interface{}{1,2}, 1, "", `[0,1]`},
}
Expand All @@ -702,7 +735,7 @@ func TestValue_Add_Pop(t *testing.T) {
for i, val := range c.adds {
vals = append(vals, NewValue(val))
println("add", i)
if err := root.AddAny(val); err != nil {
if err := root.AddAny(-1, val); err != nil {
t.Fatal(err)
}
println(root.js)
Expand All @@ -712,7 +745,7 @@ func TestValue_Add_Pop(t *testing.T) {
println(root.js)
}
require.Equal(t, c.js, root.js)
require.NoError(t, root.AddMany(vals))
require.NoError(t, root.AddMany(-1, vals))
require.NoError(t, root.PopMany(c.pops))
require.Equal(t, c.out, root.js)
}
Expand Down

0 comments on commit 83facca

Please sign in to comment.