You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
2.6 KiB
145 lines
2.6 KiB
package enc
|
|
|
|
import (
|
|
"gordenko.dev/dima/diploma/bin"
|
|
)
|
|
|
|
// REVERSE
|
|
|
|
const (
|
|
lastUnixtimeIdx = 0
|
|
baseDeltaIdx = 4
|
|
)
|
|
|
|
type ReverseTimeDeltaOfDeltaDecompressor struct {
|
|
step byte
|
|
buf []byte
|
|
pos int
|
|
bound int
|
|
lastUnixtime uint32
|
|
baseDelta uint32
|
|
lastDeltaOfDelta int64
|
|
length uint16
|
|
idxOf8 uint
|
|
s8 byte
|
|
}
|
|
|
|
func NewReverseTimeDeltaOfDeltaDecompressor(buf []byte) *ReverseTimeDeltaOfDeltaDecompressor {
|
|
return &ReverseTimeDeltaOfDeltaDecompressor{
|
|
buf: buf,
|
|
pos: len(buf),
|
|
}
|
|
}
|
|
|
|
func (s *ReverseTimeDeltaOfDeltaDecompressor) NextValue() (value uint32, done bool) {
|
|
if s.step == 0 {
|
|
if s.pos == 0 {
|
|
return 0, true
|
|
}
|
|
s.lastUnixtime = bin.GetUint32(s.buf[lastUnixtimeIdx:])
|
|
s.step = 1
|
|
return s.lastUnixtime, false
|
|
}
|
|
|
|
if s.step == 1 {
|
|
if s.pos == baseDeltaIdx {
|
|
return 0, true
|
|
}
|
|
u64, n, err := bin.GetVarUint64(s.buf[baseDeltaIdx:])
|
|
if err != nil {
|
|
panic("EOF")
|
|
}
|
|
s.bound = baseDeltaIdx + n
|
|
s.baseDelta = uint32(u64)
|
|
|
|
s.pos--
|
|
s.idxOf8 = uint(8 - s.buf[s.pos])
|
|
s.pos--
|
|
s.s8 = s.buf[s.pos]
|
|
s.pos--
|
|
|
|
s.readVar()
|
|
if s.length > 0 {
|
|
s.length--
|
|
}
|
|
s.step = 2
|
|
return s.lastUnixtime, false
|
|
}
|
|
|
|
if s.length > 0 {
|
|
s.length--
|
|
delta := int64(s.baseDelta) + s.lastDeltaOfDelta
|
|
s.lastUnixtime = uint32(int64(s.lastUnixtime) - delta)
|
|
return s.lastUnixtime, false
|
|
}
|
|
|
|
if s.pos < s.bound {
|
|
return 0, true
|
|
}
|
|
if s.idxOf8 == 0 {
|
|
s.s8 = s.buf[s.pos]
|
|
s.pos--
|
|
}
|
|
s.readVar()
|
|
if s.length > 0 {
|
|
s.length--
|
|
}
|
|
return s.lastUnixtime, false
|
|
}
|
|
|
|
func GetTimeRange(timestampsBuf []byte) (since, until uint32) {
|
|
decompressor := NewReverseTimeDeltaOfDeltaDecompressor(timestampsBuf)
|
|
value, done := decompressor.NextValue()
|
|
if done {
|
|
return
|
|
}
|
|
|
|
since = value
|
|
until = value
|
|
for {
|
|
value, done = decompressor.NextValue()
|
|
if done {
|
|
return
|
|
}
|
|
since = value
|
|
}
|
|
}
|
|
|
|
func (s *ReverseTimeDeltaOfDeltaDecompressor) readVar() {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
|
|
s.lastDeltaOfDelta, n, err = bin.ReverseGetVarInt64(s.buf[:s.pos+1])
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
s.pos -= n
|
|
|
|
delta := int64(s.baseDelta) + s.lastDeltaOfDelta
|
|
s.lastUnixtime = uint32(int64(s.lastUnixtime) - delta)
|
|
|
|
var flag byte = 1 << s.idxOf8
|
|
if (s.s8 & flag) == flag {
|
|
s.decodeLength()
|
|
}
|
|
if s.idxOf8 == 7 {
|
|
s.idxOf8 = 0
|
|
} else {
|
|
s.idxOf8++
|
|
}
|
|
}
|
|
|
|
func (s *ReverseTimeDeltaOfDeltaDecompressor) decodeLength() {
|
|
b1 := s.buf[s.pos]
|
|
s.pos--
|
|
if b1 < 128 {
|
|
s.length = uint16(b1)
|
|
} else {
|
|
b2 := s.buf[s.pos]
|
|
s.pos--
|
|
s.length = uint16(b1&127) | (uint16(b2) << 7)
|
|
}
|
|
s.length += 2
|
|
}
|
|
|