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"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Editor struct {
|
||||
|
|
@ -56,6 +57,8 @@ func NewEditor(version *Version, srcFile string) (*Editor, error) {
|
|||
// Load all the segments from the source file
|
||||
func (e *Editor) loadSegments() error {
|
||||
var last *Segment = nil
|
||||
var segments []*Segment
|
||||
var sorting = false
|
||||
|
||||
var iErr = IterateSegments(e.srcHandle, func(l string) {
|
||||
// do nothing here
|
||||
|
|
@ -65,12 +68,17 @@ func (e *Editor) loadSegments() error {
|
|||
return fmt.Errorf("invalid ip segment(%s expected)", e.verison.Name)
|
||||
}
|
||||
|
||||
// check the continuity of the data segment
|
||||
if err := seg.RightBehind(last); err != nil {
|
||||
return err
|
||||
// check the order of the data segment
|
||||
// if err := seg.RightBehind(last); err != nil {
|
||||
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
|
||||
return nil
|
||||
})
|
||||
|
|
@ -78,6 +86,64 @@ func (e *Editor) loadSegments() error {
|
|||
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
|
||||
}
|
||||
|
||||
|
|
@ -138,21 +204,24 @@ func (e *Editor) Put(ip string) (int, int, error) {
|
|||
func (e *Editor) PutSegment(seg *Segment) (int, int, error) {
|
||||
var next *list.Element
|
||||
var eList []*list.Element
|
||||
var found = false
|
||||
var found, counter = false, 0
|
||||
for ele := e.segments.Front(); ele != nil; ele = next {
|
||||
next = ele.Next()
|
||||
s, ok := ele.Value.(*Segment)
|
||||
if !ok {
|
||||
// could this even be a case ?
|
||||
continue
|
||||
return 0, 0, fmt.Errorf("type error: ele not a Segment ptr")
|
||||
}
|
||||
|
||||
counter++
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
if !found {
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -164,8 +233,6 @@ func (e *Editor) PutSegment(seg *Segment) (int, int, error) {
|
|||
|
||||
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 0, 0, fmt.Errorf("failed to find the related segment")
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +342,11 @@ func (e *Editor) Save() error {
|
|||
continue
|
||||
}
|
||||
|
||||
// ignore the padded or empty segment
|
||||
if s.Region == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// var l = s.String()
|
||||
// _, err = dstHandle.WriteString(fmt.Sprintf("%s\n", l))
|
||||
_, err = fmt.Fprintln(dstHandle, s.String())
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ type Version struct {
|
|||
|
||||
// ip compares
|
||||
IPCompare func([]byte, []byte) int
|
||||
|
||||
Min []byte
|
||||
Max []byte
|
||||
}
|
||||
|
||||
func (v *Version) String() string {
|
||||
|
|
@ -55,6 +58,8 @@ var (
|
|||
ip2[1], ip2[2] = ip2[2], ip2[1]
|
||||
return bytes.Compare(ip1, ip2)
|
||||
},
|
||||
Min: []byte{0x00, 0x00, 0x00, 0x00},
|
||||
Max: []byte{0xff, 0xff, 0xff, 0xff},
|
||||
}
|
||||
IPv6 = &Version{
|
||||
Id: 6,
|
||||
|
|
@ -68,6 +73,18 @@ var (
|
|||
IPCompare: func(ip1, ip2 []byte) int {
|
||||
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