config

package module
v0.0.0-...-57d38fd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2025 License: GPL-3.0, LGPL-3.0 Imports: 6 Imported by: 0

README

Sharkk Config File

SCF, pronounced scuff!

A very light, very intuitive config file format! Few symbols, few rules, quite flexible. Has support for comments, arrays, maps, and type guarantees.

Mercilessly benchmarked, fully tested. SCF competes toe-to-toe with Go's native JSON library, and handily outperforms the reference TOML and YAML implementations.

Format

SCF has very very simple syntax.

-- Lua style comments!
host  "localhost"
port  8080        -- no = for assignment!
debug true

allowed_ips {
    "192.168.1.1"
    "192.168.1.2"
    "10.0.0.1"
}

--[[
    Feel free to space out your explanations!

    All is well and good.
]]
database {
    host "db.example.com"
    port 5432
    credentials {
        username "admin"
        password "secure123"
    }
}

Installation

go get git.sharkk.net/Go/Config

Usage

Basic Usage
package main

import (
    "fmt"
    "os"
    
    config "git.sharkk.net/Go/Config"
)

func main() {
    file, err := os.Open("config.conf")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    
    // Pass a string to be loaded by the parser!
    cfg, err := config.Load(file)
    if err != nil {
        panic(err)
    }
    
    // Access values with type conversion.
    host, err := cfg.GetString("database.host")
    port, err := cfg.GetInt("database.port")
    debug, err := cfg.GetBool("debug")
    
    // Use default values for missing keys
    timeout := cfg.GetOr("timeout", 30).(int)

    // Get the entire map to traverse directly (cuts traversal time by 50%!)
    entireMap := cfg.GetData()
    other, err := entireMap["database"]["host"].(string)
}
Type Conversion

The parser automatically converts values to appropriate types:

boolValue, err   := cfg.GetBool("feature.enabled")
intValue, err    := cfg.GetInt("server.port")
floatValue, err  := cfg.GetFloat("threshold")
stringValue, err := cfg.GetString("app.name")
arrayValue, err  := cfg.GetArray("allowed_ips")
mapValue, err    := cfg.GetMap("database")

// Generic getter (returns any)
value, err := cfg.Get("some.key")
Accessing Arrays and Maps

Access array elements and nested map values using dot notation:

// Access the first element in the array
firstIP, err := cfg.GetString("allowed_ips.0")

// Access deeply nested values
username, err := cfg.GetString("database.credentials.username")

Performance

This parser provides competitive performance compared to popular formats like JSON, YAML, and TOML:

Benchmark Operations Time (ns/op) Memory (B/op) Allocations (allocs/op)
Small Config Files
Config 1,000,000 1,052 1,743 15
JSON 1,000,000 1,112 1,384 23
YAML 215,121 5,600 8,888 82
TOML 286,334 4,483 4,520 67
Medium Config Files
Config 211,863 5,696 4,056 74
JSON 261,925 4,602 5,344 89
YAML 50,010 23,965 21,577 347
TOML 68,420 17,639 16,348 208
Large Config Files
Config 55,338 21,556 12,208 207
JSON 70,219 17,202 18,140 297
YAML 12,536 95,945 65,568 1,208
TOML 14,732 74,198 66,050 669

Benchmarked on AMD Ryzen 9 7950X 16-Core Processor

Why Choose This Parser?

  • Readability: Simple syntax that's easy for humans to read and write
  • Flexibility: Supports various data types and nested structures
  • Performance: Fast parsing with minimal overhead
  • Type Safety: Strong typing with automatic conversion
  • Simplicity: No external dependencies required

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnterminatedString  = errors.New("unterminated string")
	ErrUnterminatedEscape  = errors.New("unterminated escape sequence")
	ErrUnterminatedComment = errors.New("unclosed block comment")
	ErrInvalidComment      = errors.New("invalid comment")
	ErrNameStartWithLetter = errors.New("name must start with letter")
)

Pre-declared errors to reduce allocations

Functions

func GetArray

func GetArray() *[]any

GetArray gets a slice from the pool

func GetByteSlice

func GetByteSlice() *[]byte

GetByteSlice gets a byte slice from the pool

func GetMap

func GetMap() *map[string]any

GetMap gets a map from the pool

func PutArray

func PutArray(a *[]any)

PutArray returns a slice to the pool

func PutByteSlice

func PutByteSlice(b *[]byte)

PutByteSlice returns a byte slice to the pool

func PutMap

func PutMap(m *map[string]any)

PutMap returns a map to the pool after clearing it

func ReleaseScanner

func ReleaseScanner(s *Scanner)

ReleaseScanner returns a scanner to the pool

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config holds a single hierarchical structure and handles parsing

func Load

func Load(r io.Reader) (*Config, error)

Load parses a config from a reader

func NewConfig

func NewConfig() *Config

NewConfig creates a new empty config

func (*Config) Error

func (c *Config) Error(msg string) error

Error creates an error with line information from the current token

func (*Config) Get

func (c *Config) Get(key string) (any, error)

Get retrieves a value from the config using dot notation

func (*Config) GetArray

func (c *Config) GetArray(key string) ([]any, error)

GetArray gets a value as []any

func (*Config) GetBool

func (c *Config) GetBool(key string) (bool, error)

GetBool gets a value as boolean

func (*Config) GetData

func (c *Config) GetData() map[string]any

GetData retrieves the entirety of the internal data map

func (*Config) GetFloat

func (c *Config) GetFloat(key string) (float64, error)

GetFloat gets a value as float64

func (*Config) GetInt

func (c *Config) GetInt(key string) (int, error)

GetInt gets a value as int64

func (*Config) GetMap

func (c *Config) GetMap(key string) (map[string]any, error)

GetMap gets a value as map[string]any

func (*Config) GetOr

func (c *Config) GetOr(key string, defaultValue any) any

GetOr retrieves a value or returns a default if not found

func (*Config) GetString

func (c *Config) GetString(key string) (string, error)

GetString gets a value as string

func (*Config) Parse

func (c *Config) Parse(r io.Reader) error

Parse parses the config from a reader

func (*Config) Release

func (c *Config) Release()

Release frees any resources and returns them to pools

type Scanner

type Scanner struct {
	// contains filtered or unexported fields
}

Scanner handles the low-level parsing of the configuration format

func NewScanner

func NewScanner(r io.Reader) *Scanner

NewScanner creates a new scanner from a pool

func (*Scanner) Error

func (s *Scanner) Error(msg string) error

Error creates an error with line and column information

func (*Scanner) NextToken

func (s *Scanner) NextToken() (Token, error)

NextToken scans and returns the next token

func (*Scanner) PeekByte

func (s *Scanner) PeekByte() (byte, error)

PeekByte looks at the next byte without consuming it

func (*Scanner) PeekBytes

func (s *Scanner) PeekBytes(n int) ([]byte, error)

PeekBytes looks at the next n bytes without consuming them

func (*Scanner) ReadByte

func (s *Scanner) ReadByte() (byte, error)

ReadByte reads a single byte from the input

func (*Scanner) SkipWhitespace

func (s *Scanner) SkipWhitespace() error

SkipWhitespace skips whitespace characters

func (*Scanner) UnreadByte

func (s *Scanner) UnreadByte() error

UnreadByte pushes back a byte to the reader

func (*Scanner) UnreadToken

func (s *Scanner) UnreadToken(token Token)

UnreadToken stores a token to be returned by the next call to NextToken

type Token

type Token struct {
	Type   TokenType
	Value  []byte // Not modified after returning - caller must copy if needed
	Line   int
	Column int
}

Token represents a lexical token

type TokenType

type TokenType int

TokenType represents the type of token

const (
	TokenError TokenType = iota
	TokenEOF
	TokenName
	TokenString
	TokenNumber
	TokenBoolean
	TokenOpenBrace
	TokenCloseBrace
	TokenComment
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL