github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/ranges/range.go (about) 1 package ranges 2 3 import ( 4 "sort" 5 6 "github.com/sagernet/sing/common/x/constraints" 7 ) 8 9 type Range[N comparable] struct { 10 Start N 11 End N 12 } 13 14 func New[N constraints.Integer](start N, end N) Range[N] { 15 return Range[N]{start, end} 16 } 17 18 func NewSingle[N constraints.Integer](index N) Range[N] { 19 return Range[N]{index, index} 20 } 21 22 func Merge[N constraints.Integer](ranges []Range[N]) (mergedRanges []Range[N]) { 23 if len(ranges) == 0 { 24 return 25 } 26 sort.Slice(ranges, func(i, j int) bool { 27 return ranges[i].Start < ranges[j].Start 28 }) 29 mergedRanges = ranges[:1] 30 var rangeIndex N 31 for _, r := range ranges[1:] { 32 if r.Start > mergedRanges[rangeIndex].End+1 { 33 mergedRanges = append(mergedRanges, r) 34 rangeIndex++ 35 } else if r.End > mergedRanges[rangeIndex].End { 36 mergedRanges[rangeIndex].End = r.End 37 } 38 } 39 return 40 } 41 42 func Revert[N constraints.Integer](start, end N, ranges []Range[N]) (revertedRanges []Range[N]) { 43 if len(ranges) == 0 { 44 return 45 } 46 ranges = Merge(ranges) 47 if ranges[0].Start > start { 48 revertedRanges = append(revertedRanges, Range[N]{start, ranges[0].Start - 1}) 49 } 50 rangeEnd := ranges[0].End 51 for _, r := range ranges[1:] { 52 if r.Start > rangeEnd+1 { 53 revertedRanges = append(revertedRanges, Range[N]{rangeEnd + 1, r.Start - 1}) 54 } 55 rangeEnd = r.End 56 } 57 if end > rangeEnd { 58 revertedRanges = append(revertedRanges, Range[N]{rangeEnd + 1, end}) 59 } 60 return 61 } 62 63 func Exclude[N constraints.Integer](ranges []Range[N], targetRanges []Range[N]) []Range[N] { 64 ranges = Merge(ranges) 65 if len(ranges) == 0 { 66 return nil 67 } 68 targetRanges = Merge(targetRanges) 69 if len(targetRanges) == 0 { 70 return ranges 71 } 72 var mergedRanges []Range[N] 73 rangeStart := ranges[0].Start 74 rangeEnd := ranges[0].End 75 rangeIndex := rangeStart 76 ranges = ranges[1:] 77 targetStart := targetRanges[0].Start 78 targetEnd := targetRanges[0].End 79 targetRanges = targetRanges[1:] 80 for { 81 if targetStart > rangeEnd { 82 if rangeIndex <= rangeEnd { 83 mergedRanges = append(mergedRanges, Range[N]{rangeIndex, rangeEnd}) 84 } 85 if len(ranges) == 0 { 86 break 87 } 88 rangeStart = ranges[0].Start 89 rangeEnd = ranges[0].End 90 rangeIndex = rangeStart 91 ranges = ranges[1:] 92 continue 93 } 94 if targetStart > rangeIndex { 95 mergedRanges = append(mergedRanges, Range[N]{rangeIndex, targetStart - 1}) 96 rangeIndex = targetStart + 1 97 } 98 if targetEnd <= rangeEnd { 99 rangeIndex = targetEnd + 1 100 if len(targetRanges) == 0 { 101 break 102 } 103 targetStart = targetRanges[0].Start 104 targetEnd = targetRanges[0].End 105 targetRanges = targetRanges[1:] 106 } 107 } 108 if rangeIndex <= rangeEnd { 109 mergedRanges = append(mergedRanges, Range[N]{rangeIndex, rangeEnd}) 110 } 111 return Merge(append(mergedRanges, ranges...)) 112 }