packer.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // package packer -- упаковщик данных
  2. package packer
  3. import (
  4. "fmt"
  5. "log"
  6. "math"
  7. "os"
  8. "time"
  9. "p78git.ddns.net/svi/packer/internal/packer/dict_keys"
  10. "p78git.ddns.net/svi/packer/internal/packer/freq_pair"
  11. "p78git.ddns.net/svi/packer/internal/packer/frequencer"
  12. "p78git.ddns.net/svi/packer/pkg/types"
  13. )
  14. // Packer -- упаковщик сервиса
  15. type Packer struct {
  16. serv types.IService
  17. dictKeys types.IDictKeys // Словарь ключей
  18. freqPair *freq_pair.FreqPair // Частотная пара
  19. frequencer types.IFrequencer // Подбор частотной пары
  20. binData []uint16 // То, что останется после замен
  21. timeTotal float32 // Общее время в сек
  22. totalChange int // Общее число замен
  23. originSize int // Оригинальный размер
  24. binNew []uint16 // Буфер новых данных
  25. }
  26. // NewPacker -- возвращает ноый пакер
  27. func NewPacker(serv types.IService) (*Packer, error) {
  28. if serv == nil {
  29. return nil, fmt.Errorf("NewPacker(): IService==nil")
  30. }
  31. sf := &Packer{
  32. serv: serv,
  33. dictKeys: dict_keys.NewDictKeys(),
  34. freqPair: &freq_pair.FreqPair{},
  35. binData: []uint16{},
  36. binNew: []uint16{0, 0, 0},
  37. }
  38. var err error
  39. sf.frequencer, err = frequencer.NewFrequencer(sf)
  40. if err != nil {
  41. return nil, fmt.Errorf("NewPacker(): in create IFrequencer, err=\n\t%w", err)
  42. }
  43. _ = types.IPacker(sf)
  44. return sf, nil
  45. }
  46. // Run -- запускает упаковку
  47. func (sf *Packer) Run() error {
  48. log.Printf("Packer.Run()\n")
  49. { // Чтение файла
  50. fileName := os.Getenv("PACK_FILE")
  51. if fileName == "" {
  52. return fmt.Errorf("Packer.Run(): env PACK_FILE not set")
  53. }
  54. binData, err := os.ReadFile(fileName)
  55. if err != nil {
  56. return fmt.Errorf("Packer.Run(): in read %q, err=\n\t%w", fileName, err)
  57. }
  58. sf.originSize = len(binData)
  59. for _, val := range binData {
  60. sf.binData = append(sf.binData, uint16(val))
  61. }
  62. log.Printf("Packer.Run(): len(%q)=%v\n", fileName, len(sf.binData))
  63. }
  64. round := 1
  65. for { // Главный цикл сжатия
  66. log.Printf("Packer.Run(): round=%v, lenDict=%v\n", round, sf.dictKeys.Len())
  67. if !sf.round() {
  68. break
  69. }
  70. round++
  71. }
  72. return nil
  73. }
  74. // Serv -- возвращает сервис
  75. func (sf *Packer) Serv() types.IService {
  76. return sf.serv
  77. }
  78. // BinData -- возвращает бинарны данные для упаковки
  79. func (sf *Packer) BinData() []uint16 {
  80. return sf.binData
  81. }
  82. // DictKeys -- возвращает словарь ключей для подстановки
  83. func (sf *Packer) DictKeys() types.IDictKeys {
  84. return sf.dictKeys
  85. }
  86. // Выполняет раунд сжатия
  87. func (sf *Packer) round() bool {
  88. timeBeg := time.Now().Local().UnixMilli()
  89. defer func() {
  90. timeEnd := time.Now().Local().UnixMilli()
  91. timeDelta := float32(timeEnd-timeBeg) / 1000
  92. sf.timeTotal += timeDelta
  93. ratio := (float32(len(sf.binData)) - float32(sf.originSize)) / float32(sf.originSize) * 100
  94. log.Printf("Packer.Round(): timeTotal=%0.2fsec, timeRound=%0.2fsec, ration=%0.2f%%, totalChange=%v\n\n",
  95. sf.timeTotal,
  96. timeDelta,
  97. ratio,
  98. sf.totalChange)
  99. }()
  100. sf.dictUp()
  101. if err := sf.frequencer.Run(); err != nil {
  102. log.Printf("Packer.round(): in work IFrequencer, err=\n\t%v\n", err)
  103. return false
  104. }
  105. sf.freqPair.SetKeys(sf.frequencer.Keys())
  106. keyNext, err := sf.keyNext()
  107. if err != nil {
  108. log.Printf("Packer.round(): limit keys, err=\n\t%v\n", err)
  109. return false
  110. }
  111. sf.changeKey(keyNext)
  112. return true
  113. }
  114. // Заменяет частотную пару на указанный ключ
  115. func (sf *Packer) changeKey(key uint16) {
  116. sf.binNew = sf.binNew[:0]
  117. val0 := sf.binData[0]
  118. ind := 1
  119. val1 := sf.binData[ind]
  120. fnNext := func() bool { // вычисляет сдвиг после замены
  121. sf.binNew = append(sf.binNew, key)
  122. if ind+1 >= len(sf.binData) { // Достигнут предел прохода
  123. return false
  124. }
  125. ind++
  126. val0 = sf.binData[ind]
  127. if ind+1 >= len(sf.binData) { // Достигнут предел прохода
  128. return false
  129. }
  130. ind++
  131. val1 = sf.binData[ind]
  132. return true
  133. }
  134. key0 := sf.freqPair.Key0_
  135. key1 := sf.freqPair.Key1_
  136. for ind < len(sf.binData) {
  137. val1 = sf.binData[ind]
  138. if val0 == key0 && val1 == key1 {
  139. fnNext()
  140. continue
  141. }
  142. sf.binNew = append(sf.binNew, val0)
  143. val0 = val1
  144. ind++
  145. }
  146. countChange := len(sf.binData) - len(sf.binNew)
  147. sf.totalChange += countChange
  148. log.Printf("Packer.changeKey(): len{old=%v, new=%v}, numChange=%v\n",
  149. len(sf.binData),
  150. len(sf.binNew),
  151. countChange)
  152. sf.binData = sf.binNew
  153. }
  154. // Ищёт следующий свободный ключ
  155. func (sf *Packer) keyNext() (uint16, error) {
  156. key := uint16(0)
  157. for {
  158. if !sf.dictKeys.IsExists(key) {
  159. return key, nil
  160. }
  161. key++
  162. if key == math.MaxUint16 {
  163. return 0, fmt.Errorf("Packer.keyNext(): key up to limit uint32")
  164. }
  165. }
  166. }
  167. // Собирает словарь ключей из текста
  168. func (sf *Packer) dictUp() {
  169. // Собрать встречающиеся ключи
  170. for _, val := range sf.binData {
  171. if !sf.dictKeys.IsExists(val) {
  172. sf.dictKeys.Add(val)
  173. continue
  174. }
  175. }
  176. }