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.

115 lines
4.1 KiB

  1. // Copyright 2009 The Go Authors. 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 flate
  5. import "fmt"
  6. const (
  7. // 2 bits: type 0 = literal 1=EOF 2=Match 3=Unused
  8. // 8 bits: xlength = length - MIN_MATCH_LENGTH
  9. // 22 bits xoffset = offset - MIN_OFFSET_SIZE, or literal
  10. lengthShift = 22
  11. offsetMask = 1<<lengthShift - 1
  12. typeMask = 3 << 30
  13. literalType = 0 << 30
  14. matchType = 1 << 30
  15. )
  16. // The length code for length X (MIN_MATCH_LENGTH <= X <= MAX_MATCH_LENGTH)
  17. // is lengthCodes[length - MIN_MATCH_LENGTH]
  18. var lengthCodes = [...]uint32{
  19. 0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
  20. 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
  21. 13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
  22. 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
  23. 17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
  24. 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
  25. 19, 19, 19, 19, 20, 20, 20, 20, 20, 20,
  26. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  27. 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
  28. 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
  29. 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
  30. 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
  31. 23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
  32. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  33. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  34. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  35. 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
  36. 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
  37. 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
  38. 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
  39. 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
  40. 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
  41. 26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
  42. 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
  43. 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
  44. 27, 27, 27, 27, 27, 28,
  45. }
  46. var offsetCodes = [...]uint32{
  47. 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
  48. 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
  49. 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
  50. 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  51. 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
  52. 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
  53. 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  54. 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  55. 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
  56. 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
  57. 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
  58. 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
  59. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  60. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  61. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  62. 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  63. }
  64. type token uint32
  65. type tokens struct {
  66. tokens [maxStoreBlockSize + 1]token
  67. n uint16 // Must be able to contain maxStoreBlockSize
  68. }
  69. // Convert a literal into a literal token.
  70. func literalToken(literal uint32) token { return token(literalType + literal) }
  71. // Convert a < xlength, xoffset > pair into a match token.
  72. func matchToken(xlength uint32, xoffset uint32) token {
  73. return token(matchType + xlength<<lengthShift + xoffset)
  74. }
  75. func matchTokend(xlength uint32, xoffset uint32) token {
  76. if xlength > maxMatchLength || xoffset > maxMatchOffset {
  77. panic(fmt.Sprintf("Invalid match: len: %d, offset: %d\n", xlength, xoffset))
  78. return token(matchType)
  79. }
  80. return token(matchType + xlength<<lengthShift + xoffset)
  81. }
  82. // Returns the type of a token
  83. func (t token) typ() uint32 { return uint32(t) & typeMask }
  84. // Returns the literal of a literal token
  85. func (t token) literal() uint32 { return uint32(t - literalType) }
  86. // Returns the extra offset of a match token
  87. func (t token) offset() uint32 { return uint32(t) & offsetMask }
  88. func (t token) length() uint32 { return uint32((t - matchType) >> lengthShift) }
  89. func lengthCode(len uint32) uint32 { return lengthCodes[len] }
  90. // Returns the offset code corresponding to a specific offset
  91. func offsetCode(off uint32) uint32 {
  92. if off < uint32(len(offsetCodes)) {
  93. return offsetCodes[off]
  94. } else if off>>7 < uint32(len(offsetCodes)) {
  95. return offsetCodes[off>>7] + 14
  96. } else {
  97. return offsetCodes[off>>14] + 28
  98. }
  99. }