forked from tordarus/format
color support
This commit is contained in:
94
mutator.go
94
mutator.go
@ -1,5 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type NumMutator struct {
|
||||
Op NumOperator
|
||||
Var bool
|
||||
@ -29,3 +34,92 @@ func NewNumOperatorFromString(str string) NumOperator {
|
||||
panic("invalid number operator: " + str)
|
||||
}
|
||||
}
|
||||
|
||||
var numMutatorCache = map[string]interface{}{}
|
||||
|
||||
func numMut2func[T int64 | float64](mutation string) (f func(value T, vars []string) T) {
|
||||
if mutation == "" {
|
||||
return func(value T, vars []string) T { return value }
|
||||
}
|
||||
|
||||
// caching
|
||||
if v, ok := numMutatorCache[mutation]; ok {
|
||||
return v.(func(value T, vars []string) T)
|
||||
}
|
||||
defer func() { numMutatorCache[mutation] = f }()
|
||||
|
||||
matches := numMutationPattern.FindAllStringSubmatch(mutation, -1)
|
||||
mutators := make([]NumMutator, 0, len(matches))
|
||||
var err error
|
||||
for _, match := range matches {
|
||||
mut := NumMutator{Op: NewNumOperatorFromString(match[1])}
|
||||
if match[3] == "" {
|
||||
mut.Value, err = strconv.Atoi(match[2])
|
||||
mut.Var = false
|
||||
if err != nil {
|
||||
panic("invalid number in number mutator: " + match[2])
|
||||
}
|
||||
} else {
|
||||
mut.Var = true
|
||||
mut.Value, err = strconv.Atoi(match[3])
|
||||
if err != nil {
|
||||
panic("invalid back reference group in number mutator: " + match[2])
|
||||
}
|
||||
}
|
||||
mutators = append(mutators, mut)
|
||||
}
|
||||
|
||||
numberParser := number_parser[T]()
|
||||
|
||||
return func(value T, vars []string) T {
|
||||
for _, mutator := range mutators {
|
||||
var otherValue T
|
||||
if mutator.Var {
|
||||
other := numberParser(vars[mutator.Value])
|
||||
otherValue = T(other)
|
||||
} else {
|
||||
otherValue = T(mutator.Value)
|
||||
}
|
||||
|
||||
switch mutator.Op {
|
||||
case NumOperatorAdd:
|
||||
value += otherValue
|
||||
case NumOperatorSub:
|
||||
value -= otherValue
|
||||
case NumOperatorMul:
|
||||
value *= otherValue
|
||||
case NumOperatorDiv:
|
||||
value /= otherValue
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func number_parser[T int64 | float64]() func(str string) T {
|
||||
typeOfT := reflect.TypeOf(new(T)).Elem()
|
||||
typeOfInt64 := reflect.TypeOf(new(int64)).Elem()
|
||||
typeOfFloat64 := reflect.TypeOf(new(float64)).Elem()
|
||||
|
||||
if typeOfT == typeOfInt64 {
|
||||
return func(str string) T {
|
||||
num, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
panic("expected integer but found " + str)
|
||||
}
|
||||
return T(num)
|
||||
}
|
||||
} else if typeOfT == typeOfFloat64 {
|
||||
return func(str string) T {
|
||||
num, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
panic("expected float but found " + str)
|
||||
}
|
||||
return T(num)
|
||||
}
|
||||
}
|
||||
|
||||
panic("invalid number type")
|
||||
}
|
||||
|
Reference in New Issue
Block a user