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  }