mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 16:32:26 -05:00 
			
		
		
		
	Grand test fixup (#138)
* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
This commit is contained in:
		
					parent
					
						
							
								329a5e8144
							
						
					
				
			
			
				commit
				
					
						98263a7de6
					
				
			
		
					 2677 changed files with 1090869 additions and 219 deletions
				
			
		
							
								
								
									
										491
									
								
								vendor/github.com/ugorji/go/codec/decimal.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								vendor/github.com/ugorji/go/codec/decimal.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,491 @@ | |||
| // Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved. | ||||
| // Use of this source code is governed by a MIT license found in the LICENSE file. | ||||
| 
 | ||||
| package codec | ||||
| 
 | ||||
| import ( | ||||
| 	"math" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // Per go spec, floats are represented in memory as | ||||
| // IEEE single or double precision floating point values. | ||||
| // | ||||
| // We also looked at the source for stdlib math/modf.go, | ||||
| // reviewed https://github.com/chewxy/math32 | ||||
| // and read wikipedia documents describing the formats. | ||||
| // | ||||
| // It became clear that we could easily look at the bits to determine | ||||
| // whether any fraction exists. | ||||
| 
 | ||||
| func parseFloat32(b []byte) (f float32, err error) { | ||||
| 	return parseFloat32_custom(b) | ||||
| } | ||||
| 
 | ||||
| func parseFloat64(b []byte) (f float64, err error) { | ||||
| 	return parseFloat64_custom(b) | ||||
| } | ||||
| 
 | ||||
| func parseFloat32_strconv(b []byte) (f float32, err error) { | ||||
| 	f64, err := strconv.ParseFloat(stringView(b), 32) | ||||
| 	f = float32(f64) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func parseFloat64_strconv(b []byte) (f float64, err error) { | ||||
| 	return strconv.ParseFloat(stringView(b), 64) | ||||
| } | ||||
| 
 | ||||
| // ------ parseFloat custom below -------- | ||||
| 
 | ||||
| // JSON really supports decimal numbers in base 10 notation, with exponent support. | ||||
| // | ||||
| // We assume the following: | ||||
| //   - a lot of floating point numbers in json files will have defined precision | ||||
| //     (in terms of number of digits after decimal point), etc. | ||||
| //   - these (referenced above) can be written in exact format. | ||||
| // | ||||
| // strconv.ParseFloat has some unnecessary overhead which we can do without | ||||
| // for the common case: | ||||
| // | ||||
| //    - expensive char-by-char check to see if underscores are in right place | ||||
| //    - testing for and skipping underscores | ||||
| //    - check if the string matches ignorecase +/- inf, +/- infinity, nan | ||||
| //    - support for base 16 (0xFFFF...) | ||||
| // | ||||
| // The functions below will try a fast-path for floats which can be decoded | ||||
| // without any loss of precision, meaning they: | ||||
| // | ||||
| //    - fits within the significand bits of the 32-bits or 64-bits | ||||
| //    - exponent fits within the exponent value | ||||
| //    - there is no truncation (any extra numbers are all trailing zeros) | ||||
| // | ||||
| // To figure out what the values are for maxMantDigits, use this idea below: | ||||
| // | ||||
| // 2^23 =                 838 8608 (between 10^ 6 and 10^ 7) (significand bits of uint32) | ||||
| // 2^32 =             42 9496 7296 (between 10^ 9 and 10^10) (full uint32) | ||||
| // 2^52 =      4503 5996 2737 0496 (between 10^15 and 10^16) (significand bits of uint64) | ||||
| // 2^64 = 1844 6744 0737 0955 1616 (between 10^19 and 10^20) (full uint64) | ||||
| // | ||||
| // Note: we only allow for up to what can comfortably fit into the significand | ||||
| // ignoring the exponent, and we only try to parse iff significand fits. | ||||
| 
 | ||||
| const ( | ||||
| 	fMaxMultiplierForExactPow10_64 = 1e15 | ||||
| 	fMaxMultiplierForExactPow10_32 = 1e7 | ||||
| 
 | ||||
| 	fUint64Cutoff = (1<<64-1)/10 + 1 | ||||
| 	// fUint32Cutoff = (1<<32-1)/10 + 1 | ||||
| 
 | ||||
| 	fBase = 10 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	thousand    = 1000 | ||||
| 	million     = thousand * thousand | ||||
| 	billion     = thousand * million | ||||
| 	trillion    = thousand * billion | ||||
| 	quadrillion = thousand * trillion | ||||
| 	quintillion = thousand * quadrillion | ||||
| ) | ||||
| 
 | ||||
| // Exact powers of 10. | ||||
| var uint64pow10 = [...]uint64{ | ||||
| 	1, 10, 100, | ||||
| 	1 * thousand, 10 * thousand, 100 * thousand, | ||||
| 	1 * million, 10 * million, 100 * million, | ||||
| 	1 * billion, 10 * billion, 100 * billion, | ||||
| 	1 * trillion, 10 * trillion, 100 * trillion, | ||||
| 	1 * quadrillion, 10 * quadrillion, 100 * quadrillion, | ||||
| 	1 * quintillion, 10 * quintillion, | ||||
| } | ||||
| var float64pow10 = [...]float64{ | ||||
| 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, | ||||
| 	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, | ||||
| 	1e20, 1e21, 1e22, | ||||
| } | ||||
| var float32pow10 = [...]float32{ | ||||
| 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, | ||||
| } | ||||
| 
 | ||||
| type floatinfo struct { | ||||
| 	mantbits uint8 | ||||
| 
 | ||||
| 	// expbits uint8 // (unused) | ||||
| 	// bias    int16 // (unused) | ||||
| 	// is32bit bool // (unused) | ||||
| 
 | ||||
| 	exactPow10 int8 // Exact powers of ten are <= 10^N (32: 10, 64: 22) | ||||
| 
 | ||||
| 	exactInts int8 // Exact integers are <= 10^N (for non-float, set to 0) | ||||
| 
 | ||||
| 	// maxMantDigits int8 // 10^19 fits in uint64, while 10^9 fits in uint32 | ||||
| 
 | ||||
| 	mantCutoffIsUint64Cutoff bool | ||||
| 
 | ||||
| 	mantCutoff uint64 | ||||
| } | ||||
| 
 | ||||
| var fi32 = floatinfo{23, 10, 7, false, 1<<23 - 1} | ||||
| var fi64 = floatinfo{52, 22, 15, false, 1<<52 - 1} | ||||
| 
 | ||||
| var fi64u = floatinfo{0, 19, 0, true, fUint64Cutoff} | ||||
| 
 | ||||
| func noFrac64(fbits uint64) bool { | ||||
| 	exp := uint64(fbits>>52)&0x7FF - 1023 // uint(x>>shift)&mask - bias | ||||
| 	// clear top 12+e bits, the integer part; if the rest is 0, then no fraction. | ||||
| 	return exp < 52 && fbits<<(12+exp) == 0 // means there's no fractional part | ||||
| } | ||||
| 
 | ||||
| func noFrac32(fbits uint32) bool { | ||||
| 	exp := uint32(fbits>>23)&0xFF - 127 // uint(x>>shift)&mask - bias | ||||
| 	// clear top 9+e bits, the integer part; if the rest is 0, then no fraction. | ||||
| 	return exp < 23 && fbits<<(9+exp) == 0 // means there's no fractional part | ||||
| } | ||||
| 
 | ||||
| func strconvParseErr(b []byte, fn string) error { | ||||
| 	return &strconv.NumError{ | ||||
| 		Func: fn, | ||||
| 		Err:  strconv.ErrSyntax, | ||||
| 		Num:  string(b), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func parseFloat32_reader(r readFloatResult) (f float32, fail bool) { | ||||
| 	f = float32(r.mantissa) | ||||
| 	if r.exp == 0 { | ||||
| 	} else if r.exp < 0 { // int / 10^k | ||||
| 		f /= float32pow10[uint8(-r.exp)] | ||||
| 	} else { // exp > 0 | ||||
| 		if r.exp > fi32.exactPow10 { | ||||
| 			f *= float32pow10[r.exp-fi32.exactPow10] | ||||
| 			if f > fMaxMultiplierForExactPow10_32 { // exponent too large - outside range | ||||
| 				fail = true | ||||
| 				return // ok = false | ||||
| 			} | ||||
| 			f *= float32pow10[fi32.exactPow10] | ||||
| 		} else { | ||||
| 			f *= float32pow10[uint8(r.exp)] | ||||
| 		} | ||||
| 	} | ||||
| 	if r.neg { | ||||
| 		f = -f | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func parseFloat32_custom(b []byte) (f float32, err error) { | ||||
| 	r := readFloat(b, fi32) | ||||
| 	if r.bad { | ||||
| 		return 0, strconvParseErr(b, "ParseFloat") | ||||
| 	} | ||||
| 	if r.ok { | ||||
| 		f, r.bad = parseFloat32_reader(r) | ||||
| 		if !r.bad { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	return parseFloat32_strconv(b) | ||||
| } | ||||
| 
 | ||||
| func parseFloat64_reader(r readFloatResult) (f float64, fail bool) { | ||||
| 	f = float64(r.mantissa) | ||||
| 	if r.exp == 0 { | ||||
| 	} else if r.exp < 0 { // int / 10^k | ||||
| 		f /= float64pow10[-uint8(r.exp)] | ||||
| 	} else { // exp > 0 | ||||
| 		if r.exp > fi64.exactPow10 { | ||||
| 			f *= float64pow10[r.exp-fi64.exactPow10] | ||||
| 			if f > fMaxMultiplierForExactPow10_64 { // exponent too large - outside range | ||||
| 				fail = true | ||||
| 				return | ||||
| 			} | ||||
| 			f *= float64pow10[fi64.exactPow10] | ||||
| 		} else { | ||||
| 			f *= float64pow10[uint8(r.exp)] | ||||
| 		} | ||||
| 	} | ||||
| 	if r.neg { | ||||
| 		f = -f | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func parseFloat64_custom(b []byte) (f float64, err error) { | ||||
| 	r := readFloat(b, fi64) | ||||
| 	if r.bad { | ||||
| 		return 0, strconvParseErr(b, "ParseFloat") | ||||
| 	} | ||||
| 	if r.ok { | ||||
| 		f, r.bad = parseFloat64_reader(r) | ||||
| 		if !r.bad { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	return parseFloat64_strconv(b) | ||||
| } | ||||
| 
 | ||||
| func parseUint64_simple(b []byte) (n uint64, ok bool) { | ||||
| 	var i int | ||||
| 	var n1 uint64 | ||||
| 	var c uint8 | ||||
| LOOP: | ||||
| 	if i < len(b) { | ||||
| 		c = b[i] | ||||
| 		// unsigned integers don't overflow well on multiplication, so check cutoff here | ||||
| 		// e.g. (maxUint64-5)*10 doesn't overflow well ... | ||||
| 		// if n >= fUint64Cutoff || !isDigitChar(b[i]) { // if c < '0' || c > '9' { | ||||
| 		if n >= fUint64Cutoff || c < '0' || c > '9' { | ||||
| 			return | ||||
| 		} else if c == '0' { | ||||
| 			n *= fBase | ||||
| 		} else { | ||||
| 			n1 = n | ||||
| 			n = n*fBase + uint64(c-'0') | ||||
| 			if n < n1 { | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		i++ | ||||
| 		goto LOOP | ||||
| 	} | ||||
| 	ok = true | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func parseUint64_reader(r readFloatResult) (f uint64, fail bool) { | ||||
| 	f = r.mantissa | ||||
| 	if r.exp == 0 { | ||||
| 	} else if r.exp < 0 { // int / 10^k | ||||
| 		if f%uint64pow10[uint8(-r.exp)] != 0 { | ||||
| 			fail = true | ||||
| 		} else { | ||||
| 			f /= uint64pow10[uint8(-r.exp)] | ||||
| 		} | ||||
| 	} else { // exp > 0 | ||||
| 		f *= uint64pow10[uint8(r.exp)] | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func parseInteger_bytes(b []byte) (u uint64, neg, ok bool) { | ||||
| 	if len(b) == 0 { | ||||
| 		ok = true | ||||
| 		return | ||||
| 	} | ||||
| 	if b[0] == '-' { | ||||
| 		if len(b) == 1 { | ||||
| 			return | ||||
| 		} | ||||
| 		neg = true | ||||
| 		b = b[1:] | ||||
| 	} | ||||
| 
 | ||||
| 	u, ok = parseUint64_simple(b) | ||||
| 	if ok { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	r := readFloat(b, fi64u) | ||||
| 	if r.ok { | ||||
| 		var fail bool | ||||
| 		u, fail = parseUint64_reader(r) | ||||
| 		if fail { | ||||
| 			f, err := parseFloat64(b) | ||||
| 			if err != nil { | ||||
| 				return | ||||
| 			} | ||||
| 			if !noFrac64(math.Float64bits(f)) { | ||||
| 				return | ||||
| 			} | ||||
| 			u = uint64(f) | ||||
| 		} | ||||
| 		ok = true | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // parseNumber will return an integer if only composed of [-]?[0-9]+ | ||||
| // Else it will return a float. | ||||
| func parseNumber(b []byte, z *fauxUnion, preferSignedInt bool) (err error) { | ||||
| 	var ok, neg bool | ||||
| 	var f uint64 | ||||
| 
 | ||||
| 	if len(b) == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if b[0] == '-' { | ||||
| 		neg = true | ||||
| 		f, ok = parseUint64_simple(b[1:]) | ||||
| 	} else { | ||||
| 		f, ok = parseUint64_simple(b) | ||||
| 	} | ||||
| 
 | ||||
| 	if ok { | ||||
| 		if neg { | ||||
| 			z.v = valueTypeInt | ||||
| 			if chkOvf.Uint2Int(f, neg) { | ||||
| 				return strconvParseErr(b, "ParseInt") | ||||
| 			} | ||||
| 			z.i = -int64(f) | ||||
| 		} else if preferSignedInt { | ||||
| 			z.v = valueTypeInt | ||||
| 			if chkOvf.Uint2Int(f, neg) { | ||||
| 				return strconvParseErr(b, "ParseInt") | ||||
| 			} | ||||
| 			z.i = int64(f) | ||||
| 		} else { | ||||
| 			z.v = valueTypeUint | ||||
| 			z.u = f | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	z.v = valueTypeFloat | ||||
| 	z.f, err = parseFloat64_custom(b) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| type readFloatResult struct { | ||||
| 	mantissa uint64 | ||||
| 	exp      int8 | ||||
| 	neg      bool | ||||
| 	trunc    bool | ||||
| 	bad      bool // bad decimal string | ||||
| 	hardexp  bool // exponent is hard to handle (> 2 digits, etc) | ||||
| 	ok       bool | ||||
| 	// sawdot   bool | ||||
| 	// sawexp   bool | ||||
| 	//_ [2]bool // padding | ||||
| } | ||||
| 
 | ||||
| func readFloat(s []byte, y floatinfo) (r readFloatResult) { | ||||
| 	var i uint // uint, so that we eliminate bounds checking | ||||
| 	var slen = uint(len(s)) | ||||
| 	if slen == 0 { | ||||
| 		// read an empty string as the zero value | ||||
| 		// r.bad = true | ||||
| 		r.ok = true | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if s[0] == '-' { | ||||
| 		r.neg = true | ||||
| 		i++ | ||||
| 	} | ||||
| 
 | ||||
| 	// we considered punting early if string has length > maxMantDigits, but this doesn't account | ||||
| 	// for trailing 0's e.g. 700000000000000000000 can be encoded exactly as it is 7e20 | ||||
| 
 | ||||
| 	var nd, ndMant, dp int8 | ||||
| 	var sawdot, sawexp bool | ||||
| 	var xu uint64 | ||||
| 
 | ||||
| LOOP: | ||||
| 	for ; i < slen; i++ { | ||||
| 		switch s[i] { | ||||
| 		case '.': | ||||
| 			if sawdot { | ||||
| 				r.bad = true | ||||
| 				return | ||||
| 			} | ||||
| 			sawdot = true | ||||
| 			dp = nd | ||||
| 		case 'e', 'E': | ||||
| 			sawexp = true | ||||
| 			break LOOP | ||||
| 		case '0': | ||||
| 			if nd == 0 { | ||||
| 				dp-- | ||||
| 				continue LOOP | ||||
| 			} | ||||
| 			nd++ | ||||
| 			if r.mantissa < y.mantCutoff { | ||||
| 				r.mantissa *= fBase | ||||
| 				ndMant++ | ||||
| 			} | ||||
| 		case '1', '2', '3', '4', '5', '6', '7', '8', '9': | ||||
| 			nd++ | ||||
| 			if y.mantCutoffIsUint64Cutoff && r.mantissa < fUint64Cutoff { | ||||
| 				r.mantissa *= fBase | ||||
| 				xu = r.mantissa + uint64(s[i]-'0') | ||||
| 				if xu < r.mantissa { | ||||
| 					r.trunc = true | ||||
| 					return | ||||
| 				} | ||||
| 				r.mantissa = xu | ||||
| 			} else if r.mantissa < y.mantCutoff { | ||||
| 				// mantissa = (mantissa << 1) + (mantissa << 3) + uint64(c-'0') | ||||
| 				r.mantissa = r.mantissa*fBase + uint64(s[i]-'0') | ||||
| 			} else { | ||||
| 				r.trunc = true | ||||
| 				return | ||||
| 			} | ||||
| 			ndMant++ | ||||
| 		default: | ||||
| 			r.bad = true | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if !sawdot { | ||||
| 		dp = nd | ||||
| 	} | ||||
| 
 | ||||
| 	if sawexp { | ||||
| 		i++ | ||||
| 		if i < slen { | ||||
| 			var eneg bool | ||||
| 			if s[i] == '+' { | ||||
| 				i++ | ||||
| 			} else if s[i] == '-' { | ||||
| 				i++ | ||||
| 				eneg = true | ||||
| 			} | ||||
| 			if i < slen { | ||||
| 				// for exact match, exponent is 1 or 2 digits (float64: -22 to 37, float32: -1 to 17). | ||||
| 				// exit quick if exponent is more than 2 digits. | ||||
| 				if i+2 < slen { | ||||
| 					r.hardexp = true | ||||
| 					return | ||||
| 				} | ||||
| 				var e int8 | ||||
| 				if s[i] < '0' || s[i] > '9' { // !isDigitChar(s[i]) { // | ||||
| 					r.bad = true | ||||
| 					return | ||||
| 				} | ||||
| 				e = int8(s[i] - '0') | ||||
| 				i++ | ||||
| 				if i < slen { | ||||
| 					if s[i] < '0' || s[i] > '9' { // !isDigitChar(s[i]) { // | ||||
| 						r.bad = true | ||||
| 						return | ||||
| 					} | ||||
| 					e = e*fBase + int8(s[i]-'0') // (e << 1) + (e << 3) + int8(s[i]-'0') | ||||
| 					i++ | ||||
| 				} | ||||
| 				if eneg { | ||||
| 					dp -= e | ||||
| 				} else { | ||||
| 					dp += e | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if r.mantissa != 0 { | ||||
| 		r.exp = dp - ndMant | ||||
| 		// do not set ok=true for cases we cannot handle | ||||
| 		if r.exp < -y.exactPow10 || | ||||
| 			r.exp > y.exactInts+y.exactPow10 || | ||||
| 			(y.mantbits != 0 && r.mantissa>>y.mantbits != 0) { | ||||
| 			r.hardexp = true | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	r.ok = true | ||||
| 	return | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue