Skip to content

Commit

Permalink
Merge pull request #3 from gowebpki/bugfix/2-json-null
Browse files Browse the repository at this point in the history
Bugfix/2 json null
  • Loading branch information
jordan2175 authored Oct 15, 2023
2 parents 680d943 + 8f9bcb7 commit 1a4242a
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 21 deletions.
46 changes: 37 additions & 9 deletions jcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ type jcsData struct {
}

// JSON standard escapes (modulo \u)
var asciiEscapes = []byte{'\\', '"', 'b', 'f', 'n', 'r', 't'}
var binaryEscapes = []byte{'\\', '"', '\b', '\f', '\n', '\r', '\t'}
var (
asciiEscapes = []byte{'\\', '"', 'b', 'f', 'n', 'r', 't'}
binaryEscapes = []byte{'\\', '"', '\b', '\f', '\n', '\r', '\t'}
)

// JSON literals
var literals = []string{"true", "false", "null"}
Expand All @@ -47,7 +49,7 @@ func Transform(jsonData []byte) ([]byte, error) {
jd.jsonData = jsonData
j := &jd

transformed, err := j.parseElement()
transformed, err := j.parseEntry()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -77,7 +79,7 @@ func (j *jcsData) nextChar() (byte, error) {
return 0, errors.New("Unexpected EOF reached")
}

//scan advances index on jsonData to the first non whitespace character and returns it.
// scan advances index on jsonData to the first non whitespace character and returns it.
func (j *jcsData) scan() (byte, error) {
for {
c, err := j.nextChar()
Expand Down Expand Up @@ -147,6 +149,28 @@ CoreLoop:
return quotedString.String()
}

// parseEntry is the entrypoint into the parsing control flow
func (j *jcsData) parseEntry() (string, error) {
c, err := j.scan()
if err != nil {
return "", err
}
j.index--

switch c {
case '{', '"', '[':
return j.parseElement()
default:
value, err := parseLiteral(string(j.jsonData))
if err != nil {
return "", err
}

j.index = len(j.jsonData)
return value, nil
}
}

func (j *jcsData) parseQuotedString() (string, error) {
var rawString strings.Builder

Expand Down Expand Up @@ -237,9 +261,10 @@ func (j *jcsData) parseSimpleType() (string, error) {
var token strings.Builder

j.index--
//no condition is needed here.
//if the buffer reaches EOF scan returns an error, or we terminate because the
//json simple type terminates

// no condition is needed here.
// if the buffer reaches EOF scan returns an error, or we terminate because the
// json simple type terminates
for {
c, err := j.scan()
if err != nil {
Expand All @@ -258,7 +283,10 @@ func (j *jcsData) parseSimpleType() (string, error) {
return "", errors.New("Missing argument")
}

value := token.String()
return parseLiteral(token.String())
}

func parseLiteral(value string) (string, error) {
// Is it a JSON literal?
for _, literal := range literals {
if literal == value {
Expand Down Expand Up @@ -391,7 +419,7 @@ CoreLoop:
}

if c == '}' {
//advance index because of peeked '}'
// advance index because of peeked '}'
j.index++
break
}
Expand Down
54 changes: 46 additions & 8 deletions jcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ package jcs
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"

Expand All @@ -31,16 +31,34 @@ func errorOccurred(activity string, err error) string {
}

func doesNotMatchExpected(expectedField, expectedValue, actualField, actualValue string) string {
return failedBecause(fmt.Sprintf("%s [%s] does not match expected %s [%s]\n", actualField, actualValue, expectedField, expectedValue))
return failedBecause(
fmt.Sprintf(
"%s [%s] does not match expected %s [%s]\n",
actualField,
actualValue,
expectedField,
expectedValue,
),
)
}

func TestTransform(t *testing.T) {
r := require.New(t)

testCases := []struct {
desc string
filename string
}{
{
desc: "Null",
filename: "null.json",
},
{
desc: "True",
filename: "true.json",
},
{
desc: "False",
filename: "false.json",
},
{
desc: "Arrays",
filename: "arrays.json",
Expand Down Expand Up @@ -72,11 +90,15 @@ func TestTransform(t *testing.T) {
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
input, err := ioutil.ReadFile(filepath.Join(pathTestData,
tC := tC
t.Parallel()
r := require.New(t)

input, err := os.ReadFile(filepath.Join(pathTestData,
pathInputRelativeToTestData, tC.filename))
r.NoError(err, errorOccurred("reading test input json", err))

output, err := ioutil.ReadFile(filepath.Join(pathTestData,
output, err := os.ReadFile(filepath.Join(pathTestData,
pathOutputRelativeToTestData, tC.filename))
r.NoError(err, errorOccurred("reading expected transformed output sample", err))

Expand All @@ -86,8 +108,24 @@ func TestTransform(t *testing.T) {
twiceTransformed, err := Transform(input)
r.NoError(err, errorOccurred("transforming transformed input", err))

r.True(bytes.Equal(transformed, output), doesNotMatchExpected("JSON", string(output), "transformed JSON", string(transformed)))
r.True(bytes.Equal(twiceTransformed, transformed), doesNotMatchExpected("transformed JSON", string(transformed), "twice transformed JSON", string(twiceTransformed)))
r.True(
bytes.Equal(transformed, output),
doesNotMatchExpected(
"JSON",
string(output),
"transformed JSON",
string(transformed),
),
)
r.True(
bytes.Equal(twiceTransformed, transformed),
doesNotMatchExpected(
"transformed JSON",
string(transformed),
"twice transformed JSON",
string(twiceTransformed),
),
)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ func verify(fileName string) {
recycled, err2 := jcs.Transform(actual)
check(err2)
expected := read(fileName, "output")
var utf8InHex = "\nFile: " + fileName
var byteCount = 0
var next = false
utf8InHex := "\nFile: " + fileName
byteCount := 0
next := false
for _, b := range actual {
if byteCount%32 == 0 {
utf8InHex = utf8InHex + "\n"
Expand Down Expand Up @@ -83,7 +83,7 @@ func main() {
verify(file.Name())
}
if failures == 0 {
fmt.Println("All tests succeeded!\n")
fmt.Println("All tests succeeded!")
} else {
fmt.Printf("\n****** ERRORS: %d *******\n", failures)
}
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions testdata/input/false.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
false
1 change: 1 addition & 0 deletions testdata/input/null.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
null
1 change: 1 addition & 0 deletions testdata/input/true.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
1 change: 1 addition & 0 deletions testdata/outhex/false.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
66 61 6C 73 65
1 change: 1 addition & 0 deletions testdata/outhex/null.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6E 75 6C 6C
1 change: 1 addition & 0 deletions testdata/outhex/true.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
74 72 75 65
1 change: 1 addition & 0 deletions testdata/output/false.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
false
1 change: 1 addition & 0 deletions testdata/output/null.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
null
1 change: 1 addition & 0 deletions testdata/output/true.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true

0 comments on commit 1a4242a

Please sign in to comment.