Source file src/pkg/strconv/itoa.go
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 // FormatUint returns the string representation of i in the given base. 8 func FormatUint(i uint64, base int) string { 9 _, s := formatBits(nil, i, base, false, false) 10 return s 11 } 12 13 // FormatInt returns the string representation of i in the given base. 14 func FormatInt(i int64, base int) string { 15 _, s := formatBits(nil, uint64(i), base, i < 0, false) 16 return s 17 } 18 19 // Itoa is shorthand for FormatInt(i, 10). 20 func Itoa(i int) string { 21 return FormatInt(int64(i), 10) 22 } 23 24 // AppendInt appends the string form of the integer i, 25 // as generated by FormatInt, to dst and returns the extended buffer. 26 func AppendInt(dst []byte, i int64, base int) []byte { 27 dst, _ = formatBits(dst, uint64(i), base, i < 0, true) 28 return dst 29 } 30 31 // AppendUint appends the string form of the unsigned integer i, 32 // as generated by FormatUint, to dst and returns the extended buffer. 33 func AppendUint(dst []byte, i uint64, base int) []byte { 34 dst, _ = formatBits(dst, i, base, false, true) 35 return dst 36 } 37 38 const ( 39 digits = "0123456789abcdefghijklmnopqrstuvwxyz" 40 digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" 41 digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" 42 ) 43 44 var shifts = [len(digits) + 1]uint{ 45 1 << 1: 1, 46 1 << 2: 2, 47 1 << 3: 3, 48 1 << 4: 4, 49 1 << 5: 5, 50 } 51 52 // formatBits computes the string representation of u in the given base. 53 // If neg is set, u is treated as negative int64 value. If append_ is 54 // set, the string is appended to dst and the resulting byte slice is 55 // returned as the first result value; otherwise the string is returned 56 // as the second result value. 57 // 58 func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { 59 if base < 2 || base > len(digits) { 60 panic("strconv: illegal AppendInt/FormatInt base") 61 } 62 // 2 <= base && base <= len(digits) 63 64 var a [64 + 1]byte // +1 for sign of 64bit value in base 2 65 i := len(a) 66 67 if neg { 68 u = -u 69 } 70 71 // convert bits 72 if base == 10 { 73 // common case: use constants for / and % because 74 // the compiler can optimize it into a multiply+shift, 75 // and unroll loop 76 for u >= 100 { 77 i -= 2 78 q := u / 100 79 j := uintptr(u - q*100) 80 a[i+1] = digits01[j] 81 a[i+0] = digits10[j] 82 u = q 83 } 84 if u >= 10 { 85 i-- 86 q := u / 10 87 a[i] = digits[uintptr(u-q*10)] 88 u = q 89 } 90 91 } else if s := shifts[base]; s > 0 { 92 // base is power of 2: use shifts and masks instead of / and % 93 b := uint64(base) 94 m := uintptr(b) - 1 // == 1<<s - 1 95 for u >= b { 96 i-- 97 a[i] = digits[uintptr(u)&m] 98 u >>= s 99 } 100 101 } else { 102 // general case 103 b := uint64(base) 104 for u >= b { 105 i-- 106 a[i] = digits[uintptr(u%b)] 107 u /= b 108 } 109 } 110 111 // u < base 112 i-- 113 a[i] = digits[uintptr(u)] 114 115 // add sign, if any 116 if neg { 117 i-- 118 a[i] = '-' 119 } 120 121 if append_ { 122 d = append(dst, a[i:]...) 123 return 124 } 125 s = string(a[i:]) 126 return 127 }