diff --git a/config/config.go b/config/config.go index 476b85b..e52e299 100644 --- a/config/config.go +++ b/config/config.go @@ -1,8 +1,8 @@ package config +import "io" import "os" import "bufio" -import "errors" import "strings" import "strconv" import "image/color" @@ -20,12 +20,52 @@ const ( // ErrorIllegalName is thrown when an application name contains illegal // characters such as a slash. ErrorIllegalName Error = iota + + // ErrorNoSeparator is thrown when a configuration file has an + // incorrectly formatted key-value pair. + ErrorNoSeparator + + // ErrorUnknownParameter is thrown when an unknown key is encountered in + // a configuration file. + ErrorUnknownParameter + + // ErrorWrongColorLength is thrown when a configuration file has a color + // literal with a total length unequal to 7. + ErrorWrongColorLength + + // ErrorMalformedColorLiteral is thrown when a configuration file has an + // improperly formatted color literal, or a color literal was expected + // and something else was encountered. + ErrorMalformedColorLiteral + + // ErrorMalformedIntegerLiteral is thrown when a configuration file has + // an improperly formatted integer literal, or an integer literal was + // expected and something else was encountered. + ErrorMalformedIntegerLiteral + + // ErrorMalformedFloatLiteral is thrown when a configuration file has + // an improperly formatted float literal, or a float literal was + // expected and something else was encountered. + ErrorMalformedFloatLiteral ) +// Error returns a description of the error. func (err Error) Error () (description string) { switch err { case ErrorIllegalName: description = "name contains illegal characters" + case ErrorNoSeparator: + description = "key:value pair has no separator" + case ErrorUnknownParameter: + description = "unknown parameter" + case ErrorWrongColorLength: + description = "color literal has the wrong length" + case ErrorMalformedColorLiteral: + description = "malformed color literal" + case ErrorMalformedIntegerLiteral: + description = "malformed integer literal" + case ErrorMalformedFloatLiteral: + description = "malformed float literal" } return @@ -36,10 +76,12 @@ type Type int const ( // string + // It is just a basic string with inner whitespace preserved. No quotes + // should be used in the file. TypeString Type = iota // Type: image/color.RGBA - // Represented as a 24 bit hexidecimal number (case insensitive) + // Represented as a 24 bit hexadecimal number (case insensitive) // preceded with a # sign where the first two digits represent the red // channel, the middle two digits represent the green channel, and the // last two digits represent the blue channel. @@ -112,16 +154,24 @@ func (config *Config) Load (name string) (err error) { configDirs = append(configDirs, configHome) for _, directory := range configDirs { - config.loadFile(filepath.Join(directory, name, name + ".conf")) + path := filepath.Join(directory, name, name + ".conf") + + file, fileErr := os.Open(path) + if fileErr != nil { continue } + parseErr := config.loadFile(file) + defer file.Close() + + if parseErr != nil { + println ( + "config: error in file", path + + ":", parseErr.Error()) + } } return } -func (config *Config) loadFile (path string) { - file, err := os.Open(path) - if err != nil { return } - +func (config *Config) loadFile (file io.Reader) (err error) { scanner := bufio.NewScanner(file) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) @@ -136,22 +186,16 @@ func (config *Config) loadFile (path string) { key, value, found := strings.Cut(scanner.Text(), ":") if !found { - println ( - "config: error in file", path + - ": key-value separator missing") - println(scanner.Text()) - continue + err = ErrorNoSeparator + return } key = strings.TrimSpace(key) value = strings.TrimSpace(value) what, isKnown := config.LegalParameters[key] if !isKnown { - println ( - "config: error in file", path + - ": unknown parameter") - println(scanner.Text()) - continue + err = ErrorUnknownParameter + return } switch what { @@ -161,24 +205,15 @@ func (config *Config) loadFile (path string) { case TypeColor: var valueColor color.Color valueColor, err = parseColor(value) - if err != nil { - println ( - "config: error in file", path + - ":", err) - println(scanner.Text()) - continue - } + if err != nil { return } config.Parameters[key] = valueColor case TypeInteger: var valueInt int valueInt, err = strconv.Atoi(value) if err != nil { - println ( - "config: error in file", path + - ": malformed integer literal") - println(scanner.Text()) - continue + err = ErrorMalformedIntegerLiteral + return } config.Parameters[key] = valueInt @@ -186,11 +221,8 @@ func (config *Config) loadFile (path string) { var valueFloat float64 valueFloat, err = strconv.ParseFloat(value, 64) if err != nil { - println ( - "config: error in file", path + - ": malformed float literal") - println(scanner.Text()) - continue + err = ErrorMalformedFloatLiteral + return } config.Parameters[key] = valueFloat @@ -211,14 +243,14 @@ func (config *Config) loadFile (path string) { func parseColor (value string) (valueColor color.Color, err error) { if value[0] == '#' { if len(value) != 7 { - err = errors.New("wrong length color literal") + err = ErrorWrongColorLength return } var colorInt uint64 colorInt, err = strconv.ParseUint(value[1:7], 16, 24) if err != nil { - err = errors.New("malformed color literal") + err = ErrorMalformedColorLiteral return } @@ -229,7 +261,7 @@ func parseColor (value string) (valueColor color.Color, err error) { A: 0xFF, } } else { - err = errors.New("malformed color literal") + err = ErrorMalformedColorLiteral return }