From d856804ca1b088863d08f99a5869472a12188656 Mon Sep 17 00:00:00 2001 From: fpatron Date: Sun, 1 Mar 2026 09:21:16 -0700 Subject: [PATCH] add initial pass with zero allocation --- README.md | 6 +++--- jsonc.go | 26 ++++++++++++++++++++++++++ v2/jsonc.go | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2ac78f7..9e8dd54 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ -# jsonc - https://pkg.go.dev/github.com/fpatron/jsonc +# jsonc [![Go CI](https://github.com/fpatron/jsonc/actions/workflows/go.yml/badge.svg)](https://github.com/fpatron/jsonc/actions/workflows/go.yml) +[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/fpatron/jsonc) -`jsonc` is an extension of the JSON data format that allows single and multi line comments and provides accurate parsing errors. +`jsonc` is an extension of the JSON data format that allows single and multi line comments. ## Instalation To install `jsonc`, use `go get`: @@ -13,7 +14,6 @@ To install `jsonc`, use `go get`: ## Features - **Comment Support**: Easily parse JSON files with single-line and multi-line comments. -- **Accurate Errors**: Errors while parsing will match original commented JSON. - **Simple API**: Uses a familiar API similar to the standard `encoding/json` package. ## Usage diff --git a/jsonc.go b/jsonc.go index dec6fab..915f99d 100644 --- a/jsonc.go +++ b/jsonc.go @@ -18,6 +18,32 @@ func stripComments(data []byte) []byte { ) state := OUTSIDE + hasComment := false +scanLoop: + for i := 0; i < len(data); i++ { + switch state { + case OUTSIDE: + if data[i] == '/' && i+1 < len(data) && (data[i+1] == '/' || data[i+1] == '*') { + hasComment = true + break scanLoop + } + if data[i] == '"' { + state = IN_STRING + } + case IN_STRING: + if data[i] == '\\' && i+1 < len(data) { + i++ + } else if data[i] == '"' { + state = OUTSIDE + } + } + } + + if !hasComment { + return data + } + + state = OUTSIDE result := make([]byte, 0, len(data)) for i := 0; i < len(data); i++ { diff --git a/v2/jsonc.go b/v2/jsonc.go index 9215900..b90a9b9 100644 --- a/v2/jsonc.go +++ b/v2/jsonc.go @@ -16,6 +16,32 @@ func stripComments(data []byte) []byte { ) state := OUTSIDE + hasComment := false +scanLoop: + for i := 0; i < len(data); i++ { + switch state { + case OUTSIDE: + if data[i] == '/' && i+1 < len(data) && (data[i+1] == '/' || data[i+1] == '*') { + hasComment = true + break scanLoop + } + if data[i] == '"' { + state = IN_STRING + } + case IN_STRING: + if data[i] == '\\' && i+1 < len(data) { + i++ + } else if data[i] == '"' { + state = OUTSIDE + } + } + } + + if !hasComment { + return data + } + + state = OUTSIDE result := make([]byte, 0, len(data)) for i := 0; i < len(data); i++ {