| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // package packer -- упаковщик данных
- package packer
- import (
- "fmt"
- "log"
- "math"
- "os"
- "time"
- "p78git.ddns.net/svi/packer/internal/packer/dict_keys"
- "p78git.ddns.net/svi/packer/internal/packer/freq_pair"
- "p78git.ddns.net/svi/packer/internal/packer/frequencer"
- "p78git.ddns.net/svi/packer/pkg/types"
- )
- // Packer -- упаковщик сервиса
- type Packer struct {
- serv types.IService
- dictKeys types.IDictKeys // Словарь ключей
- freqPair *freq_pair.FreqPair // Частотная пара
- frequencer types.IFrequencer // Подбор частотной пары
- binData []uint16 // То, что останется после замен
- timeTotal float32 // Общее время в сек
- totalChange int // Общее число замен
- originSize int // Оригинальный размер
- binNew []uint16 // Буфер новых данных
- }
- // NewPacker -- возвращает ноый пакер
- func NewPacker(serv types.IService) (*Packer, error) {
- if serv == nil {
- return nil, fmt.Errorf("NewPacker(): IService==nil")
- }
- sf := &Packer{
- serv: serv,
- dictKeys: dict_keys.NewDictKeys(),
- freqPair: &freq_pair.FreqPair{},
- binData: []uint16{},
- binNew: []uint16{0, 0, 0},
- }
- var err error
- sf.frequencer, err = frequencer.NewFrequencer(sf)
- if err != nil {
- return nil, fmt.Errorf("NewPacker(): in create IFrequencer, err=\n\t%w", err)
- }
- _ = types.IPacker(sf)
- return sf, nil
- }
- // Run -- запускает упаковку
- func (sf *Packer) Run() error {
- log.Printf("Packer.Run()\n")
- { // Чтение файла
- fileName := os.Getenv("PACK_FILE")
- if fileName == "" {
- return fmt.Errorf("Packer.Run(): env PACK_FILE not set")
- }
- binData, err := os.ReadFile(fileName)
- if err != nil {
- return fmt.Errorf("Packer.Run(): in read %q, err=\n\t%w", fileName, err)
- }
- sf.originSize = len(binData)
- for _, val := range binData {
- sf.binData = append(sf.binData, uint16(val))
- }
- log.Printf("Packer.Run(): len(%q)=%v\n", fileName, len(sf.binData))
- }
- round := 1
- for { // Главный цикл сжатия
- log.Printf("Packer.Run(): round=%v, lenDict=%v\n", round, sf.dictKeys.Len())
- if !sf.round() {
- break
- }
- round++
- }
- return nil
- }
- // Serv -- возвращает сервис
- func (sf *Packer) Serv() types.IService {
- return sf.serv
- }
- // BinData -- возвращает бинарны данные для упаковки
- func (sf *Packer) BinData() []uint16 {
- return sf.binData
- }
- // DictKeys -- возвращает словарь ключей для подстановки
- func (sf *Packer) DictKeys() types.IDictKeys {
- return sf.dictKeys
- }
- // Выполняет раунд сжатия
- func (sf *Packer) round() bool {
- timeBeg := time.Now().Local().UnixMilli()
- defer func() {
- timeEnd := time.Now().Local().UnixMilli()
- timeDelta := float32(timeEnd-timeBeg) / 1000
- sf.timeTotal += timeDelta
- ratio := (float32(len(sf.binData)) - float32(sf.originSize)) / float32(sf.originSize) * 100
- log.Printf("Packer.Round(): timeTotal=%0.2fsec, timeRound=%0.2fsec, ration=%0.2f%%, totalChange=%v\n\n",
- sf.timeTotal,
- timeDelta,
- ratio,
- sf.totalChange)
- }()
- sf.dictUp()
- if err := sf.frequencer.Run(); err != nil {
- log.Printf("Packer.round(): in work IFrequencer, err=\n\t%v\n", err)
- return false
- }
- sf.freqPair.SetKeys(sf.frequencer.Keys())
- keyNext, err := sf.keyNext()
- if err != nil {
- log.Printf("Packer.round(): limit keys, err=\n\t%v\n", err)
- return false
- }
- sf.changeKey(keyNext)
- return true
- }
- // Заменяет частотную пару на указанный ключ
- func (sf *Packer) changeKey(key uint16) {
- sf.binNew = sf.binNew[:0]
- val0 := sf.binData[0]
- ind := 1
- val1 := sf.binData[ind]
- fnNext := func() bool { // вычисляет сдвиг после замены
- sf.binNew = append(sf.binNew, key)
- if ind+1 >= len(sf.binData) { // Достигнут предел прохода
- return false
- }
- ind++
- val0 = sf.binData[ind]
- if ind+1 >= len(sf.binData) { // Достигнут предел прохода
- return false
- }
- ind++
- val1 = sf.binData[ind]
- return true
- }
- key0 := sf.freqPair.Key0_
- key1 := sf.freqPair.Key1_
- for ind < len(sf.binData) {
- val1 = sf.binData[ind]
- if val0 == key0 && val1 == key1 {
- fnNext()
- continue
- }
- sf.binNew = append(sf.binNew, val0)
- val0 = val1
- ind++
- }
- countChange := len(sf.binData) - len(sf.binNew)
- sf.totalChange += countChange
- log.Printf("Packer.changeKey(): len{old=%v, new=%v}, numChange=%v\n",
- len(sf.binData),
- len(sf.binNew),
- countChange)
- sf.binData = sf.binNew
- }
- // Ищёт следующий свободный ключ
- func (sf *Packer) keyNext() (uint16, error) {
- key := uint16(0)
- for {
- if !sf.dictKeys.IsExists(key) {
- return key, nil
- }
- key++
- if key == math.MaxUint16 {
- return 0, fmt.Errorf("Packer.keyNext(): key up to limit uint32")
- }
- }
- }
- // Собирает словарь ключей из текста
- func (sf *Packer) dictUp() {
- // Собрать встречающиеся ключи
- for _, val := range sf.binData {
- if !sf.dictKeys.IsExists(val) {
- sf.dictKeys.Add(val)
- continue
- }
- }
- }
|