Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions jsonc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,45 +18,42 @@ func stripComments(data []byte) []byte {
)

state := OUTSIDE
result := make([]byte, len(data))
copy(result, data)
result := make([]byte, 0, len(data))

for i := 0; i < len(result); i++ {
for i := 0; i < len(data); i++ {
switch state {
case OUTSIDE:
if data[i] == '/' && i+1 < len(data) {
if data[i+1] == '/' {
state = SINGLE_LINE
result[i] = ' '
result[i+1] = ' '
i++
} else if data[i+1] == '*' {
state = MULTI_LINE
result[i] = ' '
result[i+1] = ' '
i++
} else {
result = append(result, data[i])
}
} else if data[i] == '"' {
state = IN_STRING
} else {
if data[i] == '"' {
state = IN_STRING
}
result = append(result, data[i])
}
case SINGLE_LINE:
if data[i] == '\n' {
state = OUTSIDE
} else {
result[i] = ' '
result = append(result, '\n')
}
case MULTI_LINE:
if data[i] == '*' && i+1 < len(result) && data[i+1] == '/' {
if data[i] == '*' && i+1 < len(data) && data[i+1] == '/' {
state = OUTSIDE
result[i] = ' '
result[i+1] = ' '
i++
} else if result[i] != '\n' {
result[i] = ' '
}
case IN_STRING:
result = append(result, data[i])
if data[i] == '\\' && i+1 < len(data) {
i++
result = append(result, data[i])
} else if data[i] == '"' {
state = OUTSIDE
}
Expand Down
43 changes: 18 additions & 25 deletions jsonc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,56 +82,49 @@ func TestStripComments(t *testing.T) {
{
name: "Single line comment",
input: `{"name": "Alice"} // Comment`,
expected: `{"name": "Alice"} `,
expected: `{"name": "Alice"} `,
},
{
name: "Multi-line comment",
input: `{"name": "Alice" /* Comment */}`,
expected: `{"name": "Alice" }`,
expected: `{"name": "Alice" }`,
},
{
name: "Nested comments",
input: `{"name": "Alice" /* Comment // Nested comment */}`,
expected: `{"name": "Alice" }`,
expected: `{"name": "Alice" }`,
},
{
name: "Comment at the end of file without newline",
input: `{"name": "Alice"} // Comment`,
expected: `{"name": "Alice"} `,
expected: `{"name": "Alice"} `,
},
{
name: "Comment at the end of file with newline",
input: `{"name": "Alice"} // Comment
`,
expected: `{"name": "Alice"}
`,
expected: "{\"name\": \"Alice\"} \n",
},
{
name: "Multiple single line comments",
input: `// Comment 1
// Comment 2
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "Multiple multi-line comments",
input: `/* Comment 1 */
/* Comment 2 */
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "Mixed comments",
input: `/* Comment 1 */
// Comment 2
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "No comments",
Expand All @@ -151,12 +144,12 @@ func TestStripComments(t *testing.T) {
{
name: "Comment slashes inside string followed by actual comment",
input: `{"name": "//Alice"} // Comment`,
expected: `{"name": "//Alice"} `,
expected: `{"name": "//Alice"} `,
},
{
name: "Multi-line comment delimiters inside string",
input: `{"name": "/*Alice*/"} /* Comment */`,
expected: `{"name": "/*Alice*/"} `,
expected: `{"name": "/*Alice*/"} `,
},
{
name: "Empty input",
Expand All @@ -166,22 +159,22 @@ func TestStripComments(t *testing.T) {
{
name: "Only single line comment",
input: `// Comment`,
expected: ` `,
expected: ``,
},
{
name: "Only multi-line comment",
input: `/* Comment */`,
expected: ` `,
expected: ``,
},
{
name: "Comment after a comma",
input: `{"name": "Alice", /* Comment */ "age": 30}`,
expected: `{"name": "Alice", "age": 30}`,
expected: `{"name": "Alice", "age": 30}`,
},
{
name: "Comment inside array",
input: `["Alice", /* Comment */ "Bob"]`,
expected: `["Alice", "Bob"]`,
expected: `["Alice", "Bob"]`,
},
{
name: "Newline inside string",
Expand All @@ -195,19 +188,19 @@ func TestStripComments(t *testing.T) {
input: `{"message": "Hello
World"} // Comment`,
expected: `{"message": "Hello
World"} `,
World"} `,
},
{
name: "Newline inside string with multi-line comment after",
input: `{"message": "Hello
World"} /* Comment */`,
expected: `{"message": "Hello
World"} `,
World"} `,
},
{
name: "Multiple newlines inside string & single comment at the end",
input: "{\"message\": \"Hello\n\nWorld\"}// ",
expected: "{\"message\": \"Hello\n\nWorld\"} ",
expected: "{\"message\": \"Hello\n\nWorld\"}",
},
{
name: "Newline inside string with actual newline after",
Expand All @@ -216,7 +209,7 @@ World"}
// Comment`,
expected: `{"message": "Hello
World"}
`,
`,
},
}

Expand Down
29 changes: 13 additions & 16 deletions v2/jsonc.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,42 @@ func stripComments(data []byte) []byte {
)

state := OUTSIDE
result := make([]byte, len(data))
copy(result, data)
result := make([]byte, 0, len(data))

for i := 0; i < len(result); i++ {
for i := 0; i < len(data); i++ {
switch state {
case OUTSIDE:
if data[i] == '/' && i+1 < len(data) {
if data[i+1] == '/' {
state = SINGLE_LINE
result[i] = ' '
result[i+1] = ' '
i++
} else if data[i+1] == '*' {
state = MULTI_LINE
result[i] = ' '
result[i+1] = ' '
i++
} else {
result = append(result, data[i])
}
} else if data[i] == '"' {
state = IN_STRING
} else {
if data[i] == '"' {
state = IN_STRING
}
result = append(result, data[i])
}
case SINGLE_LINE:
if data[i] == '\n' {
state = OUTSIDE
} else {
result[i] = ' '
result = append(result, '\n')
}
case MULTI_LINE:
if data[i] == '*' && i+1 < len(result) && data[i+1] == '/' {
if data[i] == '*' && i+1 < len(data) && data[i+1] == '/' {
state = OUTSIDE
result[i] = ' '
result[i+1] = ' '
i++
} else if result[i] != '\n' {
result[i] = ' '
}
case IN_STRING:
result = append(result, data[i])
if data[i] == '\\' && i+1 < len(data) {
i++
result = append(result, data[i])
} else if data[i] == '"' {
state = OUTSIDE
}
Expand Down
43 changes: 18 additions & 25 deletions v2/jsonc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,56 +78,49 @@ func TestStripComments(t *testing.T) {
{
name: "Single line comment",
input: `{"name": "Alice"} // Comment`,
expected: `{"name": "Alice"} `,
expected: `{"name": "Alice"} `,
},
{
name: "Multi-line comment",
input: `{"name": "Alice" /* Comment */}`,
expected: `{"name": "Alice" }`,
expected: `{"name": "Alice" }`,
},
{
name: "Nested comments",
input: `{"name": "Alice" /* Comment // Nested comment */}`,
expected: `{"name": "Alice" }`,
expected: `{"name": "Alice" }`,
},
{
name: "Comment at the end of file without newline",
input: `{"name": "Alice"} // Comment`,
expected: `{"name": "Alice"} `,
expected: `{"name": "Alice"} `,
},
{
name: "Comment at the end of file with newline",
input: `{"name": "Alice"} // Comment
`,
expected: `{"name": "Alice"}
`,
expected: "{\"name\": \"Alice\"} \n",
},
{
name: "Multiple single line comments",
input: `// Comment 1
// Comment 2
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "Multiple multi-line comments",
input: `/* Comment 1 */
/* Comment 2 */
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "Mixed comments",
input: `/* Comment 1 */
// Comment 2
{"name": "Alice"}`,
expected: `

{"name": "Alice"}`,
expected: "\n\t\t\t\n\t\t\t{\"name\": \"Alice\"}",
},
{
name: "No comments",
Expand All @@ -147,12 +140,12 @@ func TestStripComments(t *testing.T) {
{
name: "Comment slashes inside string followed by actual comment",
input: `{"name": "//Alice"} // Comment`,
expected: `{"name": "//Alice"} `,
expected: `{"name": "//Alice"} `,
},
{
name: "Multi-line comment delimiters inside string",
input: `{"name": "/*Alice*/"} /* Comment */`,
expected: `{"name": "/*Alice*/"} `,
expected: `{"name": "/*Alice*/"} `,
},
{
name: "Empty input",
Expand All @@ -162,22 +155,22 @@ func TestStripComments(t *testing.T) {
{
name: "Only single line comment",
input: `// Comment`,
expected: ` `,
expected: ``,
},
{
name: "Only multi-line comment",
input: `/* Comment */`,
expected: ` `,
expected: ``,
},
{
name: "Comment after a comma",
input: `{"name": "Alice", /* Comment */ "age": 30}`,
expected: `{"name": "Alice", "age": 30}`,
expected: `{"name": "Alice", "age": 30}`,
},
{
name: "Comment inside array",
input: `["Alice", /* Comment */ "Bob"]`,
expected: `["Alice", "Bob"]`,
expected: `["Alice", "Bob"]`,
},
{
name: "Newline inside string",
Expand All @@ -191,19 +184,19 @@ func TestStripComments(t *testing.T) {
input: `{"message": "Hello
World"} // Comment`,
expected: `{"message": "Hello
World"} `,
World"} `,
},
{
name: "Newline inside string with multi-line comment after",
input: `{"message": "Hello
World"} /* Comment */`,
expected: `{"message": "Hello
World"} `,
World"} `,
},
{
name: "Multiple newlines inside string & single comment at the end",
input: "{\"message\": \"Hello\n\nWorld\"}// ",
expected: "{\"message\": \"Hello\n\nWorld\"} ",
expected: "{\"message\": \"Hello\n\nWorld\"}",
},
{
name: "Newline inside string with actual newline after",
Expand All @@ -212,7 +205,7 @@ World"}
// Comment`,
expected: `{"message": "Hello
World"}
`,
`,
},
}

Expand Down