deflate.go 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Copyright (c) 2015 Klaus Post
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package flate
  6. import (
  7. "fmt"
  8. "io"
  9. "math"
  10. )
  11. const (
  12. NoCompression = 0
  13. BestSpeed = 1
  14. BestCompression = 9
  15. DefaultCompression = -1
  16. // HuffmanOnly disables Lempel-Ziv match searching and only performs Huffman
  17. // entropy encoding. This mode is useful in compressing data that has
  18. // already been compressed with an LZ style algorithm (e.g. Snappy or LZ4)
  19. // that lacks an entropy encoder. Compression gains are achieved when
  20. // certain bytes in the input stream occur more frequently than others.
  21. //
  22. // Note that HuffmanOnly produces a compressed output that is
  23. // RFC 1951 compliant. That is, any valid DEFLATE decompressor will
  24. // continue to be able to decompress this output.
  25. HuffmanOnly = -2
  26. ConstantCompression = HuffmanOnly // compatibility alias.
  27. logWindowSize = 15
  28. windowSize = 1 << logWindowSize
  29. windowMask = windowSize - 1
  30. logMaxOffsetSize = 15 // Standard DEFLATE
  31. minMatchLength = 4 // The smallest match that the compressor looks for
  32. maxMatchLength = 258 // The longest match for the compressor
  33. minOffsetSize = 1 // The shortest offset that makes any sense
  34. // The maximum number of tokens we put into a single flat block, just too
  35. // stop things from getting too large.
  36. maxFlateBlockTokens = 1 << 14
  37. maxStoreBlockSize = 65535
  38. hashBits = 17 // After 17 performance degrades
  39. hashSize = 1 << hashBits
  40. hashMask = (1 << hashBits) - 1
  41. hashShift = (hashBits + minMatchLength - 1) / minMatchLength
  42. maxHashOffset = 1 << 24
  43. skipNever = math.MaxInt32
  44. )
  45. var useSSE42 bool
  46. type compressionLevel struct {
  47. good, lazy, nice, chain, fastSkipHashing, level int
  48. }
  49. // Compression levels have been rebalanced from zlib deflate defaults
  50. // to give a bigger spread in speed and compression.
  51. // See https://blog.klauspost.com/rebalancing-deflate-compression-levels/
  52. var levels = []compressionLevel{
  53. {}, // 0
  54. // Level 1-4 uses specialized algorithm - values not used
  55. {0, 0, 0, 0, 0, 1},
  56. {0, 0, 0, 0, 0, 2},
  57. {0, 0, 0, 0, 0, 3},
  58. {0, 0, 0, 0, 0, 4},
  59. // For levels 5-6 we don't bother trying with lazy matches.
  60. // Lazy matching is at least 30% slower, with 1.5% increase.
  61. {6, 0, 12, 8, 12, 5},
  62. {8, 0, 24, 16, 16, 6},
  63. // Levels 7-9 use increasingly more lazy matching
  64. // and increasingly stringent conditions for "good enough".
  65. {8, 8, 24, 16, skipNever, 7},
  66. {10, 16, 24, 64, skipNever, 8},
  67. {32, 258, 258, 4096, skipNever, 9},
  68. }
  69. type compressor struct {
  70. compressionLevel
  71. w *huffmanBitWriter
  72. bulkHasher func([]byte, []uint32)
  73. // compression algorithm
  74. fill func(*compressor, []byte) int // copy data to window
  75. step func(*compressor) // process window
  76. sync bool // requesting flush
  77. // Input hash chains
  78. // hashHead[hashValue] contains the largest inputIndex with the specified hash value
  79. // If hashHead[hashValue] is within the current window, then
  80. // hashPrev[hashHead[hashValue] & windowMask] contains the previous index
  81. // with the same hash value.
  82. chainHead int
  83. hashHead [hashSize]uint32
  84. hashPrev [windowSize]uint32
  85. hashOffset int
  86. // input window: unprocessed data is window[index:windowEnd]
  87. index int
  88. window []byte
  89. windowEnd int
  90. blockStart int // window index where current tokens start
  91. byteAvailable bool // if true, still need to process window[index-1].
  92. // queued output tokens
  93. tokens tokens
  94. // deflate state
  95. length int
  96. offset int
  97. hash uint32
  98. maxInsertIndex int
  99. err error
  100. ii uint16 // position of last match, intended to overflow to reset.
  101. snap snappyEnc
  102. hashMatch [maxMatchLength + minMatchLength]uint32
  103. }
  104. func (d *compressor) fillDeflate(b []byte) int {
  105. if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) {
  106. // shift the window by windowSize
  107. copy(d.window[:], d.window[windowSize:2*windowSize])
  108. d.index -= windowSize
  109. d.windowEnd -= windowSize
  110. if d.blockStart >= windowSize {
  111. d.blockStart -= windowSize
  112. } else {
  113. d.blockStart = math.MaxInt32
  114. }
  115. d.hashOffset += windowSize
  116. if d.hashOffset > maxHashOffset {
  117. delta := d.hashOffset - 1
  118. d.hashOffset -= delta
  119. d.chainHead -= delta
  120. for i, v := range d.hashPrev {
  121. if int(v) > delta {
  122. d.hashPrev[i] = uint32(int(v) - delta)
  123. } else {
  124. d.hashPrev[i] = 0
  125. }
  126. }
  127. for i, v := range d.hashHead {
  128. if int(v) > delta {
  129. d.hashHead[i] = uint32(int(v) - delta)
  130. } else {
  131. d.hashHead[i] = 0
  132. }
  133. }
  134. }
  135. }
  136. n := copy(d.window[d.windowEnd:], b)
  137. d.windowEnd += n
  138. return n
  139. }
  140. func (d *compressor) writeBlock(tok tokens, index int, eof bool) error {
  141. if index > 0 || eof {
  142. var window []byte
  143. if d.blockStart <= index {
  144. window = d.window[d.blockStart:index]
  145. }
  146. d.blockStart = index
  147. d.w.writeBlock(tok.tokens[:tok.n], eof, window)
  148. return d.w.err
  149. }
  150. return nil
  151. }
  152. // writeBlockSkip writes the current block and uses the number of tokens
  153. // to determine if the block should be stored on no matches, or
  154. // only huffman encoded.
  155. func (d *compressor) writeBlockSkip(tok tokens, index int, eof bool) error {
  156. if index > 0 || eof {
  157. if d.blockStart <= index {
  158. window := d.window[d.blockStart:index]
  159. // If we removed less than a 64th of all literals
  160. // we huffman compress the block.
  161. if int(tok.n) > len(window)-int(tok.n>>6) {
  162. d.w.writeBlockHuff(eof, window)
  163. } else {
  164. // Write a dynamic huffman block.
  165. d.w.writeBlockDynamic(tok.tokens[:tok.n], eof, window)
  166. }
  167. } else {
  168. d.w.writeBlock(tok.tokens[:tok.n], eof, nil)
  169. }
  170. d.blockStart = index
  171. return d.w.err
  172. }
  173. return nil
  174. }
  175. // fillWindow will fill the current window with the supplied
  176. // dictionary and calculate all hashes.
  177. // This is much faster than doing a full encode.
  178. // Should only be used after a start/reset.
  179. func (d *compressor) fillWindow(b []byte) {
  180. // Do not fill window if we are in store-only mode,
  181. // use constant or Snappy compression.
  182. switch d.compressionLevel.level {
  183. case 0, 1, 2:
  184. return
  185. }
  186. // If we are given too much, cut it.
  187. if len(b) > windowSize {
  188. b = b[len(b)-windowSize:]
  189. }
  190. // Add all to window.
  191. n := copy(d.window[d.windowEnd:], b)
  192. // Calculate 256 hashes at the time (more L1 cache hits)
  193. loops := (n + 256 - minMatchLength) / 256
  194. for j := 0; j < loops; j++ {
  195. startindex := j * 256
  196. end := startindex + 256 + minMatchLength - 1
  197. if end > n {
  198. end = n
  199. }
  200. tocheck := d.window[startindex:end]
  201. dstSize := len(tocheck) - minMatchLength + 1
  202. if dstSize <= 0 {
  203. continue
  204. }
  205. dst := d.hashMatch[:dstSize]
  206. d.bulkHasher(tocheck, dst)
  207. var newH uint32
  208. for i, val := range dst {
  209. di := i + startindex
  210. newH = val & hashMask
  211. // Get previous value with the same hash.
  212. // Our chain should point to the previous value.
  213. d.hashPrev[di&windowMask] = d.hashHead[newH]
  214. // Set the head of the hash chain to us.
  215. d.hashHead[newH] = uint32(di + d.hashOffset)
  216. }
  217. d.hash = newH
  218. }
  219. // Update window information.
  220. d.windowEnd += n
  221. d.index = n
  222. }
  223. // Try to find a match starting at index whose length is greater than prevSize.
  224. // We only look at chainCount possibilities before giving up.
  225. // pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead
  226. func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
  227. minMatchLook := maxMatchLength
  228. if lookahead < minMatchLook {
  229. minMatchLook = lookahead
  230. }
  231. win := d.window[0 : pos+minMatchLook]
  232. // We quit when we get a match that's at least nice long
  233. nice := len(win) - pos
  234. if d.nice < nice {
  235. nice = d.nice
  236. }
  237. // If we've got a match that's good enough, only look in 1/4 the chain.
  238. tries := d.chain
  239. length = prevLength
  240. if length >= d.good {
  241. tries >>= 2
  242. }
  243. wEnd := win[pos+length]
  244. wPos := win[pos:]
  245. minIndex := pos - windowSize
  246. for i := prevHead; tries > 0; tries-- {
  247. if wEnd == win[i+length] {
  248. n := matchLen(win[i:], wPos, minMatchLook)
  249. if n > length && (n > minMatchLength || pos-i <= 4096) {
  250. length = n
  251. offset = pos - i
  252. ok = true
  253. if n >= nice {
  254. // The match is good enough that we don't try to find a better one.
  255. break
  256. }
  257. wEnd = win[pos+n]
  258. }
  259. }
  260. if i == minIndex {
  261. // hashPrev[i & windowMask] has already been overwritten, so stop now.
  262. break
  263. }
  264. i = int(d.hashPrev[i&windowMask]) - d.hashOffset
  265. if i < minIndex || i < 0 {
  266. break
  267. }
  268. }
  269. return
  270. }
  271. // Try to find a match starting at index whose length is greater than prevSize.
  272. // We only look at chainCount possibilities before giving up.
  273. // pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead
  274. func (d *compressor) findMatchSSE(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
  275. minMatchLook := maxMatchLength
  276. if lookahead < minMatchLook {
  277. minMatchLook = lookahead
  278. }
  279. win := d.window[0 : pos+minMatchLook]
  280. // We quit when we get a match that's at least nice long
  281. nice := len(win) - pos
  282. if d.nice < nice {
  283. nice = d.nice
  284. }
  285. // If we've got a match that's good enough, only look in 1/4 the chain.
  286. tries := d.chain
  287. length = prevLength
  288. if length >= d.good {
  289. tries >>= 2
  290. }
  291. wEnd := win[pos+length]
  292. wPos := win[pos:]
  293. minIndex := pos - windowSize
  294. for i := prevHead; tries > 0; tries-- {
  295. if wEnd == win[i+length] {
  296. n := matchLenSSE4(win[i:], wPos, minMatchLook)
  297. if n > length && (n > minMatchLength || pos-i <= 4096) {
  298. length = n
  299. offset = pos - i
  300. ok = true
  301. if n >= nice {
  302. // The match is good enough that we don't try to find a better one.
  303. break
  304. }
  305. wEnd = win[pos+n]
  306. }
  307. }
  308. if i == minIndex {
  309. // hashPrev[i & windowMask] has already been overwritten, so stop now.
  310. break
  311. }
  312. i = int(d.hashPrev[i&windowMask]) - d.hashOffset
  313. if i < minIndex || i < 0 {
  314. break
  315. }
  316. }
  317. return
  318. }
  319. func (d *compressor) writeStoredBlock(buf []byte) error {
  320. if d.w.writeStoredHeader(len(buf), false); d.w.err != nil {
  321. return d.w.err
  322. }
  323. d.w.writeBytes(buf)
  324. return d.w.err
  325. }
  326. const hashmul = 0x1e35a7bd
  327. // hash4 returns a hash representation of the first 4 bytes
  328. // of the supplied slice.
  329. // The caller must ensure that len(b) >= 4.
  330. func hash4(b []byte) uint32 {
  331. return ((uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24) * hashmul) >> (32 - hashBits)
  332. }
  333. // bulkHash4 will compute hashes using the same
  334. // algorithm as hash4
  335. func bulkHash4(b []byte, dst []uint32) {
  336. if len(b) < minMatchLength {
  337. return
  338. }
  339. hb := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
  340. dst[0] = (hb * hashmul) >> (32 - hashBits)
  341. end := len(b) - minMatchLength + 1
  342. for i := 1; i < end; i++ {
  343. hb = (hb << 8) | uint32(b[i+3])
  344. dst[i] = (hb * hashmul) >> (32 - hashBits)
  345. }
  346. }
  347. // matchLen returns the number of matching bytes in a and b
  348. // up to length 'max'. Both slices must be at least 'max'
  349. // bytes in size.
  350. func matchLen(a, b []byte, max int) int {
  351. a = a[:max]
  352. b = b[:len(a)]
  353. for i, av := range a {
  354. if b[i] != av {
  355. return i
  356. }
  357. }
  358. return max
  359. }
  360. func (d *compressor) initDeflate() {
  361. d.window = make([]byte, 2*windowSize)
  362. d.hashOffset = 1
  363. d.length = minMatchLength - 1
  364. d.offset = 0
  365. d.byteAvailable = false
  366. d.index = 0
  367. d.hash = 0
  368. d.chainHead = -1
  369. d.bulkHasher = bulkHash4
  370. if useSSE42 {
  371. d.bulkHasher = crc32sseAll
  372. }
  373. }
  374. // Assumes that d.fastSkipHashing != skipNever,
  375. // otherwise use deflateLazy
  376. func (d *compressor) deflate() {
  377. // Sanity enables additional runtime tests.
  378. // It's intended to be used during development
  379. // to supplement the currently ad-hoc unit tests.
  380. const sanity = false
  381. if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
  382. return
  383. }
  384. d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
  385. if d.index < d.maxInsertIndex {
  386. d.hash = hash4(d.window[d.index : d.index+minMatchLength])
  387. }
  388. for {
  389. if sanity && d.index > d.windowEnd {
  390. panic("index > windowEnd")
  391. }
  392. lookahead := d.windowEnd - d.index
  393. if lookahead < minMatchLength+maxMatchLength {
  394. if !d.sync {
  395. return
  396. }
  397. if sanity && d.index > d.windowEnd {
  398. panic("index > windowEnd")
  399. }
  400. if lookahead == 0 {
  401. if d.tokens.n > 0 {
  402. if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
  403. return
  404. }
  405. d.tokens.n = 0
  406. }
  407. return
  408. }
  409. }
  410. if d.index < d.maxInsertIndex {
  411. // Update the hash
  412. d.hash = hash4(d.window[d.index : d.index+minMatchLength])
  413. ch := d.hashHead[d.hash&hashMask]
  414. d.chainHead = int(ch)
  415. d.hashPrev[d.index&windowMask] = ch
  416. d.hashHead[d.hash&hashMask] = uint32(d.index + d.hashOffset)
  417. }
  418. d.length = minMatchLength - 1
  419. d.offset = 0
  420. minIndex := d.index - windowSize
  421. if minIndex < 0 {
  422. minIndex = 0
  423. }
  424. if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 {
  425. if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
  426. d.length = newLength
  427. d.offset = newOffset
  428. }
  429. }
  430. if d.length >= minMatchLength {
  431. d.ii = 0
  432. // There was a match at the previous step, and the current match is
  433. // not better. Output the previous match.
  434. // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3
  435. d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize))
  436. d.tokens.n++
  437. // Insert in the hash table all strings up to the end of the match.
  438. // index and index-1 are already inserted. If there is not enough
  439. // lookahead, the last two strings are not inserted into the hash
  440. // table.
  441. if d.length <= d.fastSkipHashing {
  442. var newIndex int
  443. newIndex = d.index + d.length
  444. // Calculate missing hashes
  445. end := newIndex
  446. if end > d.maxInsertIndex {
  447. end = d.maxInsertIndex
  448. }
  449. end += minMatchLength - 1
  450. startindex := d.index + 1
  451. if startindex > d.maxInsertIndex {
  452. startindex = d.maxInsertIndex
  453. }
  454. tocheck := d.window[startindex:end]
  455. dstSize := len(tocheck) - minMatchLength + 1
  456. if dstSize > 0 {
  457. dst := d.hashMatch[:dstSize]
  458. bulkHash4(tocheck, dst)
  459. var newH uint32
  460. for i, val := range dst {
  461. di := i + startindex
  462. newH = val & hashMask
  463. // Get previous value with the same hash.
  464. // Our chain should point to the previous value.
  465. d.hashPrev[di&windowMask] = d.hashHead[newH]
  466. // Set the head of the hash chain to us.
  467. d.hashHead[newH] = uint32(di + d.hashOffset)
  468. }
  469. d.hash = newH
  470. }
  471. d.index = newIndex
  472. } else {
  473. // For matches this long, we don't bother inserting each individual
  474. // item into the table.
  475. d.index += d.length
  476. if d.index < d.maxInsertIndex {
  477. d.hash = hash4(d.window[d.index : d.index+minMatchLength])
  478. }
  479. }
  480. if d.tokens.n == maxFlateBlockTokens {
  481. // The block includes the current character
  482. if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
  483. return
  484. }
  485. d.tokens.n = 0
  486. }
  487. } else {
  488. d.ii++
  489. end := d.index + int(d.ii>>uint(d.fastSkipHashing)) + 1
  490. if end > d.windowEnd {
  491. end = d.windowEnd
  492. }
  493. for i := d.index; i < end; i++ {
  494. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i]))
  495. d.tokens.n++
  496. if d.tokens.n == maxFlateBlockTokens {
  497. if d.err = d.writeBlockSkip(d.tokens, i+1, false); d.err != nil {
  498. return
  499. }
  500. d.tokens.n = 0
  501. }
  502. }
  503. d.index = end
  504. }
  505. }
  506. }
  507. // deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever,
  508. // meaning it always has lazy matching on.
  509. func (d *compressor) deflateLazy() {
  510. // Sanity enables additional runtime tests.
  511. // It's intended to be used during development
  512. // to supplement the currently ad-hoc unit tests.
  513. const sanity = false
  514. if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
  515. return
  516. }
  517. d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
  518. if d.index < d.maxInsertIndex {
  519. d.hash = hash4(d.window[d.index : d.index+minMatchLength])
  520. }
  521. for {
  522. if sanity && d.index > d.windowEnd {
  523. panic("index > windowEnd")
  524. }
  525. lookahead := d.windowEnd - d.index
  526. if lookahead < minMatchLength+maxMatchLength {
  527. if !d.sync {
  528. return
  529. }
  530. if sanity && d.index > d.windowEnd {
  531. panic("index > windowEnd")
  532. }
  533. if lookahead == 0 {
  534. // Flush current output block if any.
  535. if d.byteAvailable {
  536. // There is still one pending token that needs to be flushed
  537. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  538. d.tokens.n++
  539. d.byteAvailable = false
  540. }
  541. if d.tokens.n > 0 {
  542. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  543. return
  544. }
  545. d.tokens.n = 0
  546. }
  547. return
  548. }
  549. }
  550. if d.index < d.maxInsertIndex {
  551. // Update the hash
  552. d.hash = hash4(d.window[d.index : d.index+minMatchLength])
  553. ch := d.hashHead[d.hash&hashMask]
  554. d.chainHead = int(ch)
  555. d.hashPrev[d.index&windowMask] = ch
  556. d.hashHead[d.hash&hashMask] = uint32(d.index + d.hashOffset)
  557. }
  558. prevLength := d.length
  559. prevOffset := d.offset
  560. d.length = minMatchLength - 1
  561. d.offset = 0
  562. minIndex := d.index - windowSize
  563. if minIndex < 0 {
  564. minIndex = 0
  565. }
  566. if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
  567. if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
  568. d.length = newLength
  569. d.offset = newOffset
  570. }
  571. }
  572. if prevLength >= minMatchLength && d.length <= prevLength {
  573. // There was a match at the previous step, and the current match is
  574. // not better. Output the previous match.
  575. d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize))
  576. d.tokens.n++
  577. // Insert in the hash table all strings up to the end of the match.
  578. // index and index-1 are already inserted. If there is not enough
  579. // lookahead, the last two strings are not inserted into the hash
  580. // table.
  581. var newIndex int
  582. newIndex = d.index + prevLength - 1
  583. // Calculate missing hashes
  584. end := newIndex
  585. if end > d.maxInsertIndex {
  586. end = d.maxInsertIndex
  587. }
  588. end += minMatchLength - 1
  589. startindex := d.index + 1
  590. if startindex > d.maxInsertIndex {
  591. startindex = d.maxInsertIndex
  592. }
  593. tocheck := d.window[startindex:end]
  594. dstSize := len(tocheck) - minMatchLength + 1
  595. if dstSize > 0 {
  596. dst := d.hashMatch[:dstSize]
  597. bulkHash4(tocheck, dst)
  598. var newH uint32
  599. for i, val := range dst {
  600. di := i + startindex
  601. newH = val & hashMask
  602. // Get previous value with the same hash.
  603. // Our chain should point to the previous value.
  604. d.hashPrev[di&windowMask] = d.hashHead[newH]
  605. // Set the head of the hash chain to us.
  606. d.hashHead[newH] = uint32(di + d.hashOffset)
  607. }
  608. d.hash = newH
  609. }
  610. d.index = newIndex
  611. d.byteAvailable = false
  612. d.length = minMatchLength - 1
  613. if d.tokens.n == maxFlateBlockTokens {
  614. // The block includes the current character
  615. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  616. return
  617. }
  618. d.tokens.n = 0
  619. }
  620. } else {
  621. // Reset, if we got a match this run.
  622. if d.length >= minMatchLength {
  623. d.ii = 0
  624. }
  625. // We have a byte waiting. Emit it.
  626. if d.byteAvailable {
  627. d.ii++
  628. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  629. d.tokens.n++
  630. if d.tokens.n == maxFlateBlockTokens {
  631. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  632. return
  633. }
  634. d.tokens.n = 0
  635. }
  636. d.index++
  637. // If we have a long run of no matches, skip additional bytes
  638. // Resets when d.ii overflows after 64KB.
  639. if d.ii > 31 {
  640. n := int(d.ii >> 5)
  641. for j := 0; j < n; j++ {
  642. if d.index >= d.windowEnd-1 {
  643. break
  644. }
  645. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  646. d.tokens.n++
  647. if d.tokens.n == maxFlateBlockTokens {
  648. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  649. return
  650. }
  651. d.tokens.n = 0
  652. }
  653. d.index++
  654. }
  655. // Flush last byte
  656. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  657. d.tokens.n++
  658. d.byteAvailable = false
  659. // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength
  660. if d.tokens.n == maxFlateBlockTokens {
  661. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  662. return
  663. }
  664. d.tokens.n = 0
  665. }
  666. }
  667. } else {
  668. d.index++
  669. d.byteAvailable = true
  670. }
  671. }
  672. }
  673. }
  674. // Assumes that d.fastSkipHashing != skipNever,
  675. // otherwise use deflateLazySSE
  676. func (d *compressor) deflateSSE() {
  677. // Sanity enables additional runtime tests.
  678. // It's intended to be used during development
  679. // to supplement the currently ad-hoc unit tests.
  680. const sanity = false
  681. if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
  682. return
  683. }
  684. d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
  685. if d.index < d.maxInsertIndex {
  686. d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
  687. }
  688. for {
  689. if sanity && d.index > d.windowEnd {
  690. panic("index > windowEnd")
  691. }
  692. lookahead := d.windowEnd - d.index
  693. if lookahead < minMatchLength+maxMatchLength {
  694. if !d.sync {
  695. return
  696. }
  697. if sanity && d.index > d.windowEnd {
  698. panic("index > windowEnd")
  699. }
  700. if lookahead == 0 {
  701. if d.tokens.n > 0 {
  702. if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
  703. return
  704. }
  705. d.tokens.n = 0
  706. }
  707. return
  708. }
  709. }
  710. if d.index < d.maxInsertIndex {
  711. // Update the hash
  712. d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
  713. ch := d.hashHead[d.hash]
  714. d.chainHead = int(ch)
  715. d.hashPrev[d.index&windowMask] = ch
  716. d.hashHead[d.hash] = uint32(d.index + d.hashOffset)
  717. }
  718. d.length = minMatchLength - 1
  719. d.offset = 0
  720. minIndex := d.index - windowSize
  721. if minIndex < 0 {
  722. minIndex = 0
  723. }
  724. if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 {
  725. if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
  726. d.length = newLength
  727. d.offset = newOffset
  728. }
  729. }
  730. if d.length >= minMatchLength {
  731. d.ii = 0
  732. // There was a match at the previous step, and the current match is
  733. // not better. Output the previous match.
  734. // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3
  735. d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize))
  736. d.tokens.n++
  737. // Insert in the hash table all strings up to the end of the match.
  738. // index and index-1 are already inserted. If there is not enough
  739. // lookahead, the last two strings are not inserted into the hash
  740. // table.
  741. if d.length <= d.fastSkipHashing {
  742. var newIndex int
  743. newIndex = d.index + d.length
  744. // Calculate missing hashes
  745. end := newIndex
  746. if end > d.maxInsertIndex {
  747. end = d.maxInsertIndex
  748. }
  749. end += minMatchLength - 1
  750. startindex := d.index + 1
  751. if startindex > d.maxInsertIndex {
  752. startindex = d.maxInsertIndex
  753. }
  754. tocheck := d.window[startindex:end]
  755. dstSize := len(tocheck) - minMatchLength + 1
  756. if dstSize > 0 {
  757. dst := d.hashMatch[:dstSize]
  758. crc32sseAll(tocheck, dst)
  759. var newH uint32
  760. for i, val := range dst {
  761. di := i + startindex
  762. newH = val & hashMask
  763. // Get previous value with the same hash.
  764. // Our chain should point to the previous value.
  765. d.hashPrev[di&windowMask] = d.hashHead[newH]
  766. // Set the head of the hash chain to us.
  767. d.hashHead[newH] = uint32(di + d.hashOffset)
  768. }
  769. d.hash = newH
  770. }
  771. d.index = newIndex
  772. } else {
  773. // For matches this long, we don't bother inserting each individual
  774. // item into the table.
  775. d.index += d.length
  776. if d.index < d.maxInsertIndex {
  777. d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
  778. }
  779. }
  780. if d.tokens.n == maxFlateBlockTokens {
  781. // The block includes the current character
  782. if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
  783. return
  784. }
  785. d.tokens.n = 0
  786. }
  787. } else {
  788. d.ii++
  789. end := d.index + int(d.ii>>5) + 1
  790. if end > d.windowEnd {
  791. end = d.windowEnd
  792. }
  793. for i := d.index; i < end; i++ {
  794. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i]))
  795. d.tokens.n++
  796. if d.tokens.n == maxFlateBlockTokens {
  797. if d.err = d.writeBlockSkip(d.tokens, i+1, false); d.err != nil {
  798. return
  799. }
  800. d.tokens.n = 0
  801. }
  802. }
  803. d.index = end
  804. }
  805. }
  806. }
  807. // deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever,
  808. // meaning it always has lazy matching on.
  809. func (d *compressor) deflateLazySSE() {
  810. // Sanity enables additional runtime tests.
  811. // It's intended to be used during development
  812. // to supplement the currently ad-hoc unit tests.
  813. const sanity = false
  814. if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
  815. return
  816. }
  817. d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
  818. if d.index < d.maxInsertIndex {
  819. d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
  820. }
  821. for {
  822. if sanity && d.index > d.windowEnd {
  823. panic("index > windowEnd")
  824. }
  825. lookahead := d.windowEnd - d.index
  826. if lookahead < minMatchLength+maxMatchLength {
  827. if !d.sync {
  828. return
  829. }
  830. if sanity && d.index > d.windowEnd {
  831. panic("index > windowEnd")
  832. }
  833. if lookahead == 0 {
  834. // Flush current output block if any.
  835. if d.byteAvailable {
  836. // There is still one pending token that needs to be flushed
  837. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  838. d.tokens.n++
  839. d.byteAvailable = false
  840. }
  841. if d.tokens.n > 0 {
  842. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  843. return
  844. }
  845. d.tokens.n = 0
  846. }
  847. return
  848. }
  849. }
  850. if d.index < d.maxInsertIndex {
  851. // Update the hash
  852. d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
  853. ch := d.hashHead[d.hash]
  854. d.chainHead = int(ch)
  855. d.hashPrev[d.index&windowMask] = ch
  856. d.hashHead[d.hash] = uint32(d.index + d.hashOffset)
  857. }
  858. prevLength := d.length
  859. prevOffset := d.offset
  860. d.length = minMatchLength - 1
  861. d.offset = 0
  862. minIndex := d.index - windowSize
  863. if minIndex < 0 {
  864. minIndex = 0
  865. }
  866. if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
  867. if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
  868. d.length = newLength
  869. d.offset = newOffset
  870. }
  871. }
  872. if prevLength >= minMatchLength && d.length <= prevLength {
  873. // There was a match at the previous step, and the current match is
  874. // not better. Output the previous match.
  875. d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize))
  876. d.tokens.n++
  877. // Insert in the hash table all strings up to the end of the match.
  878. // index and index-1 are already inserted. If there is not enough
  879. // lookahead, the last two strings are not inserted into the hash
  880. // table.
  881. var newIndex int
  882. newIndex = d.index + prevLength - 1
  883. // Calculate missing hashes
  884. end := newIndex
  885. if end > d.maxInsertIndex {
  886. end = d.maxInsertIndex
  887. }
  888. end += minMatchLength - 1
  889. startindex := d.index + 1
  890. if startindex > d.maxInsertIndex {
  891. startindex = d.maxInsertIndex
  892. }
  893. tocheck := d.window[startindex:end]
  894. dstSize := len(tocheck) - minMatchLength + 1
  895. if dstSize > 0 {
  896. dst := d.hashMatch[:dstSize]
  897. crc32sseAll(tocheck, dst)
  898. var newH uint32
  899. for i, val := range dst {
  900. di := i + startindex
  901. newH = val & hashMask
  902. // Get previous value with the same hash.
  903. // Our chain should point to the previous value.
  904. d.hashPrev[di&windowMask] = d.hashHead[newH]
  905. // Set the head of the hash chain to us.
  906. d.hashHead[newH] = uint32(di + d.hashOffset)
  907. }
  908. d.hash = newH
  909. }
  910. d.index = newIndex
  911. d.byteAvailable = false
  912. d.length = minMatchLength - 1
  913. if d.tokens.n == maxFlateBlockTokens {
  914. // The block includes the current character
  915. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  916. return
  917. }
  918. d.tokens.n = 0
  919. }
  920. } else {
  921. // Reset, if we got a match this run.
  922. if d.length >= minMatchLength {
  923. d.ii = 0
  924. }
  925. // We have a byte waiting. Emit it.
  926. if d.byteAvailable {
  927. d.ii++
  928. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  929. d.tokens.n++
  930. if d.tokens.n == maxFlateBlockTokens {
  931. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  932. return
  933. }
  934. d.tokens.n = 0
  935. }
  936. d.index++
  937. // If we have a long run of no matches, skip additional bytes
  938. // Resets when d.ii overflows after 64KB.
  939. if d.ii > 31 {
  940. n := int(d.ii >> 6)
  941. for j := 0; j < n; j++ {
  942. if d.index >= d.windowEnd-1 {
  943. break
  944. }
  945. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  946. d.tokens.n++
  947. if d.tokens.n == maxFlateBlockTokens {
  948. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  949. return
  950. }
  951. d.tokens.n = 0
  952. }
  953. d.index++
  954. }
  955. // Flush last byte
  956. d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
  957. d.tokens.n++
  958. d.byteAvailable = false
  959. // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength
  960. if d.tokens.n == maxFlateBlockTokens {
  961. if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
  962. return
  963. }
  964. d.tokens.n = 0
  965. }
  966. }
  967. } else {
  968. d.index++
  969. d.byteAvailable = true
  970. }
  971. }
  972. }
  973. }
  974. func (d *compressor) store() {
  975. if d.windowEnd > 0 && (d.windowEnd == maxStoreBlockSize || d.sync) {
  976. d.err = d.writeStoredBlock(d.window[:d.windowEnd])
  977. d.windowEnd = 0
  978. }
  979. }
  980. // fillWindow will fill the buffer with data for huffman-only compression.
  981. // The number of bytes copied is returned.
  982. func (d *compressor) fillBlock(b []byte) int {
  983. n := copy(d.window[d.windowEnd:], b)
  984. d.windowEnd += n
  985. return n
  986. }
  987. // storeHuff will compress and store the currently added data,
  988. // if enough has been accumulated or we at the end of the stream.
  989. // Any error that occurred will be in d.err
  990. func (d *compressor) storeHuff() {
  991. if d.windowEnd < len(d.window) && !d.sync || d.windowEnd == 0 {
  992. return
  993. }
  994. d.w.writeBlockHuff(false, d.window[:d.windowEnd])
  995. d.err = d.w.err
  996. d.windowEnd = 0
  997. }
  998. // storeHuff will compress and store the currently added data,
  999. // if enough has been accumulated or we at the end of the stream.
  1000. // Any error that occurred will be in d.err
  1001. func (d *compressor) storeSnappy() {
  1002. // We only compress if we have maxStoreBlockSize.
  1003. if d.windowEnd < maxStoreBlockSize {
  1004. if !d.sync {
  1005. return
  1006. }
  1007. // Handle extremely small sizes.
  1008. if d.windowEnd < 128 {
  1009. if d.windowEnd == 0 {
  1010. return
  1011. }
  1012. if d.windowEnd <= 32 {
  1013. d.err = d.writeStoredBlock(d.window[:d.windowEnd])
  1014. d.tokens.n = 0
  1015. d.windowEnd = 0
  1016. } else {
  1017. d.w.writeBlockHuff(false, d.window[:d.windowEnd])
  1018. d.err = d.w.err
  1019. }
  1020. d.tokens.n = 0
  1021. d.windowEnd = 0
  1022. d.snap.Reset()
  1023. return
  1024. }
  1025. }
  1026. d.snap.Encode(&d.tokens, d.window[:d.windowEnd])
  1027. // If we made zero matches, store the block as is.
  1028. if int(d.tokens.n) == d.windowEnd {
  1029. d.err = d.writeStoredBlock(d.window[:d.windowEnd])
  1030. // If we removed less than 1/16th, huffman compress the block.
  1031. } else if int(d.tokens.n) > d.windowEnd-(d.windowEnd>>4) {
  1032. d.w.writeBlockHuff(false, d.window[:d.windowEnd])
  1033. d.err = d.w.err
  1034. } else {
  1035. d.w.writeBlockDynamic(d.tokens.tokens[:d.tokens.n], false, d.window[:d.windowEnd])
  1036. d.err = d.w.err
  1037. }
  1038. d.tokens.n = 0
  1039. d.windowEnd = 0
  1040. }
  1041. // write will add input byte to the stream.
  1042. // Unless an error occurs all bytes will be consumed.
  1043. func (d *compressor) write(b []byte) (n int, err error) {
  1044. if d.err != nil {
  1045. return 0, d.err
  1046. }
  1047. n = len(b)
  1048. for len(b) > 0 {
  1049. d.step(d)
  1050. b = b[d.fill(d, b):]
  1051. if d.err != nil {
  1052. return 0, d.err
  1053. }
  1054. }
  1055. return n, d.err
  1056. }
  1057. func (d *compressor) syncFlush() error {
  1058. d.sync = true
  1059. if d.err != nil {
  1060. return d.err
  1061. }
  1062. d.step(d)
  1063. if d.err == nil {
  1064. d.w.writeStoredHeader(0, false)
  1065. d.w.flush()
  1066. d.err = d.w.err
  1067. }
  1068. d.sync = false
  1069. return d.err
  1070. }
  1071. func (d *compressor) init(w io.Writer, level int) (err error) {
  1072. d.w = newHuffmanBitWriter(w)
  1073. switch {
  1074. case level == NoCompression:
  1075. d.window = make([]byte, maxStoreBlockSize)
  1076. d.fill = (*compressor).fillBlock
  1077. d.step = (*compressor).store
  1078. case level == ConstantCompression:
  1079. d.window = make([]byte, maxStoreBlockSize)
  1080. d.fill = (*compressor).fillBlock
  1081. d.step = (*compressor).storeHuff
  1082. case level >= 1 && level <= 4:
  1083. d.snap = newSnappy(level)
  1084. d.window = make([]byte, maxStoreBlockSize)
  1085. d.fill = (*compressor).fillBlock
  1086. d.step = (*compressor).storeSnappy
  1087. case level == DefaultCompression:
  1088. level = 5
  1089. fallthrough
  1090. case 5 <= level && level <= 9:
  1091. d.compressionLevel = levels[level]
  1092. d.initDeflate()
  1093. d.fill = (*compressor).fillDeflate
  1094. if d.fastSkipHashing == skipNever {
  1095. if useSSE42 {
  1096. d.step = (*compressor).deflateLazySSE
  1097. } else {
  1098. d.step = (*compressor).deflateLazy
  1099. }
  1100. } else {
  1101. if useSSE42 {
  1102. d.step = (*compressor).deflateSSE
  1103. } else {
  1104. d.step = (*compressor).deflate
  1105. }
  1106. }
  1107. default:
  1108. return fmt.Errorf("flate: invalid compression level %d: want value in range [-2, 9]", level)
  1109. }
  1110. return nil
  1111. }
  1112. // reset the state of the compressor.
  1113. func (d *compressor) reset(w io.Writer) {
  1114. d.w.reset(w)
  1115. d.sync = false
  1116. d.err = nil
  1117. // We only need to reset a few things for Snappy.
  1118. if d.snap != nil {
  1119. d.snap.Reset()
  1120. d.windowEnd = 0
  1121. d.tokens.n = 0
  1122. return
  1123. }
  1124. switch d.compressionLevel.chain {
  1125. case 0:
  1126. // level was NoCompression or ConstantCompresssion.
  1127. d.windowEnd = 0
  1128. default:
  1129. d.chainHead = -1
  1130. for i := range d.hashHead {
  1131. d.hashHead[i] = 0
  1132. }
  1133. for i := range d.hashPrev {
  1134. d.hashPrev[i] = 0
  1135. }
  1136. d.hashOffset = 1
  1137. d.index, d.windowEnd = 0, 0
  1138. d.blockStart, d.byteAvailable = 0, false
  1139. d.tokens.n = 0
  1140. d.length = minMatchLength - 1
  1141. d.offset = 0
  1142. d.hash = 0
  1143. d.ii = 0
  1144. d.maxInsertIndex = 0
  1145. }
  1146. }
  1147. func (d *compressor) close() error {
  1148. if d.err != nil {
  1149. return d.err
  1150. }
  1151. d.sync = true
  1152. d.step(d)
  1153. if d.err != nil {
  1154. return d.err
  1155. }
  1156. if d.w.writeStoredHeader(0, true); d.w.err != nil {
  1157. return d.w.err
  1158. }
  1159. d.w.flush()
  1160. return d.w.err
  1161. }
  1162. // NewWriter returns a new Writer compressing data at the given level.
  1163. // Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression);
  1164. // higher levels typically run slower but compress more.
  1165. // Level 0 (NoCompression) does not attempt any compression; it only adds the
  1166. // necessary DEFLATE framing.
  1167. // Level -1 (DefaultCompression) uses the default compression level.
  1168. // Level -2 (ConstantCompression) will use Huffman compression only, giving
  1169. // a very fast compression for all types of input, but sacrificing considerable
  1170. // compression efficiency.
  1171. //
  1172. // If level is in the range [-2, 9] then the error returned will be nil.
  1173. // Otherwise the error returned will be non-nil.
  1174. func NewWriter(w io.Writer, level int) (*Writer, error) {
  1175. var dw Writer
  1176. if err := dw.d.init(w, level); err != nil {
  1177. return nil, err
  1178. }
  1179. return &dw, nil
  1180. }
  1181. // NewWriterDict is like NewWriter but initializes the new
  1182. // Writer with a preset dictionary. The returned Writer behaves
  1183. // as if the dictionary had been written to it without producing
  1184. // any compressed output. The compressed data written to w
  1185. // can only be decompressed by a Reader initialized with the
  1186. // same dictionary.
  1187. func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
  1188. dw := &dictWriter{w}
  1189. zw, err := NewWriter(dw, level)
  1190. if err != nil {
  1191. return nil, err
  1192. }
  1193. zw.d.fillWindow(dict)
  1194. zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method.
  1195. return zw, err
  1196. }
  1197. type dictWriter struct {
  1198. w io.Writer
  1199. }
  1200. func (w *dictWriter) Write(b []byte) (n int, err error) {
  1201. return w.w.Write(b)
  1202. }
  1203. // A Writer takes data written to it and writes the compressed
  1204. // form of that data to an underlying writer (see NewWriter).
  1205. type Writer struct {
  1206. d compressor
  1207. dict []byte
  1208. }
  1209. // Write writes data to w, which will eventually write the
  1210. // compressed form of data to its underlying writer.
  1211. func (w *Writer) Write(data []byte) (n int, err error) {
  1212. return w.d.write(data)
  1213. }
  1214. // Flush flushes any pending data to the underlying writer.
  1215. // It is useful mainly in compressed network protocols, to ensure that
  1216. // a remote reader has enough data to reconstruct a packet.
  1217. // Flush does not return until the data has been written.
  1218. // Calling Flush when there is no pending data still causes the Writer
  1219. // to emit a sync marker of at least 4 bytes.
  1220. // If the underlying writer returns an error, Flush returns that error.
  1221. //
  1222. // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
  1223. func (w *Writer) Flush() error {
  1224. // For more about flushing:
  1225. // http://www.bolet.org/~pornin/deflate-flush.html
  1226. return w.d.syncFlush()
  1227. }
  1228. // Close flushes and closes the writer.
  1229. func (w *Writer) Close() error {
  1230. return w.d.close()
  1231. }
  1232. // Reset discards the writer's state and makes it equivalent to
  1233. // the result of NewWriter or NewWriterDict called with dst
  1234. // and w's level and dictionary.
  1235. func (w *Writer) Reset(dst io.Writer) {
  1236. if dw, ok := w.d.w.writer.(*dictWriter); ok {
  1237. // w was created with NewWriterDict
  1238. dw.w = dst
  1239. w.d.reset(dw)
  1240. w.d.fillWindow(w.dict)
  1241. } else {
  1242. // w was created with NewWriter
  1243. w.d.reset(dst)
  1244. }
  1245. }
  1246. // ResetDict discards the writer's state and makes it equivalent to
  1247. // the result of NewWriter or NewWriterDict called with dst
  1248. // and w's level, but sets a specific dictionary.
  1249. func (w *Writer) ResetDict(dst io.Writer, dict []byte) {
  1250. w.dict = dict
  1251. w.d.reset(dst)
  1252. w.d.fillWindow(w.dict)
  1253. }