github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/strconv/itoa.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package strconv 6 7 const fastSmalls = true // enable fast path for small integers 8 9 // FormatUint returns the string representation of i in the given base, 10 // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' 11 // for digit values >= 10. 12 func FormatUint(i uint64, base int) string { 13 if fastSmalls && i < nSmalls && base == 10 { 14 return small(int(i)) 15 } 16 _, s := formatBits(nil, i, base, false, false) 17 return s 18 } 19 20 // FormatInt returns the string representation of i in the given base, 21 // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' 22 // for digit values >= 10. 23 func FormatInt(i int64, base int) string { 24 if fastSmalls && 0 <= i && i < nSmalls && base == 10 { 25 return small(int(i)) 26 } 27 _, s := formatBits(nil, uint64(i), base, i < 0, false) 28 return s 29 } 30 31 // Itoa is shorthand for FormatInt(int64(i), 10). 32 func Itoa(i int) string { 33 return FormatInt(int64(i), 10) 34 } 35 36 // AppendInt appends the string form of the integer i, 37 // as generated by FormatInt, to dst and returns the extended buffer. 38 func AppendInt(dst []byte, i int64, base int) []byte { 39 if fastSmalls && 0 <= i && i < nSmalls && base == 10 { 40 return append(dst, small(int(i))...) 41 } 42 dst, _ = formatBits(dst, uint64(i), base, i < 0, true) 43 return dst 44 } 45 46 // AppendUint appends the string form of the unsigned integer i, 47 // as generated by FormatUint, to dst and returns the extended buffer. 48 func AppendUint(dst []byte, i uint64, base int) []byte { 49 if fastSmalls && i < nSmalls && base == 10 { 50 return append(dst, small(int(i))...) 51 } 52 dst, _ = formatBits(dst, i, base, false, true) 53 return dst 54 } 55 56 // small returns the string for an i with 0 <= i < nSmalls. 57 func small(i int) string { 58 off := 0 59 if i < 10 { 60 off = 1 61 } 62 return smallsString[i*2+off : i*2+2] 63 } 64 65 const nSmalls = 100 66 67 const smallsString = "00010203040506070809" + 68 "10111213141516171819" + 69 "20212223242526272829" + 70 "30313233343536373839" + 71 "40414243444546474849" + 72 "50515253545556575859" + 73 "60616263646566676869" + 74 "70717273747576777879" + 75 "80818283848586878889" + 76 "90919293949596979899" 77 78 const host32bit = ^uint(0)>>32 == 0 79 80 const digits = "0123456789abcdefghijklmnopqrstuvwxyz" 81 82 var shifts = [len(digits) + 1]uint{ 83 1 << 1: 1, 84 1 << 2: 2, 85 1 << 3: 3, 86 1 << 4: 4, 87 1 << 5: 5, 88 } 89 90 // formatBits computes the string representation of u in the given base. 91 // If neg is set, u is treated as negative int64 value. If append_ is 92 // set, the string is appended to dst and the resulting byte slice is 93 // returned as the first result value; otherwise the string is returned 94 // as the second result value. 95 // 96 func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { 97 if base < 2 || base > len(digits) { 98 panic("strconv: illegal AppendInt/FormatInt base") 99 } 100 // 2 <= base && base <= len(digits) 101 102 var a [64 + 1]byte // +1 for sign of 64bit value in base 2 103 i := len(a) 104 105 if neg { 106 u = -u 107 } 108 109 // convert bits 110 // We use uint values where we can because those will 111 // fit into a single register even on a 32bit machine. 112 if base == 10 { 113 // common case: use constants for / because 114 // the compiler can optimize it into a multiply+shift 115 116 if host32bit { 117 // convert the lower digits using 32bit operations 118 for u >= 1e9 { 119 // Avoid using r = a%b in addition to q = a/b 120 // since 64bit division and modulo operations 121 // are calculated by runtime functions on 32bit machines. 122 q := u / 1e9 123 us := uint(u - q*1e9) // u % 1e9 fits into a uint 124 for j := 4; j > 0; j-- { 125 is := us % 100 * 2 126 us /= 100 127 i -= 2 128 a[i+1] = smallsString[is+1] 129 a[i+0] = smallsString[is+0] 130 } 131 132 // us < 10, since it contains the last digit 133 // from the initial 9-digit us. 134 i-- 135 a[i] = smallsString[us*2+1] 136 137 u = q 138 } 139 // u < 1e9 140 } 141 142 // u guaranteed to fit into a uint 143 us := uint(u) 144 for us >= 100 { 145 is := us % 100 * 2 146 us /= 100 147 i -= 2 148 a[i+1] = smallsString[is+1] 149 a[i+0] = smallsString[is+0] 150 } 151 152 // us < 100 153 is := us * 2 154 i-- 155 a[i] = smallsString[is+1] 156 if us >= 10 { 157 i-- 158 a[i] = smallsString[is] 159 } 160 161 } else if s := shifts[base]; s > 0 { 162 // base is power of 2: use shifts and masks instead of / and % 163 b := uint64(base) 164 m := uint(base) - 1 // == 1<<s - 1 165 for u >= b { 166 i-- 167 a[i] = digits[uint(u)&m] 168 u >>= s 169 } 170 // u < base 171 i-- 172 a[i] = digits[uint(u)] 173 } else { 174 // general case 175 b := uint64(base) 176 for u >= b { 177 i-- 178 // Avoid using r = a%b in addition to q = a/b 179 // since 64bit division and modulo operations 180 // are calculated by runtime functions on 32bit machines. 181 q := u / b 182 a[i] = digits[uint(u-q*b)] 183 u = q 184 } 185 // u < base 186 i-- 187 a[i] = digits[uint(u)] 188 } 189 190 // add sign, if any 191 if neg { 192 i-- 193 a[i] = '-' 194 } 195 196 if append_ { 197 d = append(dst, a[i:]...) 198 return 199 } 200 s = string(a[i:]) 201 return 202 }