add ip sub/half/middle functions
This commit is contained in:
parent
8a7b088216
commit
edb29aea3b
|
|
@ -87,20 +87,59 @@ func IPSubOne(ip []byte) []byte {
|
|||
return r
|
||||
}
|
||||
|
||||
func IPMiddle(sip, eip []byte) []byte {
|
||||
var result = make([]byte, len(sip))
|
||||
var carry uint16 = 0
|
||||
// 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)
|
||||
|
||||
// Add the two addresses with carry
|
||||
for i := len(sip) - 1; i >= 0; i-- {
|
||||
sum := uint16(sip[i]) + uint16(eip[i]) + carry
|
||||
result[i] = byte(sum >> 0x01) // Divide by 2
|
||||
carry = (sum & 0x01) << 7 // Carry for next byte (shift to MSB)
|
||||
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
|
||||
}
|
||||
|
||||
func IterateSegments(handle *os.File, before func(l string), filter func(region string) (string, error), done func(seg *Segment) error) error {
|
||||
var last *Segment = nil
|
||||
var scanner = bufio.NewScanner(handle)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
package xdb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
|
@ -99,6 +100,102 @@ func TestIPSubOne2(t *testing.T) {
|
|||
fmt.Printf("nip: %+v, ip:%+v", ip, nip)
|
||||
}
|
||||
|
||||
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 TestSplitSegmentV4(t *testing.T) {
|
||||
// var str = "1.1.0.0|1.3.3.24|中国|广东|深圳|电信"
|
||||
// var str = "0.0.0.0|1.255.225.254|0|0|0|内网IP|内网IP"
|
||||
|
|
|
|||
Loading…
Reference in New Issue