github.com/webmafia/fast@v0.10.0/string_buffer_num.go (about) 1 // Borrowed from jsoniter (https://github.com/json-iterator/go) 2 package fast 3 4 import ( 5 "math" 6 "strconv" 7 ) 8 9 var digits [1000]uint32 10 var pow10 = [...]uint64{1, 10, 100, 1000, 10000, 100000, 1000000} 11 12 func init() { 13 for i := uint32(0); i < 1000; i++ { 14 digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0' 15 if i < 10 { 16 digits[i] += 2 << 24 17 } else if i < 100 { 18 digits[i] += 1 << 24 19 } 20 } 21 } 22 23 func writeFirstBuf(space []byte, v uint32) []byte { 24 start := v >> 24 25 if start == 0 { 26 space = append(space, byte(v>>16), byte(v>>8)) 27 } else if start == 1 { 28 space = append(space, byte(v>>8)) 29 } 30 space = append(space, byte(v)) 31 return space 32 } 33 34 func writeBuf(buf []byte, v uint32) []byte { 35 return append(buf, byte(v>>16), byte(v>>8), byte(v)) 36 } 37 38 // Write uint8 39 func (b *StringBuffer) WriteUint8(val uint8) { 40 b.buf = writeFirstBuf(b.buf, digits[val]) 41 } 42 43 // Write int8 44 func (b *StringBuffer) WriteInt8(nval int8) { 45 var val uint8 46 if nval < 0 { 47 val = uint8(-nval) 48 b.buf = append(b.buf, '-') 49 } else { 50 val = uint8(nval) 51 } 52 b.buf = writeFirstBuf(b.buf, digits[val]) 53 } 54 55 // Write uint16 56 func (b *StringBuffer) WriteUint16(val uint16) { 57 q1 := val / 1000 58 if q1 == 0 { 59 b.buf = writeFirstBuf(b.buf, digits[val]) 60 return 61 } 62 r1 := val - q1*1000 63 b.buf = writeFirstBuf(b.buf, digits[q1]) 64 b.buf = writeBuf(b.buf, digits[r1]) 65 } 66 67 // Write int16 68 func (b *StringBuffer) WriteInt16(nval int16) { 69 var val uint16 70 if nval < 0 { 71 val = uint16(-nval) 72 b.buf = append(b.buf, '-') 73 } else { 74 val = uint16(nval) 75 } 76 b.WriteUint16(val) 77 } 78 79 // Write uint32 80 func (b *StringBuffer) WriteUint32(val uint32) { 81 q1 := val / 1000 82 if q1 == 0 { 83 b.buf = writeFirstBuf(b.buf, digits[val]) 84 return 85 } 86 r1 := val - q1*1000 87 q2 := q1 / 1000 88 if q2 == 0 { 89 b.buf = writeFirstBuf(b.buf, digits[q1]) 90 b.buf = writeBuf(b.buf, digits[r1]) 91 return 92 } 93 r2 := q1 - q2*1000 94 q3 := q2 / 1000 95 if q3 == 0 { 96 b.buf = writeFirstBuf(b.buf, digits[q2]) 97 } else { 98 r3 := q2 - q3*1000 99 b.buf = append(b.buf, byte(q3+'0')) 100 b.buf = writeBuf(b.buf, digits[r3]) 101 } 102 b.buf = writeBuf(b.buf, digits[r2]) 103 b.buf = writeBuf(b.buf, digits[r1]) 104 } 105 106 // Write int32 107 func (b *StringBuffer) WriteInt32(nval int32) { 108 var val uint32 109 if nval < 0 { 110 val = uint32(-nval) 111 b.buf = append(b.buf, '-') 112 } else { 113 val = uint32(nval) 114 } 115 b.WriteUint32(val) 116 } 117 118 // Write uint64 119 func (b *StringBuffer) WriteUint64(val uint64) { 120 q1 := val / 1000 121 if q1 == 0 { 122 b.buf = writeFirstBuf(b.buf, digits[val]) 123 return 124 } 125 r1 := val - q1*1000 126 q2 := q1 / 1000 127 if q2 == 0 { 128 b.buf = writeFirstBuf(b.buf, digits[q1]) 129 b.buf = writeBuf(b.buf, digits[r1]) 130 return 131 } 132 r2 := q1 - q2*1000 133 q3 := q2 / 1000 134 if q3 == 0 { 135 b.buf = writeFirstBuf(b.buf, digits[q2]) 136 b.buf = writeBuf(b.buf, digits[r2]) 137 b.buf = writeBuf(b.buf, digits[r1]) 138 return 139 } 140 r3 := q2 - q3*1000 141 q4 := q3 / 1000 142 if q4 == 0 { 143 b.buf = writeFirstBuf(b.buf, digits[q3]) 144 b.buf = writeBuf(b.buf, digits[r3]) 145 b.buf = writeBuf(b.buf, digits[r2]) 146 b.buf = writeBuf(b.buf, digits[r1]) 147 return 148 } 149 r4 := q3 - q4*1000 150 q5 := q4 / 1000 151 if q5 == 0 { 152 b.buf = writeFirstBuf(b.buf, digits[q4]) 153 b.buf = writeBuf(b.buf, digits[r4]) 154 b.buf = writeBuf(b.buf, digits[r3]) 155 b.buf = writeBuf(b.buf, digits[r2]) 156 b.buf = writeBuf(b.buf, digits[r1]) 157 return 158 } 159 r5 := q4 - q5*1000 160 q6 := q5 / 1000 161 if q6 == 0 { 162 b.buf = writeFirstBuf(b.buf, digits[q5]) 163 } else { 164 b.buf = writeFirstBuf(b.buf, digits[q6]) 165 r6 := q5 - q6*1000 166 b.buf = writeBuf(b.buf, digits[r6]) 167 } 168 b.buf = writeBuf(b.buf, digits[r5]) 169 b.buf = writeBuf(b.buf, digits[r4]) 170 b.buf = writeBuf(b.buf, digits[r3]) 171 b.buf = writeBuf(b.buf, digits[r2]) 172 b.buf = writeBuf(b.buf, digits[r1]) 173 } 174 175 // Write int64 176 func (b *StringBuffer) WriteInt64(nval int64) { 177 var val uint64 178 if nval < 0 { 179 val = uint64(-nval) 180 b.buf = append(b.buf, '-') 181 } else { 182 val = uint64(nval) 183 } 184 b.WriteUint64(val) 185 } 186 187 // Write int 188 func (b *StringBuffer) WriteInt(val int) { 189 b.WriteInt64(int64(val)) 190 } 191 192 // Write uint 193 func (b *StringBuffer) WriteUint(val uint) { 194 b.WriteUint64(uint64(val)) 195 } 196 197 // Write float32 198 func (b *StringBuffer) WriteFloat32(val float32) { 199 abs := math.Abs(float64(val)) 200 fmt := byte('f') 201 // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. 202 if abs != 0 { 203 if float32(abs) < 1e-6 || float32(abs) >= 1e21 { 204 fmt = 'e' 205 } 206 } 207 b.buf = strconv.AppendFloat(b.buf, float64(val), fmt, -1, 32) 208 } 209 210 // Write float32 with ONLY 6 digits precision although much much faster 211 func (b *StringBuffer) WriteFloat32Lossy(val float32) { 212 if val < 0 { 213 b.WriteByte('-') 214 val = -val 215 } 216 if val > 0x4ffffff { 217 b.WriteFloat32(val) 218 return 219 } 220 precision := 6 221 exp := uint64(1000000) // 6 222 lval := uint64(float64(val)*float64(exp) + 0.5) 223 b.WriteUint64(lval / exp) 224 fval := lval % exp 225 if fval == 0 { 226 return 227 } 228 b.WriteByte('.') 229 for p := precision - 1; p > 0 && fval < pow10[p]; p-- { 230 b.WriteByte('0') 231 } 232 b.WriteUint64(fval) 233 for b.buf[len(b.buf)-1] == '0' { 234 b.buf = b.buf[:len(b.buf)-1] 235 } 236 } 237 238 // Write float64 239 func (b *StringBuffer) WriteFloat64(val float64) { 240 abs := math.Abs(val) 241 fmt := byte('f') 242 // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. 243 if abs != 0 { 244 if abs < 1e-6 || abs >= 1e21 { 245 fmt = 'e' 246 } 247 } 248 b.buf = strconv.AppendFloat(b.buf, float64(val), fmt, -1, 64) 249 } 250 251 // Write float64 with ONLY 6 digits precision although much much faster 252 func (b *StringBuffer) WriteFloat64Lossy(val float64) { 253 if val < 0 { 254 b.WriteByte('-') 255 val = -val 256 } 257 if val > 0x4ffffff { 258 b.WriteFloat64(val) 259 return 260 } 261 precision := 6 262 exp := uint64(1000000) // 6 263 lval := uint64(val*float64(exp) + 0.5) 264 b.WriteUint64(lval / exp) 265 fval := lval % exp 266 if fval == 0 { 267 return 268 } 269 b.WriteByte('.') 270 for p := precision - 1; p > 0 && fval < pow10[p]; p-- { 271 b.WriteByte('0') 272 } 273 b.WriteUint64(fval) 274 for b.buf[len(b.buf)-1] == '0' { 275 b.buf = b.buf[:len(b.buf)-1] 276 } 277 }