add bytes ip sub and middle util func
This commit is contained in:
parent
dabe7798f6
commit
d9fc17727e
|
|
@ -82,6 +82,59 @@ func IPSubOne(ip []byte) []byte {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPSub Sub the spcecified two byte ip
|
||||||
|
func IPSub(sip, eip []byte) ([]byte, error) {
|
||||||
|
if len(sip) != len(eip) {
|
||||||
|
return []byte{}, fmt.Errorf("length of the two ips are not the same")
|
||||||
|
}
|
||||||
|
|
||||||
|
var carry uint16 = 0
|
||||||
|
var result = make([]byte, len(sip)+1)
|
||||||
|
|
||||||
|
for i := len(sip) - 1; i >= 0; i-- {
|
||||||
|
sum := uint16(sip[i]) + uint16(eip[i]) + carry
|
||||||
|
result[i+1] = byte(sum) // Store standard 8-bit result
|
||||||
|
carry = sum >> 8 // Extract the 1-bit carry for the next byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and append the carry
|
||||||
|
if carry > 0 {
|
||||||
|
result[0] = byte(carry)
|
||||||
|
return result, nil
|
||||||
|
} else {
|
||||||
|
return result[1:], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPHalf get the half value of an input byte ip
|
||||||
|
func IPHalf(ip []byte) []byte {
|
||||||
|
var length = len(ip)
|
||||||
|
var result = make([]byte, length)
|
||||||
|
// Tracks the bit falling off from the previous byte
|
||||||
|
var carry byte = 0
|
||||||
|
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
// 1. Shift current byte right by 1
|
||||||
|
// 2. Or (|) with the carry from the previous byte (shifted to the MSB position)
|
||||||
|
result[i] = (ip[i] >> 1) | (carry << 7)
|
||||||
|
|
||||||
|
// 3. Capture the Least Significant Bit (LSB) to use as carry for the next byte
|
||||||
|
carry = ip[i] & 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPMiddle get the middle value of two input ip address
|
||||||
|
func IPMiddle(sip, eip []byte) ([]byte, error) {
|
||||||
|
buf, err := IPSub(sip, eip)
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, fmt.Errorf("IPSub(%s, %s): %w", IP2String(sip), IP2String(eip), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPHalf(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Verify if the current Searcher could be used to search the specified xdb file.
|
// Verify if the current Searcher could be used to search the specified xdb file.
|
||||||
// Why do we need this check ?
|
// Why do we need this check ?
|
||||||
// The future features of the xdb impl may cause the current searcher not able to work properly.
|
// The future features of the xdb impl may cause the current searcher not able to work properly.
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
package xdb
|
package xdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -41,6 +42,102 @@ func TestIPCompare(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIPSub(t *testing.T) {
|
||||||
|
var strToSub = "1.2.3.4"
|
||||||
|
bytesToSub, err := ParseIP(strToSub)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse ip %s", strToSub)
|
||||||
|
}
|
||||||
|
var intToSub = int(binary.BigEndian.Uint32(bytesToSub))
|
||||||
|
t.Logf("to sub ip: %d -> %s", intToSub, strToSub)
|
||||||
|
|
||||||
|
counter := 0
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
for i := 0; i < 0x2FFFFFFF; i++ {
|
||||||
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
||||||
|
subVal, err := IPSub(buf, bytesToSub)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to IPSub(%s,%s): %s", IP2String(buf), strToSub, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// do it as two integers
|
||||||
|
byteSub := int(binary.BigEndian.Uint32(subVal))
|
||||||
|
intSub := i + intToSub
|
||||||
|
if byteSub != intSub {
|
||||||
|
t.Fatal("byte and int sub value are not the same")
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("test done with %d ips", counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPHalf(t *testing.T) {
|
||||||
|
var buf = make([]byte, 4)
|
||||||
|
for i := 0; i < 0xFFFFFFFF; i++ {
|
||||||
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
||||||
|
half := IPHalf(buf)
|
||||||
|
|
||||||
|
// do it as two integers
|
||||||
|
byteMiddle := binary.BigEndian.Uint32(half)
|
||||||
|
intMidle := i >> 1
|
||||||
|
if byteMiddle != uint32(intMidle) {
|
||||||
|
t.Fatal("byte middle and int middle are not the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSubOverflow(t *testing.T) {
|
||||||
|
var ip1Str = "255.255.255.250"
|
||||||
|
ip1Bytes, err := ParseIP(ip1Str)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to ParseIP(%s): %s", ip1Str, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buff = make([]byte, 4)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
binary.BigEndian.PutUint32(buff, uint32(i))
|
||||||
|
ipSub, err := IPSub(ip1Bytes, buff)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to IPSub(%s, %s): %s", ip1Str, IP2String(buff), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("IPSub(%s, %s) = %+v", ip1Str, IP2String(buff), ipSub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMiddle(t *testing.T) {
|
||||||
|
var sIPStr = "0.0.0.0"
|
||||||
|
sBytes, err := ParseIP(sIPStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse ip %s", sIPStr)
|
||||||
|
}
|
||||||
|
var sInt = int(binary.BigEndian.Uint32(sBytes))
|
||||||
|
t.Logf("start ip: %d -> %s", sInt, sIPStr)
|
||||||
|
|
||||||
|
counter := 0
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
for i := 0; i < 0x0FFFFFFF; i++ {
|
||||||
|
binary.BigEndian.PutUint32(buf, uint32(i))
|
||||||
|
midVal, err := IPMiddle(sBytes, buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to IPMiddle(%s,%s): %s", sIPStr, IP2String(buf), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// do it as two integers
|
||||||
|
byteMid := int(binary.BigEndian.Uint32(midVal))
|
||||||
|
intMid := (sInt + i) >> 1
|
||||||
|
if byteMid != intMid {
|
||||||
|
t.Fatal("byte and int middle value are not the same")
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("test done with %d ips", counter)
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadVectorIndex(t *testing.T) {
|
func TestLoadVectorIndex(t *testing.T) {
|
||||||
vIndex, err := LoadVectorIndexFromFile("../../../data/ip2region_v4.xdb")
|
vIndex, err := LoadVectorIndexFromFile("../../../data/ip2region_v4.xdb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue