state.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2014-2022 Ulrich Kunitz. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package lzma
  5. // states defines the overall state count
  6. const states = 12
  7. // State maintains the full state of the operation encoding or decoding
  8. // process.
  9. type state struct {
  10. rep [4]uint32
  11. isMatch [states << maxPosBits]prob
  12. isRepG0Long [states << maxPosBits]prob
  13. isRep [states]prob
  14. isRepG0 [states]prob
  15. isRepG1 [states]prob
  16. isRepG2 [states]prob
  17. litCodec literalCodec
  18. lenCodec lengthCodec
  19. repLenCodec lengthCodec
  20. distCodec distCodec
  21. state uint32
  22. posBitMask uint32
  23. Properties Properties
  24. }
  25. // initProbSlice initializes a slice of probabilities.
  26. func initProbSlice(p []prob) {
  27. for i := range p {
  28. p[i] = probInit
  29. }
  30. }
  31. // Reset sets all state information to the original values.
  32. func (s *state) Reset() {
  33. p := s.Properties
  34. *s = state{
  35. Properties: p,
  36. // dict: s.dict,
  37. posBitMask: (uint32(1) << uint(p.PB)) - 1,
  38. }
  39. initProbSlice(s.isMatch[:])
  40. initProbSlice(s.isRep[:])
  41. initProbSlice(s.isRepG0[:])
  42. initProbSlice(s.isRepG1[:])
  43. initProbSlice(s.isRepG2[:])
  44. initProbSlice(s.isRepG0Long[:])
  45. s.litCodec.init(p.LC, p.LP)
  46. s.lenCodec.init()
  47. s.repLenCodec.init()
  48. s.distCodec.init()
  49. }
  50. // newState creates a new state from the give Properties.
  51. func newState(p Properties) *state {
  52. s := &state{Properties: p}
  53. s.Reset()
  54. return s
  55. }
  56. // deepcopy initializes s as a deep copy of the source.
  57. func (s *state) deepcopy(src *state) {
  58. if s == src {
  59. return
  60. }
  61. s.rep = src.rep
  62. s.isMatch = src.isMatch
  63. s.isRepG0Long = src.isRepG0Long
  64. s.isRep = src.isRep
  65. s.isRepG0 = src.isRepG0
  66. s.isRepG1 = src.isRepG1
  67. s.isRepG2 = src.isRepG2
  68. s.litCodec.deepcopy(&src.litCodec)
  69. s.lenCodec.deepcopy(&src.lenCodec)
  70. s.repLenCodec.deepcopy(&src.repLenCodec)
  71. s.distCodec.deepcopy(&src.distCodec)
  72. s.state = src.state
  73. s.posBitMask = src.posBitMask
  74. s.Properties = src.Properties
  75. }
  76. // cloneState creates a new clone of the give state.
  77. func cloneState(src *state) *state {
  78. s := new(state)
  79. s.deepcopy(src)
  80. return s
  81. }
  82. // updateStateLiteral updates the state for a literal.
  83. func (s *state) updateStateLiteral() {
  84. switch {
  85. case s.state < 4:
  86. s.state = 0
  87. return
  88. case s.state < 10:
  89. s.state -= 3
  90. return
  91. }
  92. s.state -= 6
  93. }
  94. // updateStateMatch updates the state for a match.
  95. func (s *state) updateStateMatch() {
  96. if s.state < 7 {
  97. s.state = 7
  98. } else {
  99. s.state = 10
  100. }
  101. }
  102. // updateStateRep updates the state for a repetition.
  103. func (s *state) updateStateRep() {
  104. if s.state < 7 {
  105. s.state = 8
  106. } else {
  107. s.state = 11
  108. }
  109. }
  110. // updateStateShortRep updates the state for a short repetition.
  111. func (s *state) updateStateShortRep() {
  112. if s.state < 7 {
  113. s.state = 9
  114. } else {
  115. s.state = 11
  116. }
  117. }
  118. // states computes the states of the operation codec.
  119. func (s *state) states(dictHead int64) (state1, state2, posState uint32) {
  120. state1 = s.state
  121. posState = uint32(dictHead) & s.posBitMask
  122. state2 = (s.state << maxPosBits) | posState
  123. return
  124. }
  125. // litState computes the literal state.
  126. func (s *state) litState(prev byte, dictHead int64) uint32 {
  127. lp, lc := uint(s.Properties.LP), uint(s.Properties.LC)
  128. litState := ((uint32(dictHead) & ((1 << lp) - 1)) << lc) |
  129. (uint32(prev) >> (8 - lc))
  130. return litState
  131. }