discontinuous or unordered data segments edit supports

This commit is contained in:
lionsoul2014 2026-03-05 14:22:03 +08:00
parent b965ab8be9
commit 51e194a105
2 changed files with 74 additions and 20 deletions

View File

@ -92,24 +92,55 @@ func (e *Editor) loadSegments() error {
return IPCompare(segments[i].StartIP, segments[j].StartIP) < 0 return IPCompare(segments[i].StartIP, segments[j].StartIP) < 0
}) })
// open the to save
e.toSave = true
}
// check and fill in the discontinuous segments
// to Keep the entire data continuous.
last = nil last = nil
for _, seg := range segments { for _, seg := range segments {
// check the order of the data segment
if err := seg.After(last); err != nil { if err := seg.After(last); err != nil {
return fmt.Errorf("overlap checking: %w", err)
} }
if last == nil {
if IPCompare(seg.StartIP, e.verison.Min) > 0 {
e.segments.PushBack(&Segment{
StartIP: e.verison.Min,
EndIP: IPSubOne(seg.StartIP),
Region: "",
})
}
} else if err := seg.RightBehind(last); err == nil {
// Do nothing here since it just right behind the last
} else if err := seg.After(last); err != nil {
// segments overlap
return fmt.Errorf("overlap checking: %w", err)
} else {
// push the padding segments
e.segments.PushBack(&Segment{
StartIP: IPAddOne(last.EndIP),
EndIP: IPSubOne(seg.StartIP),
Region: "",
})
}
// push the current segment
e.segments.PushBack(seg)
// reset the last // reset the last
last = seg last = seg
} }
// open the to save // check and padding the tailing segmnet
e.toSave = true if back := e.segments.Back(); back != nil {
if IPCompare(e.verison.Max, back.Value.(*Segment).EndIP) > 0 {
e.segments.PushBack(&Segment{
StartIP: IPAddOne(back.Value.(*Segment).EndIP),
EndIP: e.verison.Max,
Region: "",
})
} }
// export the segments to e.segments
for _, seg := range segments {
e.segments.PushBack(seg)
} }
segments = nil // let GC do it work segments = nil // let GC do it work
@ -173,21 +204,24 @@ func (e *Editor) Put(ip string) (int, int, error) {
func (e *Editor) PutSegment(seg *Segment) (int, int, error) { func (e *Editor) PutSegment(seg *Segment) (int, int, error) {
var next *list.Element var next *list.Element
var eList []*list.Element var eList []*list.Element
var found = false var found, counter = false, 0
for ele := e.segments.Front(); ele != nil; ele = next { for ele := e.segments.Front(); ele != nil; ele = next {
next = ele.Next() next = ele.Next()
s, ok := ele.Value.(*Segment) s, ok := ele.Value.(*Segment)
if !ok { if !ok {
// could this even be a case ? // could this even be a case ?
continue return 0, 0, fmt.Errorf("type error: ele not a Segment ptr")
} }
counter++
// found the related segment // found the related segment
if IPCompare(seg.StartIP, s.EndIP) <= 0 && IPCompare(seg.StartIP, s.StartIP) >= 0 { if found {
// just keep going
} else if IPCompare(seg.StartIP, s.StartIP) >= 0 &&
IPCompare(seg.StartIP, s.EndIP) <= 0 {
found = true found = true
} } else {
if !found {
continue continue
} }
@ -199,8 +233,6 @@ func (e *Editor) PutSegment(seg *Segment) (int, int, error) {
if len(eList) == 0 { if len(eList) == 0 {
// could this even be a case ? // could this even be a case ?
// if the loaded segments contains all the segments we have
// from 0 to 0xffffffff
return 0, 0, fmt.Errorf("failed to find the related segment") return 0, 0, fmt.Errorf("failed to find the related segment")
} }
@ -310,6 +342,11 @@ func (e *Editor) Save() error {
continue continue
} }
// ignore the padded or empty segment
if s.Region == "" {
continue
}
// var l = s.String() // var l = s.String()
// _, err = dstHandle.WriteString(fmt.Sprintf("%s\n", l)) // _, err = dstHandle.WriteString(fmt.Sprintf("%s\n", l))
_, err = fmt.Fprintln(dstHandle, s.String()) _, err = fmt.Fprintln(dstHandle, s.String())

View File

@ -26,6 +26,9 @@ type Version struct {
// ip compares // ip compares
IPCompare func([]byte, []byte) int IPCompare func([]byte, []byte) int
Min []byte
Max []byte
} }
func (v *Version) String() string { func (v *Version) String() string {
@ -55,6 +58,8 @@ var (
ip2[1], ip2[2] = ip2[2], ip2[1] ip2[1], ip2[2] = ip2[2], ip2[1]
return bytes.Compare(ip1, ip2) return bytes.Compare(ip1, ip2)
}, },
Min: []byte{0x00, 0x00, 0x00, 0x00},
Max: []byte{0xff, 0xff, 0xff, 0xff},
} }
IPv6 = &Version{ IPv6 = &Version{
Id: 6, Id: 6,
@ -68,6 +73,18 @@ var (
IPCompare: func(ip1, ip2 []byte) int { IPCompare: func(ip1, ip2 []byte) int {
return bytes.Compare(ip1, ip2) return bytes.Compare(ip1, ip2)
}, },
Min: []byte{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
},
Max: []byte{
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
},
} }
) )