Compare commits

...

1 Commits

5 changed files with 79 additions and 55 deletions

View File

@ -20,9 +20,9 @@ func BenchmarkRetrieveSimpleValues(b *testing.B) {
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse config: %v", cfg.GetError().Error())
}
b.ResetTimer()
@ -75,9 +75,9 @@ func BenchmarkRetrieveNestedValues(b *testing.B) {
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse config: %v", cfg.GetError().Error())
}
b.ResetTimer()
@ -125,9 +125,9 @@ func BenchmarkRetrieveArrayValues(b *testing.B) {
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse config: %v", cfg.GetError().Error())
}
b.ResetTimer()
@ -180,9 +180,9 @@ func BenchmarkRetrieveMixedValues(b *testing.B) {
// Parse once before benchmarking retrieval
reader := strings.NewReader(configData)
cfg, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse config: %v", cfg.GetError().Error())
}
b.ResetTimer()
@ -531,14 +531,14 @@ write = 10
// Custom config
customReader := strings.NewReader(customConfig)
customCfg, err := config.Load(customReader)
if err != nil {
b.Fatalf("Failed to parse custom config: %v", err)
customCfg := config.Load(customReader)
if customCfg.HasError() {
b.Fatalf("Failed to parse custom config: %v", customCfg.GetError().Error())
}
// JSON config
var jsonResult map[string]any
err = json.Unmarshal([]byte(jsonConfig), &jsonResult)
err := json.Unmarshal([]byte(jsonConfig), &jsonResult)
if err != nil {
b.Fatalf("Failed to parse JSON: %v", err)
}

View File

@ -23,9 +23,9 @@ func BenchmarkSmallConfig(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
reader := strings.NewReader(smallConfig)
_, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse small config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse small config: %v", cfg.GetError().Error())
}
}
}
@ -74,9 +74,9 @@ func BenchmarkMediumConfig(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
reader := strings.NewReader(mediumConfig)
_, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse medium config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse small config: %v", cfg.GetError().Error())
}
}
}
@ -170,9 +170,9 @@ func BenchmarkLargeConfig(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
reader := strings.NewReader(largeConfig)
_, err := config.Load(reader)
if err != nil {
b.Fatalf("Failed to parse large config: %v", err)
cfg := config.Load(reader)
if cfg.HasError() {
b.Fatalf("Failed to parse small config: %v", cfg.GetError().Error())
}
}
}

30
data.go
View File

@ -4,6 +4,7 @@ import (
"fmt"
"io"
"maps"
"os"
"slices"
"strconv"
)
@ -15,6 +16,7 @@ type Data struct {
currentObject map[string]any
stack []map[string]any
currentToken Token
lastError error
}
func NewData() *Data {
@ -485,14 +487,36 @@ func (d *Data) parseObject() (any, error) {
}
}
func Load(r io.Reader) (*Data, error) {
func Load(r io.Reader) *Data {
data := NewData()
err := data.Parse(r)
if err != nil {
data.Release()
return nil, err
emptyData := NewData()
emptyData.lastError = err
return emptyData
}
return data, nil
return data
}
func LoadFromFile(filepath string) *Data {
file, err := os.Open(filepath)
if err != nil {
emptyData := NewData()
emptyData.lastError = err
return emptyData
}
defer file.Close()
return Load(file)
}
func (d *Data) HasError() bool {
return d.lastError != nil
}
func (d *Data) GetError() error {
return d.lastError
}
func (d *Data) tokenToValue(token Token) any {

View File

@ -18,9 +18,9 @@ func TestBasicKeyValuePairs(t *testing.T) {
negativeFloat -2.5
stringValue "hello world"
`
config, err := fin.Load(strings.NewReader(input))
if err != nil {
t.Fatalf("unexpected error: %v", err)
config := fin.Load(strings.NewReader(input))
if config.HasError() {
t.Fatalf("unexpected error: %v", config.GetError().Error())
}
// Verify boolean values
@ -98,9 +98,9 @@ func TestComments(t *testing.T) {
}
`
config, err := fin.Load(strings.NewReader(input))
if err != nil {
t.Fatalf("unexpected error: %v", err)
config := fin.Load(strings.NewReader(input))
if config.HasError() {
t.Fatalf("unexpected error: %v", config.GetError().Error())
}
// Verify that comments are properly ignored and values are parsed
@ -144,9 +144,9 @@ func TestArrays(t *testing.T) {
}
`
config, err := fin.Load(strings.NewReader(input))
if err != nil {
t.Fatalf("unexpected error: %v", err)
config := fin.Load(strings.NewReader(input))
if config.HasError() {
t.Fatalf("unexpected error: %v", config.GetError().Error())
}
// Verify simple array
@ -221,9 +221,9 @@ func TestMaps(t *testing.T) {
}
`
config, err := fin.Load(strings.NewReader(input))
if err != nil {
t.Fatalf("unexpected error: %v", err)
config := fin.Load(strings.NewReader(input))
if config.HasError() {
t.Fatalf("unexpected error: %v", config.GetError().Error())
}
// Verify simple map

View File

@ -28,9 +28,9 @@ func TestBasicWrite(t *testing.T) {
}
// Read back
readData, err := fin.Load(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("unexpected error loading written data: %v", err)
readData := fin.Load(bytes.NewReader(buf.Bytes()))
if readData.HasError() {
t.Fatalf("unexpected error loading written data: %v", readData.GetError().Error())
}
// Verify values
@ -72,9 +72,9 @@ func TestArrayWrite(t *testing.T) {
}
// Read back
readData, err := fin.Load(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("unexpected error loading written data: %v", err)
readData := fin.Load(bytes.NewReader(buf.Bytes()))
if readData.HasError() {
t.Fatalf("unexpected error loading written data: %v", readData.GetError().Error())
}
// Verify arrays
@ -149,9 +149,9 @@ func TestMapWrite(t *testing.T) {
}
// Read back
readData, err := fin.Load(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("unexpected error loading written data: %v", err)
readData := fin.Load(bytes.NewReader(buf.Bytes()))
if readData.HasError() {
t.Fatalf("unexpected error loading written data: %v", readData.GetError().Error())
}
// Verify simple map
@ -198,9 +198,9 @@ func TestSpecialCasesWrite(t *testing.T) {
}
// Read back
readData, err := fin.Load(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("unexpected error loading written data: %v", err)
readData := fin.Load(bytes.NewReader(buf.Bytes()))
if readData.HasError() {
t.Fatalf("unexpected error loading written data: %v", readData.GetError().Error())
}
// Verify combined value+object
@ -231,9 +231,9 @@ func TestStringEscapingWrite(t *testing.T) {
}
// Read back
readData, err := fin.Load(bytes.NewReader(buf.Bytes()))
if err != nil {
t.Fatalf("unexpected error loading written data: %v", err)
readData := fin.Load(bytes.NewReader(buf.Bytes()))
if readData.HasError() {
t.Fatalf("unexpected error loading written data: %v", readData.GetError().Error())
}
// Verify escaped strings