спеціалізована СУБД для зберігання та обробки показань датчиків та лічильників
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.
 
 
diploma/enc/cumdelta.go

102 lines
1.8 KiB

package enc
import (
"math"
"gordenko.dev/dima/diploma/bin"
)
type ReverseCumulativeDeltaDecompressor struct {
buf []byte
pos int
bound int
firstValue float64
lastValue float64
length uint16
coef float64
idxOf8 uint
s8 byte
}
func NewReverseCumulativeDeltaDecompressor(buf []byte, fracDigits byte) *ReverseCumulativeDeltaDecompressor {
var coef float64 = 1
if fracDigits > 0 {
coef = math.Pow(10, float64(fracDigits))
}
return &ReverseCumulativeDeltaDecompressor{
buf: buf,
coef: coef,
pos: len(buf),
}
}
func (s *ReverseCumulativeDeltaDecompressor) NextValue() (value float64, done bool) {
if s.length > 0 {
s.length--
return s.lastValue, false
}
if s.pos < s.bound {
return 0, true
}
if s.pos == len(s.buf) {
u64, n, err := bin.GetVarUint64(s.buf)
if err != nil {
panic(err)
}
s.firstValue = float64(u64) / s.coef
s.bound = n
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--
}
return s.lastValue, false
}
if s.idxOf8 == 0 {
s.s8 = s.buf[s.pos]
s.pos--
}
s.readVar()
if s.length > 0 {
s.length--
}
return s.lastValue, false
}
func (s *ReverseCumulativeDeltaDecompressor) readVar() {
u64, n, err := bin.ReverseGetVarUint64(s.buf[:s.pos+1])
if err != nil {
panic(err)
}
s.pos -= n
s.lastValue = s.firstValue + float64(u64)/s.coef
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 *ReverseCumulativeDeltaDecompressor) 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
}