src/pkg/strconv/itoa.go - The Go Programming Language

Golang

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	}