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  }