Home | History | Annotate | Download | only in strconv
      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 }
    203