159 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package sprig
 | |
| 
 | |
| import (
 | |
| 	"math"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| )
 | |
| 
 | |
| // toFloat64 converts 64-bit floats
 | |
| func toFloat64(v interface{}) float64 {
 | |
| 	if str, ok := v.(string); ok {
 | |
| 		iv, err := strconv.ParseFloat(str, 64)
 | |
| 		if err != nil {
 | |
| 			return 0
 | |
| 		}
 | |
| 		return iv
 | |
| 	}
 | |
| 
 | |
| 	val := reflect.Indirect(reflect.ValueOf(v))
 | |
| 	switch val.Kind() {
 | |
| 	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
 | |
| 		return float64(val.Int())
 | |
| 	case reflect.Uint8, reflect.Uint16, reflect.Uint32:
 | |
| 		return float64(val.Uint())
 | |
| 	case reflect.Uint, reflect.Uint64:
 | |
| 		return float64(val.Uint())
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return val.Float()
 | |
| 	case reflect.Bool:
 | |
| 		if val.Bool() == true {
 | |
| 			return 1
 | |
| 		}
 | |
| 		return 0
 | |
| 	default:
 | |
| 		return 0
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func toInt(v interface{}) int {
 | |
| 	//It's not optimal. Bud I don't want duplicate toInt64 code.
 | |
| 	return int(toInt64(v))
 | |
| }
 | |
| 
 | |
| // toInt64 converts integer types to 64-bit integers
 | |
| func toInt64(v interface{}) int64 {
 | |
| 	if str, ok := v.(string); ok {
 | |
| 		iv, err := strconv.ParseInt(str, 10, 64)
 | |
| 		if err != nil {
 | |
| 			return 0
 | |
| 		}
 | |
| 		return iv
 | |
| 	}
 | |
| 
 | |
| 	val := reflect.Indirect(reflect.ValueOf(v))
 | |
| 	switch val.Kind() {
 | |
| 	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
 | |
| 		return val.Int()
 | |
| 	case reflect.Uint8, reflect.Uint16, reflect.Uint32:
 | |
| 		return int64(val.Uint())
 | |
| 	case reflect.Uint, reflect.Uint64:
 | |
| 		tv := val.Uint()
 | |
| 		if tv <= math.MaxInt64 {
 | |
| 			return int64(tv)
 | |
| 		}
 | |
| 		// TODO: What is the sensible thing to do here?
 | |
| 		return math.MaxInt64
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return int64(val.Float())
 | |
| 	case reflect.Bool:
 | |
| 		if val.Bool() == true {
 | |
| 			return 1
 | |
| 		}
 | |
| 		return 0
 | |
| 	default:
 | |
| 		return 0
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func max(a interface{}, i ...interface{}) int64 {
 | |
| 	aa := toInt64(a)
 | |
| 	for _, b := range i {
 | |
| 		bb := toInt64(b)
 | |
| 		if bb > aa {
 | |
| 			aa = bb
 | |
| 		}
 | |
| 	}
 | |
| 	return aa
 | |
| }
 | |
| 
 | |
| func min(a interface{}, i ...interface{}) int64 {
 | |
| 	aa := toInt64(a)
 | |
| 	for _, b := range i {
 | |
| 		bb := toInt64(b)
 | |
| 		if bb < aa {
 | |
| 			aa = bb
 | |
| 		}
 | |
| 	}
 | |
| 	return aa
 | |
| }
 | |
| 
 | |
| func until(count int) []int {
 | |
| 	step := 1
 | |
| 	if count < 0 {
 | |
| 		step = -1
 | |
| 	}
 | |
| 	return untilStep(0, count, step)
 | |
| }
 | |
| 
 | |
| func untilStep(start, stop, step int) []int {
 | |
| 	v := []int{}
 | |
| 
 | |
| 	if stop < start {
 | |
| 		if step >= 0 {
 | |
| 			return v
 | |
| 		}
 | |
| 		for i := start; i > stop; i += step {
 | |
| 			v = append(v, i)
 | |
| 		}
 | |
| 		return v
 | |
| 	}
 | |
| 
 | |
| 	if step <= 0 {
 | |
| 		return v
 | |
| 	}
 | |
| 	for i := start; i < stop; i += step {
 | |
| 		v = append(v, i)
 | |
| 	}
 | |
| 	return v
 | |
| }
 | |
| 
 | |
| func floor(a interface{}) float64 {
 | |
| 	aa := toFloat64(a)
 | |
| 	return math.Floor(aa)
 | |
| }
 | |
| 
 | |
| func ceil(a interface{}) float64 {
 | |
| 	aa := toFloat64(a)
 | |
| 	return math.Ceil(aa)
 | |
| }
 | |
| 
 | |
| func round(a interface{}, p int, r_opt ...float64) float64 {
 | |
| 	roundOn := .5
 | |
| 	if len(r_opt) > 0 {
 | |
| 		roundOn = r_opt[0]
 | |
| 	}
 | |
| 	val := toFloat64(a)
 | |
| 	places := toFloat64(p)
 | |
| 
 | |
| 	var round float64
 | |
| 	pow := math.Pow(10, places)
 | |
| 	digit := pow * val
 | |
| 	_, div := math.Modf(digit)
 | |
| 	if div >= roundOn {
 | |
| 		round = math.Ceil(digit)
 | |
| 	} else {
 | |
| 		round = math.Floor(digit)
 | |
| 	}
 | |
| 	return round / pow
 | |
| } |