mirror of
https://github.com/adnanh/webhook.git
synced 2025-07-04 18:28:31 +00:00
For 3rd parties building binary packages, and for build consistency in general, it is very helpful to have the same set of dependencies at any time the product is built. See [tools/godep](https://github.com/tools/godep) for further details.
104 lines
2.4 KiB
Go
104 lines
2.4 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
|
|
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")
|
|
}
|