Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 183 additions & 0 deletions conf/conf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
Copyright 2013 Petru Ciobanu, Francesco Paglia, Lorenzo Pierfederici

This file is part of maponet/utils.

maponet/utils is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

maponet/utils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with maponet/utils. If not, see <http://www.gnu.org/licenses/>.
*/

/*
Package conf contains a simple loader for configuration files.
*/
package conf

import (
"bufio"
"fmt"
"io"
"os"
"regexp"
"strconv"
"sync"
"bytes"
)

type NotFoundError struct {
key string
}

func (e *NotFoundError) Error() string { return fmt.Sprintf("Key not found: %s", e.key) }

type ConfigSyntaxError struct {
line string
}

func (e *ConfigSyntaxError) Error() string {
return fmt.Sprintf("Config syntax error on line: %s", e.line)
}

// Regexp patterns
var (
PatternOption, _ = regexp.Compile("(.*)=([^#]*)")
PatternComment, _ = regexp.Compile("^#")
PatternEmpty, _ = regexp.Compile("^[\t\n\f\r ]$")
)

// Config is a simple synchronized object that can be used to parse
// configuration files and store key=value pairs
type Config struct {
values map[string]string
mutex sync.RWMutex
}

func NewConfig() *Config {
var c Config
c.values = make(map[string]string)
return &c
}

// Parse
func (c *Config) Parse(r *bufio.Reader) error {
for {
l, err := r.ReadBytes('\n')
if err == io.EOF {
break
} else if err != nil {
return err
}
switch {
case PatternEmpty.Match(l):
continue
case PatternComment.Match(l):
continue
case PatternOption.Match(l):
m := PatternOption.FindSubmatch(l)
c.Set(string(bytes.TrimSpace(m[1])), string(bytes.TrimSpace(m[2])))
default:
return &ConfigSyntaxError{string(l)}
}
}
return nil
}

// ParseFile
func (c *Config) ParseFile(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()

err = c.Parse(bufio.NewReader(f))
if err != nil {
return err
}
return nil
}

// Set
func (c *Config) Set(key, value string) {
c.mutex.Lock()
defer c.mutex.Unlock()

c.values[key] = value
}

// GetString
func (c *Config) GetString(key string) (string, error) {
c.mutex.RLock()
defer c.mutex.RUnlock()

v, ok := c.values[key]
if !ok {
return v, &NotFoundError{key}
}
return v, nil
}

// GetBool
func (c *Config) GetBool(key string) (bool, error) {
s, err := c.GetString(key)
if err != nil {
return *new(bool), err
}

return strconv.ParseBool(s)
}

// GetInt
func (c *Config) GetInt(key string) (int, error) {
s, err := c.GetString(key)
if err != nil {
return *new(int), err
}

return strconv.Atoi(s)
}

// GetFloat64
func (c *Config) GetFloat64(key string) (float64, error) {
s, err := c.GetString(key)
if err != nil {
return *new(float64), err
}

return strconv.ParseFloat(s, 64)
}

var DefaultConfig = NewConfig()

func ParseFile(path string) error {
return DefaultConfig.ParseFile(path)
}

func Set(key, value string) {
DefaultConfig.Set(key, value)
}

func GetString(key string) (string, error) {
return DefaultConfig.GetString(key)
}

func GetBool(key string) (bool, error) {
return DefaultConfig.GetBool(key)
}

func GetInt(key string) (int, error) {
return DefaultConfig.GetInt(key)
}

func GetFloat64(key string) (float64, error) {
return DefaultConfig.GetFloat64(key)
}
140 changes: 69 additions & 71 deletions log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ Package log contains a simple multi-level logger.
package log

import (
"errors"
"flag"
"fmt"
"io"
"os"
"time"
)
Expand All @@ -37,100 +36,99 @@ const (
DEBUG
)

// ErrLevel indicates that the specified log level is not valid
var ErrLevel = errors.New("Unknown log level")
// BadLevelError indicates that the specified log level is not valid.
type BadLevelError struct {
level interface{}
}

// SetLevel sets the output level for the global logger
func SetLevel(level int) error {
if level > DEBUG {
return ErrLevel
}
l.level = level
return nil
func (e *BadLevelError) Error() string { return fmt.Sprintf("Unknown log level: %v", e.level) }

// Logger is a simple multi-level logger.
type Logger struct {
Level int
Writer io.Writer
}

// SetLevelString sets the output level for the global logger
func SetLevelString(name string) error {
level, err := StringToLevel(name)
if err != nil || level > DEBUG {
return ErrLevel
}
l.level = level
return nil
func NewLogger(level interface{}, writer io.Writer) *Logger {
var l Logger
l.SetLevel(level)
l.Writer = writer
return &l
}

// LevelToString converts a log level to its string representation
func LevelToString(level int) (string, error) {
var s string
// SetLevel sets the output level for the logger.
// 'level' can be either a string or an int.
func (l *Logger) SetLevel(level interface{}) error {
switch level {
case ERROR:
s = "ERROR"
case INFO:
s = "INFO"
case DEBUG:
s = "DEBUG"
case ERROR, "ERROR":
l.Level = ERROR
case INFO, "INFO":
l.Level = INFO
case DEBUG, "DEBUG":
l.Level = DEBUG
default:
return "", ErrLevel
return &BadLevelError{level}
}
return s, nil
return nil
}

// StringToLevel converts a string to the corresponding log level
func StringToLevel(name string) (int, error) {
var level int
switch name {
case "ERROR":
level = ERROR
case "INFO":
level = INFO
case "DEBUG":
level = DEBUG
default:
return -1, ErrLevel
// Log logs a message with custom level and type.
// To log messages at predefined levels you can use the convenience
// functions Fatal(), Error(), Info(), Debug().
func (l *Logger) Log(level int, msgType string, format string, v ...interface{}) {
if level <= l.Level {
msg := fmt.Sprintf(format, v...)
t := time.Now().Format(time.RFC1123)
fmt.Fprintf(l.Writer, "%s [%s]: %s\n", t, msgType, msg)

}
return level, nil
}

func FlagLevel(flagname string) *string {
return flag.String(flagname, "ERROR", "set loglevel [ERROR|INFO|DEBUG]")
// Fatal logs a message at "ERROR" level and terminates the program.
func (l *Logger) Fatal(format string, v ...interface{}) {
l.Log(ERROR, "ERROR", format, v...)
os.Exit(1)
}

type logger struct {
level int
// Error logs a message at "ERROR" level.
func (l *Logger) Error(format string, v ...interface{}) {
l.Log(ERROR, "ERROR", format, v...)
}

var l logger
// Info logs a message at "INFO" level.
func (l *Logger) Info(format string, v ...interface{}) {
l.Log(INFO, "INFO", format, v...)
}

func Log(level int, format string, v ...interface{}) {
if level <= l.level {
msgType, err := LevelToString(level)
if err != nil {
Fatal(err.Error())
}
msg := fmt.Sprintf(format, v...)
t := time.Now().Format(time.RFC1123)
fmt.Printf("%s [%s]: %s\n", t, msgType, msg)
// Debug logs a message at "DEBUG" level.
func (l *Logger) Debug(format string, v ...interface{}) {
l.Log(DEBUG, "DEBUG", format, v...)
}

}
var DefaultLogger = NewLogger(ERROR, os.Stdout)

// SetLevel sets the output level for the default logger.
func SetLevel(level interface{}) error {
return DefaultLogger.SetLevel(level)
}

// Fatal logs a message at "ERROR" level and terminates the program
func Fatal(format string, v ...interface{}) {
Log(ERROR, format, v...)
os.Exit(1)
// Fatal logs a message at "ERROR" level with the default logger and
// terminates the program.
func Fatal(msg string, v ...interface{}) {
DefaultLogger.Fatal(msg, v...)
}

// Error logs a message at "ERROR" level
func Error(format string, v ...interface{}) {
Log(ERROR, format, v...)
// Error logs a message at "ERROR" level with the default logger.
func Error(msg string, v ...interface{}) {
DefaultLogger.Error(msg, v...)
}

// Info logs a message at "INFO" level
func Info(format string, v ...interface{}) {
Log(INFO, format, v...)
// Info logs a message at "INFO" level with the default logger.
func Info(msg string, v ...interface{}) {
DefaultLogger.Info(msg, v...)
}

// Debug logs a message at "DEBUG" level
func Debug(format string, v ...interface{}) {
Log(DEBUG, format, v...)
// Debug logs a message at "DEBUG" level with the default logger.
func Debug(msg string, v ...interface{}) {
DefaultLogger.Debug(msg, v...)
}