Commit 72621e58 authored by Geoff Simmons's avatar Geoff Simmons

Add parseInt64() for byte slices (with no allocations).

parent ee9c9637
......@@ -29,11 +29,28 @@
package log
const (
cutoff = ^uint32(0) / 10
rest = byte(^uint32(0)-cutoff*10) + byte('0')
cutoffU32 = ^uint32(0) / 10
restU32 = byte(^uint32(0)-cutoffU32*10) + byte('0')
maxSigned64 = int64(^uint64(1<<63))
cutoffDec64 = int64(maxSigned64 / 10)
cutoffOct64 = int64(1 << 60)
cutoffHex64 = int64(1 << 59)
restPosDec64 = byte(maxSigned64-cutoffDec64*10) + byte('0')
restNegDec64 = byte(restPosDec64 + 1)
ill = uint8(255)
)
var wsTable = wsTbl()
var (
wsTable = wsTbl()
hxTbl = [55]uint8{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
ill, ill, ill, ill, ill, ill, ill, 10, 11, 12,
13, 14, 15, ill, ill, ill, ill, ill, ill, ill,
ill, ill, ill, ill, ill, ill, ill, ill, ill, ill,
ill, ill, ill, ill, ill, ill, ill, ill, ill, 10,
11, 12, 13, 14, 15,
}
)
func wsTbl() [256]bool {
var tbl [256]bool
......@@ -52,11 +69,11 @@ func atoUint32(bytes []byte) (uint32, bool) {
}
val := uint32(0)
for _, b := range bytes {
if val >= cutoff {
if val > cutoff {
if val >= cutoffU32 {
if val > cutoffU32 {
return 0, false
}
if b > rest {
if b > restU32 {
return 0, false
}
}
......@@ -68,6 +85,116 @@ func atoUint32(bytes []byte) (uint32, bool) {
return val, true
}
func parseOct(bytes []byte, pos bool) (int64, bool) {
val := int64(0)
for _, b := range bytes {
if val >= cutoffOct64 {
if pos || val != cutoffOct64 || b != byte('0') {
return 0, false
}
}
if b < byte('0') || b > byte('7') {
if wsTable[b] {
break
}
return 0, false
}
val <<= 3
val |= int64(b-byte('0'))
}
if pos {
return val, true
}
return 0 - val, true
}
func parseHex(bytes []byte, pos bool) (int64, bool) {
val := int64(0)
for _, b := range bytes {
if val >= cutoffHex64 {
if pos || val != cutoffHex64 || b != byte('0') {
return 0, false
}
}
if b < byte('0') || b > byte('f') || hxTbl[b-byte('0')] == ill {
if wsTable[b] {
break
}
return 0, false
}
val <<= 4
val |= int64(hxTbl[b-byte('0')])
}
if pos {
return val, true
}
return 0 - val, true
}
func parseDec(bytes []byte, pos bool) (int64, bool) {
rest := restPosDec64
if !pos {
rest = restNegDec64
}
val := int64(0)
for _, b := range bytes {
if val >= cutoffDec64 {
if val > cutoffDec64 {
return 0, false
}
if b > rest {
return 0, false
}
}
if b < byte('0') || b > byte('9') {
if wsTable[b] {
break
}
return 0, false
}
val = val*10 + int64(b-byte('0'))
}
if pos {
return val, true
}
return 0 - val, true
}
// ParseInt(b, 0, 64), or strtoll(b, &p, 0), for byte slices.
// Only whitespace after the digits is permitted.
func parseInt64(bytes []byte) (int64, bool) {
l := len(bytes)
if l == 0 {
return 0, false
}
pos := true
i := 0
for ; i < l && wsTable[bytes[i]]; i++ {
}
if i == l {
return 0, false
}
if bytes[i] == byte('+') || bytes[i] == byte('-') {
if bytes[i] == byte('-') {
pos = false
}
i++
if i == l {
return 0, false
}
}
if bytes[i] == byte('0') {
if i == l {
return 0, true
}
if i+1 < l && bytes[i+1] == byte('x') {
return parseHex(bytes[i+2:], pos)
}
return parseOct(bytes[i+1:], pos)
}
return parseDec(bytes[i:], pos)
}
// Return the byte slice delimiters of the Nth whitespace-separated
// field in the given byte slice, counting fields from 0 and ignoring
// leading and trailing whitespace:
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment