Created
March 20, 2025 14:25
-
-
Save millken/838a528ede2c7f7f289f6a7e7197e0f0 to your computer and use it in GitHub Desktop.
fast golang ip2long
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//go:noinline | |
func IpToLong(ipStr string) uint32 { | |
ptr := unsafe.Pointer(unsafe.StringData(ipStr)) | |
var ( | |
n uint32 | |
oct uint32 | |
p = ptr | |
) | |
// 第一段: XXX. | |
for { | |
c := *(*byte)(p) | |
if c == '.' { | |
p = unsafe.Add(p, 1) | |
break | |
} | |
oct = oct*10 + uint32(c&0x0F) // 利用 ASCII 特性省去 -'0' | |
p = unsafe.Add(p, 1) | |
} | |
n = oct << 24 | |
// 第二段: XXX. | |
oct = 0 | |
for { | |
c := *(*byte)(p) | |
if c == '.' { | |
p = unsafe.Add(p, 1) | |
break | |
} | |
oct = oct*10 + uint32(c&0x0F) | |
p = unsafe.Add(p, 1) | |
} | |
n |= oct << 16 | |
// 第三段: XXX. | |
oct = 0 | |
for { | |
c := *(*byte)(p) | |
if c == '.' { | |
p = unsafe.Add(p, 1) | |
break | |
} | |
oct = oct*10 + uint32(c&0x0F) | |
p = unsafe.Add(p, 1) | |
} | |
n |= oct << 8 | |
// 第四段: XXX | |
oct = 0 | |
for uintptr(unsafe.Pointer(p))-uintptr(ptr) < uintptr(len(ipStr)) { | |
c := *(*byte)(p) | |
oct = oct*10 + uint32(c&0x0F) | |
p = unsafe.Add(p, 1) | |
} | |
return n | oct | |
} |
//go:noinline
func IPv6ToUint128(ipStr string) (hi, lo uint64) {
ptr := unsafe.Pointer(unsafe.StringData(ipStr))
end := uintptr(len(ipStr))
var (
groups uint16
compressPos = -1
groupIdx int
hexAcc uint16
colonCount int
hasIPv4 bool
)
// 状态机扫描
for p := uintptr(0); p < end; p++ {
c := *(*byte)(unsafe.Add(ptr, p))
switch {
// 处理 IPv4 嵌入 (如 ::ffff:192.168.0.1)
case c == '.' && hasIPv4:
ipv4Part := unsafe.Slice((*byte)(unsafe.Add(ptr, p-3)), 7) // 反向取 3 字节
var a, b, c, d uint8
a = ipv4Part&0x0F*10 + ipv4Part&0x0F
b = ipv4Part&0x0F*10 + ipv4Part&0x0F
c = ipv4Part&0x0F*10 + ipv4Part&0x0F
d = ipv4Part&0x0F*10 + ipv4Part&0x0F
groups[groupIdx] = uint16(a<<8 | b)
groups[groupIdx+1] = uint16(c<<8 | d)
groupIdx += 2
break
// 处理十六进制数字
case c >= '0' && c <= '9':
hexAcc = hexAcc<<4 | uint16(c&0x0F)
case c >= 'a' && c <= 'f':
hexAcc = hexAcc<<4 | uint16(c-'a'+10)
case c >= 'A' && c <= 'F':
hexAcc = hexAcc<<4 | uint16(c-'A'+10)
// 处理分组分隔
case c == ':':
if colonCount == 1 { // 发现压缩标记 ::
compressPos = groupIdx
colonCount = 0
continue
}
groups[groupIdx] = hexAcc
groupIdx++
hexAcc = 0
colonCount++
// 触发 IPv4 处理标志
case c == '.':
hasIPv4 = true
}
}
// 处理最后一个分组
if hexAcc != 0 || groups[groupIdx] != 0 {
groups[groupIdx] = hexAcc
groupIdx++
}
// 处理压缩的零组
if compressPos != -1 {
gap := 8 - groupIdx
copy(groups[compressPos+gap:], groups[compressPos:groupIdx])
for i := compressPos; i < compressPos+gap; i++ {
groups[i] = 0
}
groupIdx = 8
}
// 合并高低位
hi = uint64(groups)<<48 | uint64(groups)<<32 |
uint64(groups)<<16 | uint64(groups)
lo = uint64(groups)<<48 | uint64(groups)<<32 |
uint64(groups)<<16 | uint64(groups)
return
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.