mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 20:22:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			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")
							 | 
						||
| 
								 | 
							
								}
							 |