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

View File

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

30
data.go
View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"io" "io"
"maps" "maps"
"os"
"slices" "slices"
"strconv" "strconv"
) )
@ -15,6 +16,7 @@ type Data struct {
currentObject map[string]any currentObject map[string]any
stack []map[string]any stack []map[string]any
currentToken Token currentToken Token
lastError error
} }
func NewData() *Data { 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() data := NewData()
err := data.Parse(r) err := data.Parse(r)
if err != nil { if err != nil {
data.Release() 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 { func (d *Data) tokenToValue(token Token) any {

View File

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

View File

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