This commit is contained in:
h4nz4
2026-03-12 20:09:16 +01:00
commit f9b7eaa20d
23 changed files with 1481 additions and 0 deletions

125
internal/statuslist/list.go Normal file
View File

@@ -0,0 +1,125 @@
package statuslist
import (
"bytes"
"compress/gzip"
"encoding/base64"
"errors"
)
var (
ErrIndexOutOfRange = errors.New("index out of range")
)
type StatusList struct {
data []byte
bitLength int
}
// New vrne prazno bitno listo statusov.
func New() *StatusList {
return &StatusList{
data: make([]byte, 0),
bitLength: 0,
}
}
// IzSurovihPodatkov zgradi listo iz bajtov in dolzine v bitih.
func IzSurovihPodatkov(data []byte, bitLength int) (*StatusList, error) {
if bitLength < 0 {
return nil, errors.New("bitLength must be >= 0")
}
minBytes := steviloBajtovZaBite(bitLength)
if len(data) < minBytes {
return nil, errors.New("invalid data size for bitLength")
}
cloned := make([]byte, minBytes)
copy(cloned, data[:minBytes])
return &StatusList{data: cloned, bitLength: bitLength}, nil
}
// Dodaj doda novo stanje in vrne njegov index.
func (s *StatusList) Dodaj(value bool) int {
index := s.bitLength
s.zagotoviIndex(index)
s.nastaviBit(index, value)
s.bitLength++
return index
}
// Nastavi spremeni obstojece stanje na podanem indexu.
func (s *StatusList) Nastavi(index int, value bool) error {
if index < 0 || index >= s.bitLength {
return ErrIndexOutOfRange
}
s.nastaviBit(index, value)
return nil
}
// Dobi vrne stanje na podanem indexu.
func (s *StatusList) Dobi(index int) (bool, error) {
if index < 0 || index >= s.bitLength {
return false, ErrIndexOutOfRange
}
return s.dobiBit(index), nil
}
// DolzinaBitov vrne stevilo aktivnih statusov.
func (s *StatusList) DolzinaBitov() int {
return s.bitLength
}
// Bajti vrne kopijo notranjih bajtov liste.
func (s *StatusList) Bajti() []byte {
out := make([]byte, len(s.data))
copy(out, s.data)
return out
}
// KodiranSeznam vrne base64(gzip(byteArray)) predstavitev liste.
func (s *StatusList) KodiranSeznam() (string, error) {
var buf bytes.Buffer
zip := gzip.NewWriter(&buf)
if _, err := zip.Write(s.data); err != nil {
return "", err
}
if err := zip.Close(); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(buf.Bytes()), nil
}
// zagotoviIndex razsiri notranji buffer za podani index.
func (s *StatusList) zagotoviIndex(index int) {
required := steviloBajtovZaBite(index + 1)
for len(s.data) < required {
s.data = append(s.data, 0)
}
}
// nastaviBit vklopi ali izklopi bit na podanem indexu.
func (s *StatusList) nastaviBit(index int, value bool) {
byteIdx := index / 8
mask := byte(1 << (index % 8))
if value {
s.data[byteIdx] |= mask
return
}
s.data[byteIdx] &^= mask
}
// dobiBit prebere bit na podanem indexu.
func (s *StatusList) dobiBit(index int) bool {
byteIdx := index / 8
mask := byte(1 << (index % 8))
return s.data[byteIdx]&mask != 0
}
// steviloBajtovZaBite izracuna koliko bajtov potrebujemo za bite.
func steviloBajtovZaBite(bitLength int) int {
if bitLength == 0 {
return 0
}
return (bitLength + 7) / 8
}