mirror of
https://github.com/ClusterCockpit/cc-units.git
synced 2024-11-10 02:07:25 +01:00
124 lines
3.0 KiB
Go
124 lines
3.0 KiB
Go
package ccunits
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type unit struct {
|
|
prefix Prefix
|
|
measure Measure
|
|
divMeasure Measure
|
|
}
|
|
|
|
type Unit interface {
|
|
Valid() bool
|
|
String() string
|
|
Short() string
|
|
AddDivisorUnit(div Measure)
|
|
getPrefix() Prefix
|
|
getMeasure() Measure
|
|
getDivMeasure() Measure
|
|
}
|
|
|
|
func (u *unit) Valid() bool {
|
|
return u.measure != None
|
|
}
|
|
|
|
func (u *unit) String() string {
|
|
if u.divMeasure != None {
|
|
return fmt.Sprintf("%s%s/%s", u.prefix.String(), u.measure.String(), u.divMeasure.String())
|
|
} else {
|
|
return fmt.Sprintf("%s%s", u.prefix.String(), u.measure.String())
|
|
}
|
|
}
|
|
|
|
func (u *unit) Short() string {
|
|
if u.divMeasure != None {
|
|
return fmt.Sprintf("%s%s/%s", u.prefix.Prefix(), u.measure.Short(), u.divMeasure.Short())
|
|
} else {
|
|
return fmt.Sprintf("%s%s", u.prefix.Prefix(), u.measure.Short())
|
|
}
|
|
}
|
|
|
|
func (u *unit) AddDivisorUnit(div Measure) {
|
|
u.divMeasure = div
|
|
}
|
|
|
|
func (u *unit) getPrefix() Prefix {
|
|
return u.prefix
|
|
}
|
|
|
|
func (u *unit) getMeasure() Measure {
|
|
return u.measure
|
|
}
|
|
|
|
func (u *unit) getDivMeasure() Measure {
|
|
return u.divMeasure
|
|
}
|
|
|
|
func GetPrefixFactor(in Prefix, out Prefix) func(value float64) float64 {
|
|
var factor = 1.0
|
|
var in_prefix = float64(in)
|
|
var out_prefix = float64(out)
|
|
factor = in_prefix / out_prefix
|
|
return func(value float64) float64 { return factor }
|
|
}
|
|
|
|
func GetUnitPrefixFactor(in Unit, out Unit) (func(value float64) float64, error) {
|
|
if in.getMeasure() == TemperatureC && out.getMeasure() == TemperatureF {
|
|
return func(value float64) float64 { return (value * 1.8) + 32 }, nil
|
|
} else if in.getMeasure() == TemperatureF && out.getMeasure() == TemperatureC {
|
|
return func(value float64) float64 { return (value - 32) / 1.8 }, nil
|
|
} else if in.getMeasure() != out.getMeasure() || in.getDivMeasure() != out.getDivMeasure() {
|
|
return func(value float64) float64 { return 1.0 }, fmt.Errorf("invalid measures in in and out Unit")
|
|
}
|
|
return GetPrefixFactor(in.getPrefix(), out.getPrefix()), nil
|
|
}
|
|
|
|
func NewUnit(unitStr string) Unit {
|
|
u := &unit{
|
|
prefix: Base,
|
|
measure: None,
|
|
divMeasure: None,
|
|
}
|
|
matches := prefixRegex.FindStringSubmatch(unitStr)
|
|
if len(matches) > 2 {
|
|
pre := NewPrefix(matches[1])
|
|
measures := strings.Split(matches[2], "/")
|
|
m := NewMeasure(measures[0])
|
|
// Special case for prefix 'p' or 'P' (Peta) and measures starting with 'p' or 'P'
|
|
// like 'packets' or 'percent'. Same for 'e' or 'E' (Exa) for measures starting with
|
|
// 'e' or 'E' like 'events'
|
|
if m == None {
|
|
switch pre {
|
|
case Peta, Exa:
|
|
t := NewMeasure(matches[1] + measures[0])
|
|
if t != None {
|
|
m = t
|
|
pre = Base
|
|
}
|
|
}
|
|
}
|
|
div := None
|
|
if len(measures) > 1 {
|
|
div = NewMeasure(measures[1])
|
|
}
|
|
|
|
switch m {
|
|
// Special case for 'm' as prefix for Bytes and some others as thers is no unit like MilliBytes
|
|
case Bytes, Flops, Packets, Events, Cycles, Requests:
|
|
if pre == Milli {
|
|
pre = Mega
|
|
}
|
|
// Special case for percentage. No/ignore prefix
|
|
case Percentage:
|
|
pre = Base
|
|
}
|
|
u.prefix = pre
|
|
u.measure = m
|
|
u.divMeasure = div
|
|
}
|
|
return u
|
|
}
|