Skip to content

Commit

Permalink
fix: Return error on empty space-only input
Browse files Browse the repository at this point in the history
resolve #5
  • Loading branch information
romshark committed Jan 23, 2022
1 parent 916acef commit 53f281d
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
46 changes: 38 additions & 8 deletions jscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ var itrPool = sync.Pool{
},
}

func getItrFromPool(s string, escapePath bool) *Iterator {
func getItrFromPool(
s string,
escapePath bool,
startIndex int,
) *Iterator {
i := itrPool.Get().(*Iterator)
i.st.Reset()
i.escapePath = escapePath
Expand All @@ -139,7 +143,7 @@ func getItrFromPool(s string, escapePath bool) *Iterator {
i.ValueType = 0
i.Level = 0
i.KeyStart, i.KeyEnd, i.KeyLenEscaped = -1, -1, -1
i.ValueStart, i.ValueEnd = 0, -1
i.ValueStart, i.ValueEnd = startIndex, -1
i.ArrayIndex = 0
i.expect = expectVal
return i
Expand Down Expand Up @@ -208,11 +212,24 @@ func Get(s, path string, escapePath bool, fn func(*Iterator)) Error {

// Validate returns an error if s is invalid JSON.
func Validate(s string) Error {
if s == "" {
return Error{Code: ErrorCodeUnexpectedEOF}
startIndex, illegal := strfind.EndOfWhitespaceSeq(s)
if illegal {
return Error{
Src: s,
Index: startIndex,
Code: ErrorCodeIllegalControlCharacter,
}
}

if startIndex >= len(s) {
return Error{
Src: s,
Index: startIndex,
Code: ErrorCodeUnexpectedEOF,
}
}

i := getItrFromPool(s, false)
i := getItrFromPool(s, false, startIndex)
defer itrPool.Put(i)

for i.ValueStart < len(s) {
Expand Down Expand Up @@ -455,11 +472,24 @@ func Scan(
s string,
fn func(*Iterator) (err bool),
) Error {
if s == "" {
return Error{Code: ErrorCodeUnexpectedEOF}
startIndex, illegal := strfind.EndOfWhitespaceSeq(s)
if illegal {
return Error{
Src: s,
Index: startIndex,
Code: ErrorCodeIllegalControlCharacter,
}
}

if startIndex >= len(s) {
return Error{
Src: s,
Index: startIndex,
Code: ErrorCodeUnexpectedEOF,
}
}

i := getItrFromPool(s, o.EscapePath)
i := getItrFromPool(s, o.EscapePath, startIndex)
defer itrPool.Put(i)

if o.CachePath {
Expand Down
46 changes: 38 additions & 8 deletions jscan_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ var itrPoolBytes = sync.Pool{
},
}

func getItrBytesFromPool(s []byte, escapePath bool) *IteratorBytes {
func getItrBytesFromPool(
s []byte,
escapePath bool,
startIndex int,
) *IteratorBytes {
i := itrPoolBytes.Get().(*IteratorBytes)
i.st.Reset()
i.escapePath = escapePath
Expand All @@ -131,7 +135,7 @@ func getItrBytesFromPool(s []byte, escapePath bool) *IteratorBytes {
i.ValueType = 0
i.Level = 0
i.KeyStart, i.KeyEnd, i.KeyLenEscaped = -1, -1, -1
i.ValueStart, i.ValueEnd = 0, -1
i.ValueStart, i.ValueEnd = startIndex, -1
i.ArrayIndex = 0
i.expect = expectVal
i.keyBuf = i.keyBuf[:0]
Expand Down Expand Up @@ -200,11 +204,24 @@ func GetBytes(

// ValidateBytes returns an error if s is invalid JSON.
func ValidateBytes(s []byte) ErrorBytes {
if len(s) < 1 {
return ErrorBytes{Code: ErrorCodeUnexpectedEOF}
startIndex, illegal := strfind.EndOfWhitespaceSeqBytes(s)
if illegal {
return ErrorBytes{
Src: s,
Index: startIndex,
Code: ErrorCodeIllegalControlCharacter,
}
}

if startIndex >= len(s) {
return ErrorBytes{
Src: s,
Index: startIndex,
Code: ErrorCodeUnexpectedEOF,
}
}

i := getItrBytesFromPool(s, false)
i := getItrBytesFromPool(s, false, startIndex)
defer itrPoolBytes.Put(i)

for i.ValueStart < len(s) {
Expand Down Expand Up @@ -442,11 +459,24 @@ func ScanBytes(
s []byte,
fn func(*IteratorBytes) (err bool),
) ErrorBytes {
if len(s) < 1 {
return ErrorBytes{Code: ErrorCodeUnexpectedEOF}
startIndex, illegal := strfind.EndOfWhitespaceSeqBytes(s)
if illegal {
return ErrorBytes{
Src: s,
Index: startIndex,
Code: ErrorCodeIllegalControlCharacter,
}
}

if startIndex >= len(s) {
return ErrorBytes{
Src: s,
Index: startIndex,
Code: ErrorCodeUnexpectedEOF,
}
}

i := getItrBytesFromPool(s, o.EscapePath)
i := getItrBytesFromPool(s, o.EscapePath, startIndex)
defer itrPoolBytes.Put(i)

if o.CachePath {
Expand Down
38 changes: 34 additions & 4 deletions jscan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,16 @@ func TestScanError(t *testing.T) {
input: "",
expect: `error at index 0: unexpected EOF`,
},
{
name: "empty input",
input: " ",
expect: `error at index 1: unexpected EOF`,
},
{
name: "empty input",
input: "\t\r\n ",
expect: `error at index 4: unexpected EOF`,
},
{
name: "invalid literal",
input: "nul",
Expand Down Expand Up @@ -751,13 +761,13 @@ func TestScanError(t *testing.T) {
err := jscan.Scan(jscan.Options{
CachePath: true,
}, tt.input, check(t))
require.True(t, err.IsErr())
require.Equal(t, tt.expect, err.Error())
require.True(t, err.IsErr())
})
t.Run("nocachepath", func(t *testing.T) {
err := jscan.Scan(jscan.Options{}, tt.input, check(t))
require.True(t, err.IsErr())
require.Equal(t, tt.expect, err.Error())
require.True(t, err.IsErr())
})
})

Expand All @@ -776,15 +786,15 @@ func TestScanError(t *testing.T) {
err := jscan.ScanBytes(jscan.Options{
CachePath: true,
}, []byte(tt.input), check(t))
require.True(t, err.IsErr())
require.Equal(t, tt.expect, err.Error())
require.True(t, err.IsErr())
})
t.Run("nocachepath", func(t *testing.T) {
err := jscan.ScanBytes(
jscan.Options{}, []byte(tt.input), check(t),
)
require.True(t, err.IsErr())
require.Equal(t, tt.expect, err.Error())
require.True(t, err.IsErr())
})
})
})
Expand Down Expand Up @@ -877,6 +887,15 @@ func TestControlCharacters(t *testing.T) {

// Control characters outside of strings
t.Run("nonstring", func(t *testing.T) {
ForASCIIControlCharsExceptTRN(func(b byte) {
var buf bytes.Buffer
buf.WriteByte(b)
buf.WriteString("null")
test(t, buf.String(), fmt.Sprintf(
"error at index 0 (0x%x): illegal control character", b,
))
})

ForASCIIControlCharsExceptTRN(func(b byte) {
var buf bytes.Buffer
buf.WriteString("[")
Expand Down Expand Up @@ -1141,6 +1160,17 @@ func TestGet(t *testing.T) {
}
}

// func TestX(t *testing.T) {
// for _, v := range []string{
// " ",
// "0 0",
// } {
// if json.Valid([]byte(v)) != jscan.Valid(v) {
// t.Errorf("%#v", v)
// }
// }
// }

func TestGetNotFound(t *testing.T) {
for _, tt := range []struct {
json string
Expand Down

0 comments on commit 53f281d

Please sign in to comment.