Merge pull request #457 from lionsoul2014/fr_go_editor_non_contiguous_range
discontinuous or unordered data segments edit supports
This commit is contained in:
commit
8adec5a3c8
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Editor struct {
|
type Editor struct {
|
||||||
|
|
@ -56,6 +57,8 @@ func NewEditor(version *Version, srcFile string) (*Editor, error) {
|
||||||
// Load all the segments from the source file
|
// Load all the segments from the source file
|
||||||
func (e *Editor) loadSegments() error {
|
func (e *Editor) loadSegments() error {
|
||||||
var last *Segment = nil
|
var last *Segment = nil
|
||||||
|
var segments []*Segment
|
||||||
|
var sorting = false
|
||||||
|
|
||||||
var iErr = IterateSegments(e.srcHandle, func(l string) {
|
var iErr = IterateSegments(e.srcHandle, func(l string) {
|
||||||
// do nothing here
|
// do nothing here
|
||||||
|
|
@ -65,12 +68,17 @@ func (e *Editor) loadSegments() error {
|
||||||
return fmt.Errorf("invalid ip segment(%s expected)", e.verison.Name)
|
return fmt.Errorf("invalid ip segment(%s expected)", e.verison.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the continuity of the data segment
|
// check the order of the data segment
|
||||||
if err := seg.RightBehind(last); err != nil {
|
// if err := seg.RightBehind(last); err != nil {
|
||||||
return err
|
if err := seg.After(last); err != nil {
|
||||||
|
// return err
|
||||||
|
// @Note: If the continuity is disrupted,
|
||||||
|
// we will sort all these segments later.
|
||||||
|
sorting = true
|
||||||
}
|
}
|
||||||
|
|
||||||
e.segments.PushBack(seg)
|
// e.segments.PushBack(seg)
|
||||||
|
segments = append(segments, seg)
|
||||||
last = seg
|
last = seg
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -78,6 +86,64 @@ func (e *Editor) loadSegments() error {
|
||||||
return iErr
|
return iErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check and do the sorting
|
||||||
|
if sorting {
|
||||||
|
sort.Slice(segments, func(i, j int) bool {
|
||||||
|
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
|
||||||
|
for _, seg := range segments {
|
||||||
|
if err := seg.After(last); err != nil {
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
last = seg
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and padding the tailing segmnet
|
||||||
|
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: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
segments = nil // let GC do it work
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,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())
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue