diff --git a/bench/get_test.go b/bench/get_test.go index 63a83f5..7c76ece 100644 --- a/bench/get_test.go +++ b/bench/get_test.go @@ -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) } diff --git a/bench/parse_test.go b/bench/parse_test.go index f1a56b1..062ecae 100644 --- a/bench/parse_test.go +++ b/bench/parse_test.go @@ -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()) } } } diff --git a/data.go b/data.go index 31fcde0..499b82f 100644 --- a/data.go +++ b/data.go @@ -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 { diff --git a/tests/read_test.go b/tests/read_test.go index f803375..ba7d473 100644 --- a/tests/read_test.go +++ b/tests/read_test.go @@ -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 diff --git a/tests/write_test.go b/tests/write_test.go index 26b7aad..8841ec6 100644 --- a/tests/write_test.go +++ b/tests/write_test.go @@ -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