1/** 2 * Copyright 2014 Paul Querna 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18/* Portions of this file are on Go stdlib's strconv/iota.go */ 19// Copyright 2009 The Go Authors. All rights reserved. 20// Use of this source code is governed by a BSD-style 21// license that can be found in the LICENSE file. 22 23package v1 24 25import ( 26 "io" 27) 28 29const ( 30 digits = "0123456789abcdefghijklmnopqrstuvwxyz" 31 digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" 32 digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" 33) 34 35var shifts = [len(digits) + 1]uint{ 36 1 << 1: 1, 37 1 << 2: 2, 38 1 << 3: 3, 39 1 << 4: 4, 40 1 << 5: 5, 41} 42 43var smallNumbers = [][]byte{ 44 []byte("0"), 45 []byte("1"), 46 []byte("2"), 47 []byte("3"), 48 []byte("4"), 49 []byte("5"), 50 []byte("6"), 51 []byte("7"), 52 []byte("8"), 53 []byte("9"), 54 []byte("10"), 55} 56 57type FormatBitsWriter interface { 58 io.Writer 59 io.ByteWriter 60} 61 62type FormatBitsScratch struct{} 63 64// 65// DEPRECIATED: `scratch` is no longer used, FormatBits2 is available. 66// 67// FormatBits computes the string representation of u in the given base. 68// If neg is set, u is treated as negative int64 value. If append_ is 69// set, the string is appended to dst and the resulting byte slice is 70// returned as the first result value; otherwise the string is returned 71// as the second result value. 72// 73func FormatBits(scratch *FormatBitsScratch, dst FormatBitsWriter, u uint64, base int, neg bool) { 74 FormatBits2(dst, u, base, neg) 75} 76 77// FormatBits2 computes the string representation of u in the given base. 78// If neg is set, u is treated as negative int64 value. If append_ is 79// set, the string is appended to dst and the resulting byte slice is 80// returned as the first result value; otherwise the string is returned 81// as the second result value. 82// 83func FormatBits2(dst FormatBitsWriter, u uint64, base int, neg bool) { 84 if base < 2 || base > len(digits) { 85 panic("strconv: illegal AppendInt/FormatInt base") 86 } 87 // fast path for small common numbers 88 if u <= 10 { 89 if neg { 90 dst.WriteByte('-') 91 } 92 dst.Write(smallNumbers[u]) 93 return 94 } 95 96 // 2 <= base && base <= len(digits) 97 98 var a = makeSlice(65) 99 // var a [64 + 1]byte // +1 for sign of 64bit value in base 2 100 i := len(a) 101 102 if neg { 103 u = -u 104 } 105 106 // convert bits 107 if base == 10 { 108 // common case: use constants for / and % because 109 // the compiler can optimize it into a multiply+shift, 110 // and unroll loop 111 for u >= 100 { 112 i -= 2 113 q := u / 100 114 j := uintptr(u - q*100) 115 a[i+1] = digits01[j] 116 a[i+0] = digits10[j] 117 u = q 118 } 119 if u >= 10 { 120 i-- 121 q := u / 10 122 a[i] = digits[uintptr(u-q*10)] 123 u = q 124 } 125 126 } else if s := shifts[base]; s > 0 { 127 // base is power of 2: use shifts and masks instead of / and % 128 b := uint64(base) 129 m := uintptr(b) - 1 // == 1<<s - 1 130 for u >= b { 131 i-- 132 a[i] = digits[uintptr(u)&m] 133 u >>= s 134 } 135 136 } else { 137 // general case 138 b := uint64(base) 139 for u >= b { 140 i-- 141 a[i] = digits[uintptr(u%b)] 142 u /= b 143 } 144 } 145 146 // u < base 147 i-- 148 a[i] = digits[uintptr(u)] 149 150 // add sign, if any 151 if neg { 152 i-- 153 a[i] = '-' 154 } 155 156 dst.Write(a[i:]) 157 158 Pool(a) 159 160 return 161} 162