mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-05 01:20:26 +08:00
144 lines
3.0 KiB
Go
144 lines
3.0 KiB
Go
|
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||
|
|
|
||
|
|
package caches
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
)
|
||
|
|
|
||
|
|
// PartialRanges 内容分区范围定义
|
||
|
|
type PartialRanges struct {
|
||
|
|
ranges [][2]int64
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewPartialRanges 获取新对象
|
||
|
|
func NewPartialRanges() *PartialRanges {
|
||
|
|
return &PartialRanges{ranges: [][2]int64{}}
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewPartialRangesFromJSON 从JSON中解析范围
|
||
|
|
func NewPartialRangesFromJSON(data []byte) (*PartialRanges, error) {
|
||
|
|
var rs = [][2]int64{}
|
||
|
|
err := json.Unmarshal(data, &rs)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
var r = NewPartialRanges()
|
||
|
|
r.ranges = rs
|
||
|
|
return r, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add 添加新范围
|
||
|
|
func (this *PartialRanges) Add(begin int64, end int64) {
|
||
|
|
if begin > end {
|
||
|
|
begin, end = end, begin
|
||
|
|
}
|
||
|
|
|
||
|
|
var nr = [2]int64{begin, end}
|
||
|
|
|
||
|
|
var count = len(this.ranges)
|
||
|
|
if count == 0 {
|
||
|
|
this.ranges = [][2]int64{nr}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// insert
|
||
|
|
// TODO 将来使用二分法改进
|
||
|
|
var index = -1
|
||
|
|
for i, r := range this.ranges {
|
||
|
|
if r[0] > begin || (r[0] == begin && r[1] >= end) {
|
||
|
|
index = i
|
||
|
|
this.ranges = append(this.ranges, [2]int64{})
|
||
|
|
copy(this.ranges[index+1:], this.ranges[index:])
|
||
|
|
this.ranges[index] = nr
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if index == -1 {
|
||
|
|
index = count
|
||
|
|
this.ranges = append(this.ranges, nr)
|
||
|
|
}
|
||
|
|
|
||
|
|
this.merge(index)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Ranges 获取所有范围
|
||
|
|
func (this *PartialRanges) Ranges() [][2]int64 {
|
||
|
|
return this.ranges
|
||
|
|
}
|
||
|
|
|
||
|
|
// Contains 检查是否包含某个范围
|
||
|
|
func (this *PartialRanges) Contains(begin int64, end int64) bool {
|
||
|
|
if len(this.ranges) == 0 {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO 使用二分法查找改进性能
|
||
|
|
for _, r2 := range this.ranges {
|
||
|
|
if r2[0] <= begin && r2[1] >= end {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
// AsJSON 转换为JSON
|
||
|
|
func (this *PartialRanges) AsJSON() ([]byte, error) {
|
||
|
|
return json.Marshal(this.ranges)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (this *PartialRanges) merge(index int) {
|
||
|
|
// forward
|
||
|
|
var lastIndex = index
|
||
|
|
for i := index; i >= 1; i-- {
|
||
|
|
var curr = this.ranges[i]
|
||
|
|
var prev = this.ranges[i-1]
|
||
|
|
var w1 = this.w(curr)
|
||
|
|
var w2 = this.w(prev)
|
||
|
|
if w1+w2 >= this.max(curr[1], prev[1])-this.min(curr[0], prev[0])-1 {
|
||
|
|
prev = [2]int64{this.min(curr[0], prev[0]), this.max(curr[1], prev[1])}
|
||
|
|
this.ranges[i-1] = prev
|
||
|
|
this.ranges = append(this.ranges[:i], this.ranges[i+1:]...)
|
||
|
|
lastIndex = i - 1
|
||
|
|
} else {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// backward
|
||
|
|
index = lastIndex
|
||
|
|
for index < len(this.ranges)-1 {
|
||
|
|
var curr = this.ranges[index]
|
||
|
|
var next = this.ranges[index+1]
|
||
|
|
var w1 = this.w(curr)
|
||
|
|
var w2 = this.w(next)
|
||
|
|
if w1+w2 >= this.max(curr[1], next[1])-this.min(curr[0], next[0])-1 {
|
||
|
|
curr = [2]int64{this.min(curr[0], next[0]), this.max(curr[1], next[1])}
|
||
|
|
this.ranges = append(this.ranges[:index], this.ranges[index+1:]...)
|
||
|
|
this.ranges[index] = curr
|
||
|
|
} else {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (this *PartialRanges) w(r [2]int64) int64 {
|
||
|
|
return r[1] - r[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
func (this *PartialRanges) min(n1 int64, n2 int64) int64 {
|
||
|
|
if n1 <= n2 {
|
||
|
|
return n1
|
||
|
|
}
|
||
|
|
return n2
|
||
|
|
}
|
||
|
|
|
||
|
|
func (this *PartialRanges) max(n1 int64, n2 int64) int64 {
|
||
|
|
if n1 >= n2 {
|
||
|
|
return n1
|
||
|
|
}
|
||
|
|
return n2
|
||
|
|
}
|