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

130 lines
2.5 KiB

package enc
import (
"fmt"
"math"
octopus "gordenko.dev/dima/diploma"
"gordenko.dev/dima/diploma/bin"
)
type ReverseInstantDeltaDecompressor struct {
buf []byte
pos int
bound int
firstValue float64
lastValue float64
length uint16
coef float64
idxOf8 uint
s8 byte
}
func NewReverseInstantDeltaDecompressor(buf []byte, fracDigits byte) *ReverseInstantDeltaDecompressor {
var coef float64 = 1
if fracDigits > 0 {
coef = math.Pow(10, float64(fracDigits))
}
return &ReverseInstantDeltaDecompressor{
buf: buf,
coef: coef,
pos: len(buf),
}
}
func (s *ReverseInstantDeltaDecompressor) 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.GetVarInt64(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 *ReverseInstantDeltaDecompressor) readVar() {
i64, n, err := bin.ReverseGetVarInt64(s.buf[:s.pos+1])
if err != nil {
panic(err)
}
s.pos -= n
s.lastValue = s.firstValue + float64(i64)/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 *ReverseInstantDeltaDecompressor) 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
}
func GetValueBounds(valuesBuf []byte, metricType octopus.MetricType, fracDigits byte) (sinceValue, untilValue float64) {
var decompressor octopus.ValueDecompressor
switch metricType {
case octopus.Instant:
decompressor = NewReverseInstantDeltaDecompressor(valuesBuf, fracDigits)
case octopus.Cumulative:
decompressor = NewReverseCumulativeDeltaDecompressor(valuesBuf, fracDigits)
default:
panic(fmt.Sprintf("unknown metricType %d", metricType))
}
value, done := decompressor.NextValue()
if done {
return
}
sinceValue = value
untilValue = value
for {
value, done = decompressor.NextValue()
if done {
return
}
sinceValue = value
}
}