github.com/iEvan-lhr/exciting-tool@v0.0.0-20230504054234-8e983f73cdd2/charset.go (about)

     1  package tools
     2  
     3  import (
     4  	"math/bits"
     5  )
     6  
     7  const nSmalls = 100
     8  
     9  const smallsString = "00010203040506070809" +
    10  	"10111213141516171819" +
    11  	"20212223242526272829" +
    12  	"30313233343536373839" +
    13  	"40414243444546474849" +
    14  	"50515253545556575859" +
    15  	"60616263646566676869" +
    16  	"70717273747576777879" +
    17  	"80818283848586878889" +
    18  	"90919293949596979899"
    19  
    20  const host32bit = ^uint(0)>>32 == 0
    21  
    22  const fastSmalls = true // enable fast path for small integers
    23  
    24  const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
    25  
    26  // Float 此结构体用来进行自定义的Str拼接类型转换
    27  type Float struct {
    28  	Number any
    29  	Fmt    byte
    30  	Pre    int
    31  }
    32  
    33  // formatInt returns the string representation of i in the given base,
    34  // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
    35  // for digit values >= 10.
    36  func formatInt(i int64, base int, byt *[]byte) int {
    37  	if fastSmalls && 0 <= i && i < nSmalls && base == 10 {
    38  		if i < 10 {
    39  			*byt = append(*byt, digits[i : i+1][0])
    40  			return 1
    41  		} else {
    42  			*byt = append(*byt, []byte(smallsString[i*2:i*2+2])...)
    43  			return 2
    44  		}
    45  
    46  	}
    47  	return formatBits(byt, uint64(i), base, i < 0)
    48  }
    49  
    50  // appendInt is quick append int to String
    51  func appendInt(i int, byt *[]byte) int {
    52  	return formatInt(int64(i), 10, byt)
    53  }
    54  
    55  func formatBits(dst *[]byte, u uint64, base int, neg bool) int {
    56  	if base < 2 || base > len(digits) {
    57  		panic("strconv: illegal AppendInt/FormatInt base")
    58  	}
    59  	// 2 <= base && base <= len(digits)
    60  
    61  	var a [64 + 1]byte // +1 for sign of 64bit value in base 2
    62  	i := len(a)
    63  
    64  	if neg {
    65  		u = -u
    66  	}
    67  
    68  	// convert bits
    69  	// We use uint values where we can because those will
    70  	// fit into a single register even on a 32bit machine.
    71  	if base == 10 {
    72  		// common case: use constants for / because
    73  		// the compiler can optimize it into a multiply+shift
    74  
    75  		if host32bit {
    76  			// convert the lower digits using 32bit operations
    77  			for u >= 1e9 {
    78  				// Avoid using r = a%b in addition to q = a/b
    79  				// since 64bit division and modulo operations
    80  				// are calculated by runtime functions on 32bit machines.
    81  				q := u / 1e9
    82  				us := uint(u - q*1e9) // u % 1e9 fits into a uint
    83  				for j := 4; j > 0; j-- {
    84  					is := us % 100 * 2
    85  					us /= 100
    86  					i -= 2
    87  					a[i+1] = smallsString[is+1]
    88  					a[i+0] = smallsString[is+0]
    89  				}
    90  
    91  				// us < 10, since it contains the last digit
    92  				// from the initial 9-digit us.
    93  				i--
    94  				a[i] = smallsString[us*2+1]
    95  
    96  				u = q
    97  			}
    98  			// u < 1e9
    99  		}
   100  
   101  		// u guaranteed to fit into a uint
   102  		us := uint(u)
   103  		for us >= 100 {
   104  			is := us % 100 * 2
   105  			us /= 100
   106  			i -= 2
   107  			a[i+1] = smallsString[is+1]
   108  			a[i+0] = smallsString[is+0]
   109  		}
   110  
   111  		// us < 100
   112  		is := us * 2
   113  		i--
   114  		a[i] = smallsString[is+1]
   115  		if us >= 10 {
   116  			i--
   117  			a[i] = smallsString[is]
   118  		}
   119  
   120  	} else if isPowerOfTwo(base) {
   121  		// Use shifts and masks instead of / and %.
   122  		// Base is a power of 2 and 2 <= base <= len(digits) where len(digits) is 36.
   123  		// The largest power of 2 below or equal to 36 is 32, which is 1 << 5;
   124  		// i.e., the largest possible shift count is 5. By &-ind that value with
   125  		// the constant 7 we tell the compiler that the shift count is always
   126  		// less than 8 which is smaller than any register width. This allows
   127  		// the compiler to generate better code for the shift operation.
   128  		shift := uint(bits.TrailingZeros(uint(base))) & 7
   129  		b := uint64(base)
   130  		m := uint(base) - 1 // == 1<<shift - 1
   131  		for u >= b {
   132  			i--
   133  			a[i] = digits[uint(u)&m]
   134  			u >>= shift
   135  		}
   136  		// u < base
   137  		i--
   138  		a[i] = digits[uint(u)]
   139  	} else {
   140  		// general case
   141  		b := uint64(base)
   142  		for u >= b {
   143  			i--
   144  			// Avoid using r = a%b in addition to q = a/b
   145  			// since 64bit division and modulo operations
   146  			// are calculated by runtime functions on 32bit machines.
   147  			q := u / b
   148  			a[i] = digits[uint(u-q*b)]
   149  			u = q
   150  		}
   151  		// u < base
   152  		i--
   153  		a[i] = digits[uint(u)]
   154  	}
   155  
   156  	// add sign, if any
   157  	if neg {
   158  		i--
   159  		a[i] = '-'
   160  	}
   161  	*dst = append(*dst, a[i:]...)
   162  	return len(a[i:])
   163  }
   164  
   165  func isPowerOfTwo(x int) bool {
   166  	return x&(x-1) == 0
   167  }
   168  
   169  // AppendUint appends the string form of the unsigned integer i,
   170  // as generated by FormatUint, to dst and returns the extended buffer.
   171  func appendUint64(i uint64, byt *[]byte) int {
   172  	return formatBits(byt, i, 10, i < 0)
   173  }