mirror of
				https://github.com/42wim/matterbridge.git
				synced 2025-10-31 05:47:24 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package language
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // Operands is a representation of http://unicode.org/reports/tr35/tr35-numbers.html#Operands
 | |
| type Operands struct {
 | |
| 	N float64 // absolute value of the source number (integer and decimals)
 | |
| 	I int64   // integer digits of n
 | |
| 	V int64   // number of visible fraction digits in n, with trailing zeros
 | |
| 	W int64   // number of visible fraction digits in n, without trailing zeros
 | |
| 	F int64   // visible fractional digits in n, with trailing zeros
 | |
| 	T int64   // visible fractional digits in n, without trailing zeros
 | |
| }
 | |
| 
 | |
| // NequalsAny returns true if o represents an integer equal to any of the arguments.
 | |
| func (o *Operands) NequalsAny(any ...int64) bool {
 | |
| 	for _, i := range any {
 | |
| 		if o.I == i && o.T == 0 {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // NmodEqualsAny returns true if o represents an integer equal to any of the arguments modulo mod.
 | |
| func (o *Operands) NmodEqualsAny(mod int64, any ...int64) bool {
 | |
| 	modI := o.I % mod
 | |
| 	for _, i := range any {
 | |
| 		if modI == i && o.T == 0 {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // NinRange returns true if o represents an integer in the closed interval [from, to].
 | |
| func (o *Operands) NinRange(from, to int64) bool {
 | |
| 	return o.T == 0 && from <= o.I && o.I <= to
 | |
| }
 | |
| 
 | |
| // NmodInRange returns true if o represents an integer in the closed interval [from, to] modulo mod.
 | |
| func (o *Operands) NmodInRange(mod, from, to int64) bool {
 | |
| 	modI := o.I % mod
 | |
| 	return o.T == 0 && from <= modI && modI <= to
 | |
| }
 | |
| 
 | |
| func newOperands(v interface{}) (*Operands, error) {
 | |
| 	switch v := v.(type) {
 | |
| 	case int:
 | |
| 		return newOperandsInt64(int64(v)), nil
 | |
| 	case int8:
 | |
| 		return newOperandsInt64(int64(v)), nil
 | |
| 	case int16:
 | |
| 		return newOperandsInt64(int64(v)), nil
 | |
| 	case int32:
 | |
| 		return newOperandsInt64(int64(v)), nil
 | |
| 	case int64:
 | |
| 		return newOperandsInt64(v), nil
 | |
| 	case string:
 | |
| 		return newOperandsString(v)
 | |
| 	case float32, float64:
 | |
| 		return nil, fmt.Errorf("floats should be formatted into a string")
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("invalid type %T; expected integer or string", v)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func newOperandsInt64(i int64) *Operands {
 | |
| 	if i < 0 {
 | |
| 		i = -i
 | |
| 	}
 | |
| 	return &Operands{float64(i), i, 0, 0, 0, 0}
 | |
| }
 | |
| 
 | |
| func newOperandsString(s string) (*Operands, error) {
 | |
| 	if s[0] == '-' {
 | |
| 		s = s[1:]
 | |
| 	}
 | |
| 	n, err := strconv.ParseFloat(s, 64)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	ops := &Operands{N: n}
 | |
| 	parts := strings.SplitN(s, ".", 2)
 | |
| 	ops.I, err = strconv.ParseInt(parts[0], 10, 64)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if len(parts) == 1 {
 | |
| 		return ops, nil
 | |
| 	}
 | |
| 	fraction := parts[1]
 | |
| 	ops.V = int64(len(fraction))
 | |
| 	for i := ops.V - 1; i >= 0; i-- {
 | |
| 		if fraction[i] != '0' {
 | |
| 			ops.W = i + 1
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	if ops.V > 0 {
 | |
| 		f, err := strconv.ParseInt(fraction, 10, 0)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		ops.F = f
 | |
| 	}
 | |
| 	if ops.W > 0 {
 | |
| 		t, err := strconv.ParseInt(fraction[:ops.W], 10, 0)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		ops.T = t
 | |
| 	}
 | |
| 	return ops, nil
 | |
| }
 | 
