encode_best.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. // Copyright 2016 The Snappy-Go Authors. All rights reserved.
  2. // Copyright (c) 2019 Klaus Post. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package s2
  6. import (
  7. "fmt"
  8. "math"
  9. "math/bits"
  10. )
  11. // encodeBlockBest encodes a non-empty src to a guaranteed-large-enough dst. It
  12. // assumes that the varint-encoded length of the decompressed bytes has already
  13. // been written.
  14. //
  15. // It also assumes that:
  16. //
  17. // len(dst) >= MaxEncodedLen(len(src)) &&
  18. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  19. func encodeBlockBest(dst, src []byte, dict *Dict) (d int) {
  20. // Initialize the hash tables.
  21. const (
  22. // Long hash matches.
  23. lTableBits = 19
  24. maxLTableSize = 1 << lTableBits
  25. // Short hash matches.
  26. sTableBits = 16
  27. maxSTableSize = 1 << sTableBits
  28. inputMargin = 8 + 2
  29. debug = false
  30. )
  31. // sLimit is when to stop looking for offset/length copies. The inputMargin
  32. // lets us use a fast path for emitLiteral in the main loop, while we are
  33. // looking for copies.
  34. sLimit := len(src) - inputMargin
  35. if len(src) < minNonLiteralBlockSize {
  36. return 0
  37. }
  38. sLimitDict := len(src) - inputMargin
  39. if sLimitDict > MaxDictSrcOffset-inputMargin {
  40. sLimitDict = MaxDictSrcOffset - inputMargin
  41. }
  42. var lTable [maxLTableSize]uint64
  43. var sTable [maxSTableSize]uint64
  44. // Bail if we can't compress to at least this.
  45. dstLimit := len(src) - 5
  46. // nextEmit is where in src the next emitLiteral should start from.
  47. nextEmit := 0
  48. // The encoded form must start with a literal, as there are no previous
  49. // bytes to copy, so we start looking for hash matches at s == 1.
  50. s := 1
  51. repeat := 1
  52. if dict != nil {
  53. dict.initBest()
  54. s = 0
  55. repeat = len(dict.dict) - dict.repeat
  56. }
  57. cv := load64(src, s)
  58. // We search for a repeat at -1, but don't output repeats when nextEmit == 0
  59. const lowbitMask = 0xffffffff
  60. getCur := func(x uint64) int {
  61. return int(x & lowbitMask)
  62. }
  63. getPrev := func(x uint64) int {
  64. return int(x >> 32)
  65. }
  66. const maxSkip = 64
  67. for {
  68. type match struct {
  69. offset int
  70. s int
  71. length int
  72. score int
  73. rep, dict bool
  74. }
  75. var best match
  76. for {
  77. // Next src position to check
  78. nextS := (s-nextEmit)>>8 + 1
  79. if nextS > maxSkip {
  80. nextS = s + maxSkip
  81. } else {
  82. nextS += s
  83. }
  84. if nextS > sLimit {
  85. goto emitRemainder
  86. }
  87. if dict != nil && s >= MaxDictSrcOffset {
  88. dict = nil
  89. if repeat > s {
  90. repeat = math.MinInt32
  91. }
  92. }
  93. hashL := hash8(cv, lTableBits)
  94. hashS := hash4(cv, sTableBits)
  95. candidateL := lTable[hashL]
  96. candidateS := sTable[hashS]
  97. score := func(m match) int {
  98. // Matches that are longer forward are penalized since we must emit it as a literal.
  99. score := m.length - m.s
  100. if nextEmit == m.s {
  101. // If we do not have to emit literals, we save 1 byte
  102. score++
  103. }
  104. offset := m.s - m.offset
  105. if m.rep {
  106. return score - emitRepeatSize(offset, m.length)
  107. }
  108. return score - emitCopySize(offset, m.length)
  109. }
  110. matchAt := func(offset, s int, first uint32, rep bool) match {
  111. if best.length != 0 && best.s-best.offset == s-offset {
  112. // Don't retest if we have the same offset.
  113. return match{offset: offset, s: s}
  114. }
  115. if load32(src, offset) != first {
  116. return match{offset: offset, s: s}
  117. }
  118. m := match{offset: offset, s: s, length: 4 + offset, rep: rep}
  119. s += 4
  120. for s < len(src) {
  121. if len(src)-s < 8 {
  122. if src[s] == src[m.length] {
  123. m.length++
  124. s++
  125. continue
  126. }
  127. break
  128. }
  129. if diff := load64(src, s) ^ load64(src, m.length); diff != 0 {
  130. m.length += bits.TrailingZeros64(diff) >> 3
  131. break
  132. }
  133. s += 8
  134. m.length += 8
  135. }
  136. m.length -= offset
  137. m.score = score(m)
  138. if m.score <= -m.s {
  139. // Eliminate if no savings, we might find a better one.
  140. m.length = 0
  141. }
  142. return m
  143. }
  144. matchDict := func(candidate, s int, first uint32, rep bool) match {
  145. // Calculate offset as if in continuous array with s
  146. offset := -len(dict.dict) + candidate
  147. if best.length != 0 && best.s-best.offset == s-offset && !rep {
  148. // Don't retest if we have the same offset.
  149. return match{offset: offset, s: s}
  150. }
  151. if load32(dict.dict, candidate) != first {
  152. return match{offset: offset, s: s}
  153. }
  154. m := match{offset: offset, s: s, length: 4 + candidate, rep: rep, dict: true}
  155. s += 4
  156. if !rep {
  157. for s < sLimitDict && m.length < len(dict.dict) {
  158. if len(src)-s < 8 || len(dict.dict)-m.length < 8 {
  159. if src[s] == dict.dict[m.length] {
  160. m.length++
  161. s++
  162. continue
  163. }
  164. break
  165. }
  166. if diff := load64(src, s) ^ load64(dict.dict, m.length); diff != 0 {
  167. m.length += bits.TrailingZeros64(diff) >> 3
  168. break
  169. }
  170. s += 8
  171. m.length += 8
  172. }
  173. } else {
  174. for s < len(src) && m.length < len(dict.dict) {
  175. if len(src)-s < 8 || len(dict.dict)-m.length < 8 {
  176. if src[s] == dict.dict[m.length] {
  177. m.length++
  178. s++
  179. continue
  180. }
  181. break
  182. }
  183. if diff := load64(src, s) ^ load64(dict.dict, m.length); diff != 0 {
  184. m.length += bits.TrailingZeros64(diff) >> 3
  185. break
  186. }
  187. s += 8
  188. m.length += 8
  189. }
  190. }
  191. m.length -= candidate
  192. m.score = score(m)
  193. if m.score <= -m.s {
  194. // Eliminate if no savings, we might find a better one.
  195. m.length = 0
  196. }
  197. return m
  198. }
  199. bestOf := func(a, b match) match {
  200. if b.length == 0 {
  201. return a
  202. }
  203. if a.length == 0 {
  204. return b
  205. }
  206. as := a.score + b.s
  207. bs := b.score + a.s
  208. if as >= bs {
  209. return a
  210. }
  211. return b
  212. }
  213. if s > 0 {
  214. best = bestOf(matchAt(getCur(candidateL), s, uint32(cv), false), matchAt(getPrev(candidateL), s, uint32(cv), false))
  215. best = bestOf(best, matchAt(getCur(candidateS), s, uint32(cv), false))
  216. best = bestOf(best, matchAt(getPrev(candidateS), s, uint32(cv), false))
  217. }
  218. if dict != nil {
  219. candidateL := dict.bestTableLong[hashL]
  220. candidateS := dict.bestTableShort[hashS]
  221. best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false))
  222. best = bestOf(best, matchDict(int(candidateL>>16), s, uint32(cv), false))
  223. best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false))
  224. best = bestOf(best, matchDict(int(candidateS>>16), s, uint32(cv), false))
  225. }
  226. {
  227. if (dict == nil || repeat <= s) && repeat > 0 {
  228. best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8), true))
  229. } else if s-repeat < -4 && dict != nil {
  230. candidate := len(dict.dict) - (repeat - s)
  231. best = bestOf(best, matchDict(candidate, s, uint32(cv), true))
  232. candidate++
  233. best = bestOf(best, matchDict(candidate, s+1, uint32(cv>>8), true))
  234. }
  235. if best.length > 0 {
  236. hashS := hash4(cv>>8, sTableBits)
  237. // s+1
  238. nextShort := sTable[hashS]
  239. s := s + 1
  240. cv := load64(src, s)
  241. hashL := hash8(cv, lTableBits)
  242. nextLong := lTable[hashL]
  243. best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv), false))
  244. best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv), false))
  245. best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv), false))
  246. best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv), false))
  247. // Dict at + 1
  248. if dict != nil {
  249. candidateL := dict.bestTableLong[hashL]
  250. candidateS := dict.bestTableShort[hashS]
  251. best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false))
  252. best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false))
  253. }
  254. // s+2
  255. if true {
  256. hashS := hash4(cv>>8, sTableBits)
  257. nextShort = sTable[hashS]
  258. s++
  259. cv = load64(src, s)
  260. hashL := hash8(cv, lTableBits)
  261. nextLong = lTable[hashL]
  262. if (dict == nil || repeat <= s) && repeat > 0 {
  263. // Repeat at + 2
  264. best = bestOf(best, matchAt(s-repeat, s, uint32(cv), true))
  265. } else if repeat-s > 4 && dict != nil {
  266. candidate := len(dict.dict) - (repeat - s)
  267. best = bestOf(best, matchDict(candidate, s, uint32(cv), true))
  268. }
  269. best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv), false))
  270. best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv), false))
  271. best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv), false))
  272. best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv), false))
  273. // Dict at +2
  274. // Very small gain
  275. if dict != nil {
  276. candidateL := dict.bestTableLong[hashL]
  277. candidateS := dict.bestTableShort[hashS]
  278. best = bestOf(best, matchDict(int(candidateL&0xffff), s, uint32(cv), false))
  279. best = bestOf(best, matchDict(int(candidateS&0xffff), s, uint32(cv), false))
  280. }
  281. }
  282. // Search for a match at best match end, see if that is better.
  283. // Allow some bytes at the beginning to mismatch.
  284. // Sweet spot is around 1-2 bytes, but depends on input.
  285. // The skipped bytes are tested in Extend backwards,
  286. // and still picked up as part of the match if they do.
  287. const skipBeginning = 2
  288. const skipEnd = 1
  289. if sAt := best.s + best.length - skipEnd; sAt < sLimit {
  290. sBack := best.s + skipBeginning - skipEnd
  291. backL := best.length - skipBeginning
  292. // Load initial values
  293. cv = load64(src, sBack)
  294. // Grab candidates...
  295. next := lTable[hash8(load64(src, sAt), lTableBits)]
  296. if checkAt := getCur(next) - backL; checkAt > 0 {
  297. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false))
  298. }
  299. if checkAt := getPrev(next) - backL; checkAt > 0 {
  300. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false))
  301. }
  302. // Disabled: Extremely small gain
  303. if false {
  304. next = sTable[hash4(load64(src, sAt), sTableBits)]
  305. if checkAt := getCur(next) - backL; checkAt > 0 {
  306. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false))
  307. }
  308. if checkAt := getPrev(next) - backL; checkAt > 0 {
  309. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv), false))
  310. }
  311. }
  312. }
  313. }
  314. }
  315. // Update table
  316. lTable[hashL] = uint64(s) | candidateL<<32
  317. sTable[hashS] = uint64(s) | candidateS<<32
  318. if best.length > 0 {
  319. break
  320. }
  321. cv = load64(src, nextS)
  322. s = nextS
  323. }
  324. // Extend backwards, not needed for repeats...
  325. s = best.s
  326. if !best.rep && !best.dict {
  327. for best.offset > 0 && s > nextEmit && src[best.offset-1] == src[s-1] {
  328. best.offset--
  329. best.length++
  330. s--
  331. }
  332. }
  333. if false && best.offset >= s {
  334. panic(fmt.Errorf("t %d >= s %d", best.offset, s))
  335. }
  336. // Bail if we exceed the maximum size.
  337. if d+(s-nextEmit) > dstLimit {
  338. return 0
  339. }
  340. base := s
  341. offset := s - best.offset
  342. s += best.length
  343. if offset > 65535 && s-base <= 5 && !best.rep {
  344. // Bail if the match is equal or worse to the encoding.
  345. s = best.s + 1
  346. if s >= sLimit {
  347. goto emitRemainder
  348. }
  349. cv = load64(src, s)
  350. continue
  351. }
  352. if debug && nextEmit != base {
  353. fmt.Println("EMIT", base-nextEmit, "literals. base-after:", base)
  354. }
  355. d += emitLiteral(dst[d:], src[nextEmit:base])
  356. if best.rep {
  357. if nextEmit > 0 || best.dict {
  358. if debug {
  359. fmt.Println("REPEAT, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best)
  360. }
  361. // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset.
  362. d += emitRepeat(dst[d:], offset, best.length)
  363. } else {
  364. // First match without dict cannot be a repeat.
  365. if debug {
  366. fmt.Println("COPY, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best)
  367. }
  368. d += emitCopy(dst[d:], offset, best.length)
  369. }
  370. } else {
  371. if debug {
  372. fmt.Println("COPY, length", best.length, "offset:", offset, "s-after:", s, "dict:", best.dict, "best:", best)
  373. }
  374. d += emitCopy(dst[d:], offset, best.length)
  375. }
  376. repeat = offset
  377. nextEmit = s
  378. if s >= sLimit {
  379. goto emitRemainder
  380. }
  381. if d > dstLimit {
  382. // Do we have space for more, if not bail.
  383. return 0
  384. }
  385. // Fill tables...
  386. for i := best.s + 1; i < s; i++ {
  387. cv0 := load64(src, i)
  388. long0 := hash8(cv0, lTableBits)
  389. short0 := hash4(cv0, sTableBits)
  390. lTable[long0] = uint64(i) | lTable[long0]<<32
  391. sTable[short0] = uint64(i) | sTable[short0]<<32
  392. }
  393. cv = load64(src, s)
  394. }
  395. emitRemainder:
  396. if nextEmit < len(src) {
  397. // Bail if we exceed the maximum size.
  398. if d+len(src)-nextEmit > dstLimit {
  399. return 0
  400. }
  401. if debug && nextEmit != s {
  402. fmt.Println("emitted ", len(src)-nextEmit, "literals")
  403. }
  404. d += emitLiteral(dst[d:], src[nextEmit:])
  405. }
  406. return d
  407. }
  408. // encodeBlockBestSnappy encodes a non-empty src to a guaranteed-large-enough dst. It
  409. // assumes that the varint-encoded length of the decompressed bytes has already
  410. // been written.
  411. //
  412. // It also assumes that:
  413. //
  414. // len(dst) >= MaxEncodedLen(len(src)) &&
  415. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  416. func encodeBlockBestSnappy(dst, src []byte) (d int) {
  417. // Initialize the hash tables.
  418. const (
  419. // Long hash matches.
  420. lTableBits = 19
  421. maxLTableSize = 1 << lTableBits
  422. // Short hash matches.
  423. sTableBits = 16
  424. maxSTableSize = 1 << sTableBits
  425. inputMargin = 8 + 2
  426. )
  427. // sLimit is when to stop looking for offset/length copies. The inputMargin
  428. // lets us use a fast path for emitLiteral in the main loop, while we are
  429. // looking for copies.
  430. sLimit := len(src) - inputMargin
  431. if len(src) < minNonLiteralBlockSize {
  432. return 0
  433. }
  434. var lTable [maxLTableSize]uint64
  435. var sTable [maxSTableSize]uint64
  436. // Bail if we can't compress to at least this.
  437. dstLimit := len(src) - 5
  438. // nextEmit is where in src the next emitLiteral should start from.
  439. nextEmit := 0
  440. // The encoded form must start with a literal, as there are no previous
  441. // bytes to copy, so we start looking for hash matches at s == 1.
  442. s := 1
  443. cv := load64(src, s)
  444. // We search for a repeat at -1, but don't output repeats when nextEmit == 0
  445. repeat := 1
  446. const lowbitMask = 0xffffffff
  447. getCur := func(x uint64) int {
  448. return int(x & lowbitMask)
  449. }
  450. getPrev := func(x uint64) int {
  451. return int(x >> 32)
  452. }
  453. const maxSkip = 64
  454. for {
  455. type match struct {
  456. offset int
  457. s int
  458. length int
  459. score int
  460. }
  461. var best match
  462. for {
  463. // Next src position to check
  464. nextS := (s-nextEmit)>>8 + 1
  465. if nextS > maxSkip {
  466. nextS = s + maxSkip
  467. } else {
  468. nextS += s
  469. }
  470. if nextS > sLimit {
  471. goto emitRemainder
  472. }
  473. hashL := hash8(cv, lTableBits)
  474. hashS := hash4(cv, sTableBits)
  475. candidateL := lTable[hashL]
  476. candidateS := sTable[hashS]
  477. score := func(m match) int {
  478. // Matches that are longer forward are penalized since we must emit it as a literal.
  479. score := m.length - m.s
  480. if nextEmit == m.s {
  481. // If we do not have to emit literals, we save 1 byte
  482. score++
  483. }
  484. offset := m.s - m.offset
  485. return score - emitCopyNoRepeatSize(offset, m.length)
  486. }
  487. matchAt := func(offset, s int, first uint32) match {
  488. if best.length != 0 && best.s-best.offset == s-offset {
  489. // Don't retest if we have the same offset.
  490. return match{offset: offset, s: s}
  491. }
  492. if load32(src, offset) != first {
  493. return match{offset: offset, s: s}
  494. }
  495. m := match{offset: offset, s: s, length: 4 + offset}
  496. s += 4
  497. for s <= sLimit {
  498. if diff := load64(src, s) ^ load64(src, m.length); diff != 0 {
  499. m.length += bits.TrailingZeros64(diff) >> 3
  500. break
  501. }
  502. s += 8
  503. m.length += 8
  504. }
  505. m.length -= offset
  506. m.score = score(m)
  507. if m.score <= -m.s {
  508. // Eliminate if no savings, we might find a better one.
  509. m.length = 0
  510. }
  511. return m
  512. }
  513. bestOf := func(a, b match) match {
  514. if b.length == 0 {
  515. return a
  516. }
  517. if a.length == 0 {
  518. return b
  519. }
  520. as := a.score + b.s
  521. bs := b.score + a.s
  522. if as >= bs {
  523. return a
  524. }
  525. return b
  526. }
  527. best = bestOf(matchAt(getCur(candidateL), s, uint32(cv)), matchAt(getPrev(candidateL), s, uint32(cv)))
  528. best = bestOf(best, matchAt(getCur(candidateS), s, uint32(cv)))
  529. best = bestOf(best, matchAt(getPrev(candidateS), s, uint32(cv)))
  530. {
  531. best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8)))
  532. if best.length > 0 {
  533. // s+1
  534. nextShort := sTable[hash4(cv>>8, sTableBits)]
  535. s := s + 1
  536. cv := load64(src, s)
  537. nextLong := lTable[hash8(cv, lTableBits)]
  538. best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv)))
  539. best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv)))
  540. best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv)))
  541. best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv)))
  542. // Repeat at + 2
  543. best = bestOf(best, matchAt(s-repeat+1, s+1, uint32(cv>>8)))
  544. // s+2
  545. if true {
  546. nextShort = sTable[hash4(cv>>8, sTableBits)]
  547. s++
  548. cv = load64(src, s)
  549. nextLong = lTable[hash8(cv, lTableBits)]
  550. best = bestOf(best, matchAt(getCur(nextShort), s, uint32(cv)))
  551. best = bestOf(best, matchAt(getPrev(nextShort), s, uint32(cv)))
  552. best = bestOf(best, matchAt(getCur(nextLong), s, uint32(cv)))
  553. best = bestOf(best, matchAt(getPrev(nextLong), s, uint32(cv)))
  554. }
  555. // Search for a match at best match end, see if that is better.
  556. if sAt := best.s + best.length; sAt < sLimit {
  557. sBack := best.s
  558. backL := best.length
  559. // Load initial values
  560. cv = load64(src, sBack)
  561. // Search for mismatch
  562. next := lTable[hash8(load64(src, sAt), lTableBits)]
  563. //next := sTable[hash4(load64(src, sAt), sTableBits)]
  564. if checkAt := getCur(next) - backL; checkAt > 0 {
  565. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv)))
  566. }
  567. if checkAt := getPrev(next) - backL; checkAt > 0 {
  568. best = bestOf(best, matchAt(checkAt, sBack, uint32(cv)))
  569. }
  570. }
  571. }
  572. }
  573. // Update table
  574. lTable[hashL] = uint64(s) | candidateL<<32
  575. sTable[hashS] = uint64(s) | candidateS<<32
  576. if best.length > 0 {
  577. break
  578. }
  579. cv = load64(src, nextS)
  580. s = nextS
  581. }
  582. // Extend backwards, not needed for repeats...
  583. s = best.s
  584. if true {
  585. for best.offset > 0 && s > nextEmit && src[best.offset-1] == src[s-1] {
  586. best.offset--
  587. best.length++
  588. s--
  589. }
  590. }
  591. if false && best.offset >= s {
  592. panic(fmt.Errorf("t %d >= s %d", best.offset, s))
  593. }
  594. // Bail if we exceed the maximum size.
  595. if d+(s-nextEmit) > dstLimit {
  596. return 0
  597. }
  598. base := s
  599. offset := s - best.offset
  600. s += best.length
  601. if offset > 65535 && s-base <= 5 {
  602. // Bail if the match is equal or worse to the encoding.
  603. s = best.s + 1
  604. if s >= sLimit {
  605. goto emitRemainder
  606. }
  607. cv = load64(src, s)
  608. continue
  609. }
  610. d += emitLiteral(dst[d:], src[nextEmit:base])
  611. d += emitCopyNoRepeat(dst[d:], offset, best.length)
  612. repeat = offset
  613. nextEmit = s
  614. if s >= sLimit {
  615. goto emitRemainder
  616. }
  617. if d > dstLimit {
  618. // Do we have space for more, if not bail.
  619. return 0
  620. }
  621. // Fill tables...
  622. for i := best.s + 1; i < s; i++ {
  623. cv0 := load64(src, i)
  624. long0 := hash8(cv0, lTableBits)
  625. short0 := hash4(cv0, sTableBits)
  626. lTable[long0] = uint64(i) | lTable[long0]<<32
  627. sTable[short0] = uint64(i) | sTable[short0]<<32
  628. }
  629. cv = load64(src, s)
  630. }
  631. emitRemainder:
  632. if nextEmit < len(src) {
  633. // Bail if we exceed the maximum size.
  634. if d+len(src)-nextEmit > dstLimit {
  635. return 0
  636. }
  637. d += emitLiteral(dst[d:], src[nextEmit:])
  638. }
  639. return d
  640. }
  641. // emitCopySize returns the size to encode the offset+length
  642. //
  643. // It assumes that:
  644. //
  645. // 1 <= offset && offset <= math.MaxUint32
  646. // 4 <= length && length <= 1 << 24
  647. func emitCopySize(offset, length int) int {
  648. if offset >= 65536 {
  649. i := 0
  650. if length > 64 {
  651. length -= 64
  652. if length >= 4 {
  653. // Emit remaining as repeats
  654. return 5 + emitRepeatSize(offset, length)
  655. }
  656. i = 5
  657. }
  658. if length == 0 {
  659. return i
  660. }
  661. return i + 5
  662. }
  663. // Offset no more than 2 bytes.
  664. if length > 64 {
  665. if offset < 2048 {
  666. // Emit 8 bytes, then rest as repeats...
  667. return 2 + emitRepeatSize(offset, length-8)
  668. }
  669. // Emit remaining as repeats, at least 4 bytes remain.
  670. return 3 + emitRepeatSize(offset, length-60)
  671. }
  672. if length >= 12 || offset >= 2048 {
  673. return 3
  674. }
  675. // Emit the remaining copy, encoded as 2 bytes.
  676. return 2
  677. }
  678. // emitCopyNoRepeatSize returns the size to encode the offset+length
  679. //
  680. // It assumes that:
  681. //
  682. // 1 <= offset && offset <= math.MaxUint32
  683. // 4 <= length && length <= 1 << 24
  684. func emitCopyNoRepeatSize(offset, length int) int {
  685. if offset >= 65536 {
  686. return 5 + 5*(length/64)
  687. }
  688. // Offset no more than 2 bytes.
  689. if length > 64 {
  690. // Emit remaining as repeats, at least 4 bytes remain.
  691. return 3 + 3*(length/60)
  692. }
  693. if length >= 12 || offset >= 2048 {
  694. return 3
  695. }
  696. // Emit the remaining copy, encoded as 2 bytes.
  697. return 2
  698. }
  699. // emitRepeatSize returns the number of bytes required to encode a repeat.
  700. // Length must be at least 4 and < 1<<24
  701. func emitRepeatSize(offset, length int) int {
  702. // Repeat offset, make length cheaper
  703. if length <= 4+4 || (length < 8+4 && offset < 2048) {
  704. return 2
  705. }
  706. if length < (1<<8)+4+4 {
  707. return 3
  708. }
  709. if length < (1<<16)+(1<<8)+4 {
  710. return 4
  711. }
  712. const maxRepeat = (1 << 24) - 1
  713. length -= (1 << 16) - 4
  714. left := 0
  715. if length > maxRepeat {
  716. left = length - maxRepeat + 4
  717. }
  718. if left > 0 {
  719. return 5 + emitRepeatSize(offset, left)
  720. }
  721. return 5
  722. }