segments editor RC version

This commit is contained in:
Lion 2022-12-06 20:09:14 +08:00
parent f489d2a39a
commit 8b3a039edc
4 changed files with 185 additions and 38 deletions

25
data/ip.test.txt Normal file
View File

@ -0,0 +1,25 @@
1.0.0.0|1.0.0.255|澳大利亚|0|0|0|0
1.0.1.0|1.0.3.255|中国|0|福建省|福州市|电信
1.0.4.0|1.0.7.255|澳大利亚|0|维多利亚|墨尔本|0
1.0.8.0|1.0.15.255|中国|0|广东省|广州市|电信
1.0.16.0|1.0.31.255|日本|0|0|0|0
1.0.32.0|1.0.63.255|中国|0|广东省|广州市|电信
1.0.64.0|1.0.79.255|日本|0|广岛县|0|0
1.0.80.0|1.0.127.255|日本|0|冈山县|0|0
1.0.128.0|1.0.128.255|泰国|0|清莱府|0|TOT
1.0.129.0|1.0.132.191|泰国|0|曼谷|曼谷|TOT
1.0.132.192|1.0.132.255|泰国|0|Nakhon-Ratchasima|0|TOT
1.0.133.0|1.0.133.255|泰国|0|素攀武里府|0|TOT
1.0.134.0|1.0.134.255|泰国|0|曼谷|曼谷|TOT
1.0.135.0|1.0.135.127|泰国|0|华富里府|0|TOT
1.0.135.128|1.0.135.255|泰国|0|素攀武里府|0|TOT
1.0.136.0|1.0.136.255|泰国|0|龙仔厝府|0|TOT
1.0.137.0|1.0.137.255|泰国|0|大城府|0|TOT
1.0.138.0|1.0.143.255|泰国|0|曼谷|曼谷|TOT
1.0.144.0|1.0.159.255|泰国|0|春蓬府|0|TOT
1.0.160.0|1.0.162.255|泰国|0|洛坤府|0|TOT
1.0.163.0|1.0.163.255|泰国|0|春蓬府|0|TOT
1.0.164.0|1.0.164.63|泰国|0|0|0|TOT
1.0.164.64|1.0.164.127|泰国|0|普吉府|0|TOT
1.0.164.128|1.0.170.255|泰国|0|0|0|TOT
1.0.171.0|1.0.175.255|泰国|0|攀牙府|0|TOT

View File

@ -1,5 +1,5 @@
192.168.2.1|192.168.2.20|办公室A内网IP
192.168.2.21|192.168.2.30|办公室A内网IP
192.168.2.31|192.168.2.60|办公室B内网IP
192.168.2.61|192.168.2.91|办公室B内网IP
223.255.236.0|223.255.239.255|中国|0|上海|上海市|电信
192.168.2.1|192.168.2.20|0|0|0|内网IP|办公室A
192.168.2.21|192.168.2.30|0|0|0|内网IP|办公室A
192.168.2.31|192.168.2.60|0|0|0|内网IP|办公室B
192.168.2.61|192.168.2.91|0|0|0|内网IP|办公室B
223.255.236.0|223.255.239.255|中国|0|上海|上海市|电信

View File

@ -10,6 +10,7 @@ import (
"github.com/lionsoul2014/ip2region/maker/golang/xdb"
"log"
"os"
"regexp"
"strings"
"time"
)
@ -303,6 +304,12 @@ func edit() {
return
}
rExp, err := regexp.Compile("\\s+")
if err != nil {
fmt.Printf("failed to compile regexp: %s\n", err)
return
}
fmt.Printf("init the editor from source @ `%s` ... \n", srcFile)
var tStart = time.Now()
editor, err := xdb.NewEditor(srcFile)
@ -314,11 +321,12 @@ func edit() {
fmt.Printf("all segments loaded, length: %d, elapsed: %s\n", editor.SegLen(), time.Since(tStart))
var help = func() {
fmt.Printf("command list: \n")
fmt.Printf(" put [segment] : put the specifield segment\n")
fmt.Printf(" put_file [file] : put all the segments from the specified file\n")
fmt.Printf(" save : save all the changes to the destination source file\n")
fmt.Printf(" exit : exit the program\n")
fmt.Printf(" help : print this help menu\n")
fmt.Printf(" put [segment] : put the specifield $segment\n")
fmt.Printf(" put_file [file] : put all the segments from the specified $file\n")
fmt.Printf(" list [offset] [size] : list the first $size segments start from $offset\n")
fmt.Printf(" save : save all the changes to the destination source file\n")
fmt.Printf(" quit : exit the program\n")
fmt.Printf(" help : print this help menu\n")
}
help()
@ -341,7 +349,7 @@ func edit() {
cmd := strings.TrimSpace(line)
if cmd == "help" {
help()
} else if cmd == "exit" {
} else if cmd == "quit" {
if editor.NeedSave() {
fmt.Printf("there are changes that need to save, type 'quit!' to force quit\n")
} else {
@ -357,22 +365,45 @@ func edit() {
continue
}
fmt.Printf("all segments saved to %s\n", srcFile)
} else if strings.HasPrefix(cmd, "list") {
var sErr error
off, size, l := 0, 10, len("list")
str := strings.TrimSpace(cmd)
if len(str) > l {
sets := rExp.Split(cmd, 3)
switch len(sets) {
case 2:
_, sErr = fmt.Sscanf(cmd, "%s %d", &str, &off)
case 3:
_, sErr = fmt.Sscanf(cmd, "%s %d %d", &str, &off, &size)
}
}
if sErr != nil {
fmt.Printf("failed to parse the offset and size: %s\n", sErr)
continue
}
fmt.Printf("+-slice(%d,%d): \n", off, size)
for _, s := range editor.Slice(off, size) {
fmt.Printf("%s\n", s)
}
} else if strings.HasPrefix(cmd, "put ") {
seg := cmd[len("put "):]
err = editor.Put(seg)
seg := strings.TrimSpace(cmd[len("put "):])
o, n, err := editor.Put(seg)
if err != nil {
fmt.Printf("failed to Put(%s): %s\n", seg, err)
continue
}
fmt.Printf("Put(%s): Ok\n", seg)
fmt.Printf("Put(%s): Ok, with %d deletes and %d additions\n", seg, o, n)
} else if strings.HasPrefix(cmd, "put_file ") {
file := cmd[len("put_file "):]
err = editor.PutFile(file)
file := strings.TrimSpace(cmd[len("put_file "):])
o, n, err := editor.PutFile(file)
if err != nil {
fmt.Printf("failed to PutFile(%s): %s\n", file, err)
continue
}
fmt.Printf("PutFile(%s): Ok\n", file)
fmt.Printf("PutFile(%s): Ok, with %d deletes and %d additions\n", file, o, n)
} else if len(cmd) > 0 {
help()
}

View File

@ -81,10 +81,36 @@ func (e *Editor) SegLen() int {
return e.segments.Len()
}
func (e *Editor) Put(ip string) error {
func (e *Editor) Slice(offset int, size int) []*Segment {
var index = -1
var out []*Segment
var next *list.Element
for ele := e.segments.Front(); ele != nil; ele = next {
next = ele.Next()
s, ok := ele.Value.(*Segment)
if !ok {
continue
}
// offset match
index++
if index < offset {
continue
}
out = append(out, s)
if len(out) >= size {
break
}
}
return out
}
func (e *Editor) Put(ip string) (int, int, error) {
seg, err := SegmentFrom(ip)
if err != nil {
return err
return 0, 0, err
}
return e.PutSegment(seg)
@ -92,16 +118,17 @@ func (e *Editor) Put(ip string) error {
// PutSegment put the specified segment into the current segment list with
// the following position relationships.
// 1, fully contained like:
// 1, A - fully contained like:
// StartIP------seg.StartIP--------seg.EndIP----EndIP
// |------------------|
// 2, intersect like:
// 2, B - intersect like:
// StartIP------seg.StartIP------EndIP------|
// |---------------------seg.EndIP
//
func (e *Editor) PutSegment(seg *Segment) error {
var tOne *list.Element
func (e *Editor) PutSegment(seg *Segment) (int, int, error) {
var next *list.Element
var eList []*list.Element
var found = false
for ele := e.segments.Front(); ele != nil; ele = next {
next = ele.Next()
s, ok := ele.Value.(*Segment)
@ -110,50 +137,114 @@ func (e *Editor) PutSegment(seg *Segment) error {
continue
}
// find the related segment
if seg.StartIP >= s.StartIP && seg.StartIP <= s.EndIP {
tOne = ele
// found the related segment
if seg.StartIP <= s.EndIP && seg.StartIP >= s.StartIP {
found = true
}
if found == false {
continue
}
eList = append(eList, ele)
if seg.EndIP <= s.EndIP {
break
}
}
if tOne == nil {
if len(eList) == 0 {
// could this even be a case ?
// if the loaded segments contains all the segments we have
// from 0 to 0xffffffff
return fmt.Errorf("failed to find the related segment")
return 0, 0, fmt.Errorf("failed to find the related segment")
}
s, ok := tOne.Value.(*Segment)
if !ok {
return fmt.Errorf("internal error: invalid segment type")
// print for debug
// for i, s := range eList {
// fmt.Printf("ele %d: %s\n", i, s.Value.(*Segment))
// }
// segment split
var sList []*Segment
var head = eList[0].Value.(*Segment)
if seg.StartIP > head.StartIP {
sList = append(sList, &Segment{
StartIP: head.StartIP,
EndIP: seg.StartIP - 1,
Region: head.Region,
})
}
fmt.Printf("tOne: %s\n", s)
// append the new segment
sList = append(sList, seg)
// check and do the tailing segment append
if len(sList) > 0 {
// check and append the tailing
var tail = eList[len(eList)-1].Value.(*Segment)
if seg.EndIP < tail.EndIP {
sList = append(sList, &Segment{
StartIP: seg.EndIP + 1,
EndIP: tail.EndIP,
Region: tail.Region,
})
}
}
// print for debug
// for i, s := range sList {
// fmt.Printf("%d: %s\n", i, s)
// }
// delete all the in-range segments and
var base *list.Element
var oldRows, newRows = len(eList), len(sList)
for _, ele := range eList {
base = ele.Next()
e.segments.Remove(ele)
}
// add all the new segments
if base == nil {
for _, s := range sList {
e.segments.PushBack(s)
}
} else {
for _, s := range sList {
e.segments.InsertBefore(s, base)
}
}
// open the to save flag
e.toSave = true
return nil
return oldRows, newRows, nil
}
func (e *Editor) PutFile(src string) error {
func (e *Editor) PutFile(src string) (int, int, error) {
handle, err := os.OpenFile(src, os.O_RDONLY, 0600)
if err != nil {
return err
return 0, 0, err
}
var oldRows, newRows = 0, 0
iErr := IterateSegments(handle, func(l string) {
// do nothing here
}, func(seg *Segment) error {
return e.PutSegment(seg)
o, n, err := e.PutSegment(seg)
if err == nil {
oldRows += o
newRows += n
}
return err
})
if iErr != nil {
return iErr
return oldRows, newRows, iErr
}
_ = handle.Close()
return nil
return oldRows, newRows, nil
}
func (e *Editor) Save() error {