5849898283
Unit tests functional and coverage back to 100% Add more routes to dictionary, add more credentials, add default port 5554, rename cameradar logs ENV variable, improve unit test readability, remove tmp file
114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package yaml
|
|
|
|
import (
|
|
"reflect"
|
|
"unicode"
|
|
)
|
|
|
|
type keyList []reflect.Value
|
|
|
|
func (l keyList) Len() int { return len(l) }
|
|
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
|
func (l keyList) Less(i, j int) bool {
|
|
a := l[i]
|
|
b := l[j]
|
|
ak := a.Kind()
|
|
bk := b.Kind()
|
|
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
|
a = a.Elem()
|
|
ak = a.Kind()
|
|
}
|
|
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
|
b = b.Elem()
|
|
bk = b.Kind()
|
|
}
|
|
af, aok := keyFloat(a)
|
|
bf, bok := keyFloat(b)
|
|
if aok && bok {
|
|
if af != bf {
|
|
return af < bf
|
|
}
|
|
if ak != bk {
|
|
return ak < bk
|
|
}
|
|
return numLess(a, b)
|
|
}
|
|
if ak != reflect.String || bk != reflect.String {
|
|
return ak < bk
|
|
}
|
|
ar, br := []rune(a.String()), []rune(b.String())
|
|
for i := 0; i < len(ar) && i < len(br); i++ {
|
|
if ar[i] == br[i] {
|
|
continue
|
|
}
|
|
al := unicode.IsLetter(ar[i])
|
|
bl := unicode.IsLetter(br[i])
|
|
if al && bl {
|
|
return ar[i] < br[i]
|
|
}
|
|
if al || bl {
|
|
return bl
|
|
}
|
|
var ai, bi int
|
|
var an, bn int64
|
|
if ar[i] == '0' || br[i] == '0' {
|
|
for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
|
|
if ar[j] != '0' {
|
|
an = 1
|
|
bn = 1
|
|
break
|
|
}
|
|
}
|
|
}
|
|
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
|
an = an*10 + int64(ar[ai]-'0')
|
|
}
|
|
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
|
bn = bn*10 + int64(br[bi]-'0')
|
|
}
|
|
if an != bn {
|
|
return an < bn
|
|
}
|
|
if ai != bi {
|
|
return ai < bi
|
|
}
|
|
return ar[i] < br[i]
|
|
}
|
|
return len(ar) < len(br)
|
|
}
|
|
|
|
// keyFloat returns a float value for v if it is a number/bool
|
|
// and whether it is a number/bool or not.
|
|
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
|
switch v.Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return float64(v.Int()), true
|
|
case reflect.Float32, reflect.Float64:
|
|
return v.Float(), true
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return float64(v.Uint()), true
|
|
case reflect.Bool:
|
|
if v.Bool() {
|
|
return 1, true
|
|
}
|
|
return 0, true
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
// numLess returns whether a < b.
|
|
// a and b must necessarily have the same kind.
|
|
func numLess(a, b reflect.Value) bool {
|
|
switch a.Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return a.Int() < b.Int()
|
|
case reflect.Float32, reflect.Float64:
|
|
return a.Float() < b.Float()
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return a.Uint() < b.Uint()
|
|
case reflect.Bool:
|
|
return !a.Bool() && b.Bool()
|
|
}
|
|
panic("not a number")
|
|
}
|