encode_better.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513
  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. "bytes"
  8. "fmt"
  9. "math/bits"
  10. )
  11. // hash4 returns the hash of the lowest 4 bytes of u to fit in a hash table with h bits.
  12. // Preferably h should be a constant and should always be <32.
  13. func hash4(u uint64, h uint8) uint32 {
  14. const prime4bytes = 2654435761
  15. return (uint32(u) * prime4bytes) >> ((32 - h) & 31)
  16. }
  17. // hash5 returns the hash of the lowest 5 bytes of u to fit in a hash table with h bits.
  18. // Preferably h should be a constant and should always be <64.
  19. func hash5(u uint64, h uint8) uint32 {
  20. const prime5bytes = 889523592379
  21. return uint32(((u << (64 - 40)) * prime5bytes) >> ((64 - h) & 63))
  22. }
  23. // hash7 returns the hash of the lowest 7 bytes of u to fit in a hash table with h bits.
  24. // Preferably h should be a constant and should always be <64.
  25. func hash7(u uint64, h uint8) uint32 {
  26. const prime7bytes = 58295818150454627
  27. return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & 63))
  28. }
  29. // hash8 returns the hash of u to fit in a hash table with h bits.
  30. // Preferably h should be a constant and should always be <64.
  31. func hash8(u uint64, h uint8) uint32 {
  32. const prime8bytes = 0xcf1bbcdcb7a56463
  33. return uint32((u * prime8bytes) >> ((64 - h) & 63))
  34. }
  35. // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It
  36. // assumes that the varint-encoded length of the decompressed bytes has already
  37. // been written.
  38. //
  39. // It also assumes that:
  40. //
  41. // len(dst) >= MaxEncodedLen(len(src)) &&
  42. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  43. func encodeBlockBetterGo(dst, src []byte) (d int) {
  44. // sLimit is when to stop looking for offset/length copies. The inputMargin
  45. // lets us use a fast path for emitLiteral in the main loop, while we are
  46. // looking for copies.
  47. sLimit := len(src) - inputMargin
  48. if len(src) < minNonLiteralBlockSize {
  49. return 0
  50. }
  51. // Initialize the hash tables.
  52. const (
  53. // Long hash matches.
  54. lTableBits = betterLongTableBits
  55. maxLTableSize = betterLongTableSize
  56. // Short hash matches.
  57. sTableBits = betterShortTableBits
  58. maxSTableSize = betterShortTableSize
  59. )
  60. tbl := getBetterTables()
  61. lTable := &tbl.lTable
  62. sTable := &tbl.sTable
  63. defer betterTablePool.Put(tbl)
  64. // Bail if we can't compress to at least this.
  65. dstLimit := len(src) - len(src)>>5 - 6
  66. // nextEmit is where in src the next emitLiteral should start from.
  67. nextEmit := 0
  68. // The encoded form must start with a literal, as there are no previous
  69. // bytes to copy, so we start looking for hash matches at s == 1.
  70. s := 1
  71. cv := load64(src, s)
  72. // We initialize repeat to 0, so we never match on first attempt
  73. repeat := 0
  74. for {
  75. candidateL := 0
  76. nextS := 0
  77. for {
  78. // Next src position to check
  79. nextS = s + (s-nextEmit)>>7 + 1
  80. if nextS > sLimit {
  81. goto emitRemainder
  82. }
  83. hashL := hash7(cv, lTableBits)
  84. hashS := hash4(cv, sTableBits)
  85. candidateL = int(lTable[hashL])
  86. candidateS := int(sTable[hashS])
  87. lTable[hashL] = uint32(s)
  88. sTable[hashS] = uint32(s)
  89. valLong := load64(src, candidateL)
  90. valShort := load64(src, candidateS)
  91. // If long matches at least 8 bytes, use that.
  92. if cv == valLong {
  93. break
  94. }
  95. if cv == valShort {
  96. candidateL = candidateS
  97. break
  98. }
  99. // Check repeat at offset checkRep.
  100. const checkRep = 1
  101. // Minimum length of a repeat. Tested with various values.
  102. // While 4-5 offers improvements in some, 6 reduces
  103. // regressions significantly.
  104. const wantRepeatBytes = 6
  105. const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep)
  106. if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask {
  107. base := s + checkRep
  108. // Extend back
  109. for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
  110. i--
  111. base--
  112. }
  113. d += emitLiteral(dst[d:], src[nextEmit:base])
  114. // Extend forward
  115. candidate := s - repeat + wantRepeatBytes + checkRep
  116. s += wantRepeatBytes + checkRep
  117. for s < len(src) {
  118. if len(src)-s < 8 {
  119. if src[s] == src[candidate] {
  120. s++
  121. candidate++
  122. continue
  123. }
  124. break
  125. }
  126. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  127. s += bits.TrailingZeros64(diff) >> 3
  128. break
  129. }
  130. s += 8
  131. candidate += 8
  132. }
  133. // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset.
  134. d += emitRepeat(dst[d:], repeat, s-base)
  135. nextEmit = s
  136. if s >= sLimit {
  137. goto emitRemainder
  138. }
  139. // Index in-between
  140. index0 := base + 1
  141. index1 := s - 2
  142. for index0 < index1 {
  143. cv0 := load64(src, index0)
  144. cv1 := load64(src, index1)
  145. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  146. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  147. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  148. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  149. index0 += 2
  150. index1 -= 2
  151. }
  152. cv = load64(src, s)
  153. continue
  154. }
  155. // Long likely matches 7, so take that.
  156. if uint32(cv) == uint32(valLong) {
  157. break
  158. }
  159. // Check our short candidate
  160. if uint32(cv) == uint32(valShort) {
  161. // Try a long candidate at s+1
  162. hashL = hash7(cv>>8, lTableBits)
  163. candidateL = int(lTable[hashL])
  164. lTable[hashL] = uint32(s + 1)
  165. if uint32(cv>>8) == load32(src, candidateL) {
  166. s++
  167. break
  168. }
  169. // Use our short candidate.
  170. candidateL = candidateS
  171. break
  172. }
  173. cv = load64(src, nextS)
  174. s = nextS
  175. }
  176. // Extend backwards
  177. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  178. candidateL--
  179. s--
  180. }
  181. // Bail if we exceed the maximum size.
  182. if d+(s-nextEmit) > dstLimit {
  183. return 0
  184. }
  185. base := s
  186. offset := base - candidateL
  187. // Extend the 4-byte match as long as possible.
  188. s += 4
  189. candidateL += 4
  190. for s < len(src) {
  191. if len(src)-s < 8 {
  192. if src[s] == src[candidateL] {
  193. s++
  194. candidateL++
  195. continue
  196. }
  197. break
  198. }
  199. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  200. s += bits.TrailingZeros64(diff) >> 3
  201. break
  202. }
  203. s += 8
  204. candidateL += 8
  205. }
  206. if offset > 65535 && s-base <= 5 && repeat != offset {
  207. // Bail if the match is equal or worse to the encoding.
  208. s = nextS + 1
  209. if s >= sLimit {
  210. goto emitRemainder
  211. }
  212. cv = load64(src, s)
  213. continue
  214. }
  215. d += emitLiteral(dst[d:], src[nextEmit:base])
  216. if repeat == offset {
  217. d += emitRepeat(dst[d:], offset, s-base)
  218. } else {
  219. d += emitCopy(dst[d:], offset, s-base)
  220. repeat = offset
  221. }
  222. nextEmit = s
  223. if s >= sLimit {
  224. goto emitRemainder
  225. }
  226. if d > dstLimit {
  227. // Do we have space for more, if not bail.
  228. return 0
  229. }
  230. // Index short & long
  231. index0 := base + 1
  232. index1 := s - 2
  233. cv0 := load64(src, index0)
  234. cv1 := load64(src, index1)
  235. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  236. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  237. // lTable could be postponed, but very minor difference.
  238. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  239. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  240. index0 += 1
  241. index1 -= 1
  242. cv = load64(src, s)
  243. // Index large values sparsely in between.
  244. // We do two starting from different offsets for speed.
  245. index2 := (index0 + index1 + 1) >> 1
  246. for index2 < index1 {
  247. lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0)
  248. lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2)
  249. index0 += 2
  250. index2 += 2
  251. }
  252. }
  253. emitRemainder:
  254. if nextEmit < len(src) {
  255. // Bail if we exceed the maximum size.
  256. if d+len(src)-nextEmit > dstLimit {
  257. return 0
  258. }
  259. d += emitLiteral(dst[d:], src[nextEmit:])
  260. }
  261. return d
  262. }
  263. // encodeBlockBetterSnappyGo encodes a non-empty src to a guaranteed-large-enough dst. It
  264. // assumes that the varint-encoded length of the decompressed bytes has already
  265. // been written.
  266. //
  267. // It also assumes that:
  268. //
  269. // len(dst) >= MaxEncodedLen(len(src)) &&
  270. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  271. func encodeBlockBetterSnappyGo(dst, src []byte) (d int) {
  272. // sLimit is when to stop looking for offset/length copies. The inputMargin
  273. // lets us use a fast path for emitLiteral in the main loop, while we are
  274. // looking for copies.
  275. sLimit := len(src) - inputMargin
  276. if len(src) < minNonLiteralBlockSize {
  277. return 0
  278. }
  279. // Initialize the hash tables.
  280. const (
  281. // Long hash matches.
  282. lTableBits = betterSnappyLongTableBits
  283. maxLTableSize = betterSnappyLongTableSize
  284. // Short hash matches.
  285. sTableBits = betterShortTableBits
  286. maxSTableSize = betterShortTableSize
  287. )
  288. tbl := getBetterSnappyTables()
  289. lTable := &tbl.lTable
  290. sTable := &tbl.sTable
  291. defer betterSnappyTablePool.Put(tbl)
  292. // Bail if we can't compress to at least this.
  293. dstLimit := len(src) - len(src)>>5 - 6
  294. // nextEmit is where in src the next emitLiteral should start from.
  295. nextEmit := 0
  296. // The encoded form must start with a literal, as there are no previous
  297. // bytes to copy, so we start looking for hash matches at s == 1.
  298. s := 1
  299. cv := load64(src, s)
  300. // We initialize repeat to 0, so we never match on first attempt
  301. repeat := 0
  302. const maxSkip = 100
  303. for {
  304. candidateL := 0
  305. nextS := 0
  306. for {
  307. // Next src position to check
  308. nextS = min(s+(s-nextEmit)>>7+1, s+maxSkip)
  309. if nextS > sLimit {
  310. goto emitRemainder
  311. }
  312. hashL := hash7(cv, lTableBits)
  313. hashS := hash4(cv, sTableBits)
  314. candidateL = int(lTable[hashL])
  315. candidateS := int(sTable[hashS])
  316. lTable[hashL] = uint32(s)
  317. sTable[hashS] = uint32(s)
  318. if uint32(cv) == load32(src, candidateL) {
  319. break
  320. }
  321. // Check our short candidate
  322. if uint32(cv) == load32(src, candidateS) {
  323. // Try a long candidate at s+1
  324. hashL = hash7(cv>>8, lTableBits)
  325. candidateL = int(lTable[hashL])
  326. lTable[hashL] = uint32(s + 1)
  327. if uint32(cv>>8) == load32(src, candidateL) {
  328. s++
  329. break
  330. }
  331. // Use our short candidate.
  332. candidateL = candidateS
  333. break
  334. }
  335. cv = load64(src, nextS)
  336. s = nextS
  337. }
  338. // Extend backwards
  339. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  340. candidateL--
  341. s--
  342. }
  343. // Bail if we exceed the maximum size.
  344. if d+(s-nextEmit) > dstLimit {
  345. return 0
  346. }
  347. base := s
  348. offset := base - candidateL
  349. // Extend the 4-byte match as long as possible.
  350. s += 4
  351. candidateL += 4
  352. for s < len(src) {
  353. if len(src)-s < 8 {
  354. if src[s] == src[candidateL] {
  355. s++
  356. candidateL++
  357. continue
  358. }
  359. break
  360. }
  361. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  362. s += bits.TrailingZeros64(diff) >> 3
  363. break
  364. }
  365. s += 8
  366. candidateL += 8
  367. }
  368. if offset > 65535 && s-base <= 5 && repeat != offset {
  369. // Bail if the match is equal or worse to the encoding.
  370. s = nextS + 1
  371. if s >= sLimit {
  372. goto emitRemainder
  373. }
  374. cv = load64(src, s)
  375. continue
  376. }
  377. d += emitLiteral(dst[d:], src[nextEmit:base])
  378. d += emitCopyNoRepeat(dst[d:], offset, s-base)
  379. repeat = offset
  380. nextEmit = s
  381. if s >= sLimit {
  382. goto emitRemainder
  383. }
  384. if d > dstLimit {
  385. // Do we have space for more, if not bail.
  386. return 0
  387. }
  388. // Index short & long
  389. index0 := base + 1
  390. index1 := s - 2
  391. cv0 := load64(src, index0)
  392. cv1 := load64(src, index1)
  393. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  394. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  395. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  396. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  397. index0 += 1
  398. index1 -= 1
  399. cv = load64(src, s)
  400. // Index large values sparsely in between.
  401. // We do two starting from different offsets for speed.
  402. index2 := (index0 + index1 + 1) >> 1
  403. for index2 < index1 {
  404. lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0)
  405. lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2)
  406. index0 += 2
  407. index2 += 2
  408. }
  409. }
  410. emitRemainder:
  411. if nextEmit < len(src) {
  412. // Bail if we exceed the maximum size.
  413. if d+len(src)-nextEmit > dstLimit {
  414. return 0
  415. }
  416. d += emitLiteral(dst[d:], src[nextEmit:])
  417. }
  418. return d
  419. }
  420. func encodeBlockBetterGo64K(dst, src []byte) (d int) {
  421. // sLimit is when to stop looking for offset/length copies. The inputMargin
  422. // lets us use a fast path for emitLiteral in the main loop, while we are
  423. // looking for copies.
  424. sLimit := len(src) - inputMargin
  425. if len(src) < minNonLiteralBlockSize {
  426. return 0
  427. }
  428. // Initialize the hash tables.
  429. // Use smaller tables for smaller blocks
  430. const (
  431. // Long hash matches.
  432. lTableBits = 16
  433. maxLTableSize = 1 << lTableBits
  434. // Short hash matches.
  435. sTableBits = 13
  436. maxSTableSize = 1 << sTableBits
  437. )
  438. var lTable [maxLTableSize]uint16
  439. var sTable [maxSTableSize]uint16
  440. // Bail if we can't compress to at least this.
  441. dstLimit := len(src) - len(src)>>5 - 6
  442. // nextEmit is where in src the next emitLiteral should start from.
  443. nextEmit := 0
  444. // The encoded form must start with a literal, as there are no previous
  445. // bytes to copy, so we start looking for hash matches at s == 1.
  446. s := 1
  447. cv := load64(src, s)
  448. // We initialize repeat to 0, so we never match on first attempt
  449. repeat := 0
  450. for {
  451. candidateL := 0
  452. nextS := 0
  453. for {
  454. // Next src position to check
  455. nextS = s + (s-nextEmit)>>6 + 1
  456. if nextS > sLimit {
  457. goto emitRemainder
  458. }
  459. hashL := hash7(cv, lTableBits)
  460. hashS := hash4(cv, sTableBits)
  461. candidateL = int(lTable[hashL])
  462. candidateS := int(sTable[hashS])
  463. lTable[hashL] = uint16(s)
  464. sTable[hashS] = uint16(s)
  465. valLong := load64(src, candidateL)
  466. valShort := load64(src, candidateS)
  467. // If long matches at least 8 bytes, use that.
  468. if cv == valLong {
  469. break
  470. }
  471. if cv == valShort {
  472. candidateL = candidateS
  473. break
  474. }
  475. // Check repeat at offset checkRep.
  476. const checkRep = 1
  477. // Minimum length of a repeat. Tested with various values.
  478. // While 4-5 offers improvements in some, 6 reduces
  479. // regressions significantly.
  480. const wantRepeatBytes = 6
  481. const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep)
  482. if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask {
  483. base := s + checkRep
  484. // Extend back
  485. for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
  486. i--
  487. base--
  488. }
  489. d += emitLiteral(dst[d:], src[nextEmit:base])
  490. // Extend forward
  491. candidate := s - repeat + wantRepeatBytes + checkRep
  492. s += wantRepeatBytes + checkRep
  493. for s < len(src) {
  494. if len(src)-s < 8 {
  495. if src[s] == src[candidate] {
  496. s++
  497. candidate++
  498. continue
  499. }
  500. break
  501. }
  502. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  503. s += bits.TrailingZeros64(diff) >> 3
  504. break
  505. }
  506. s += 8
  507. candidate += 8
  508. }
  509. // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset.
  510. d += emitRepeat(dst[d:], repeat, s-base)
  511. nextEmit = s
  512. if s >= sLimit {
  513. goto emitRemainder
  514. }
  515. // Index in-between
  516. index0 := base + 1
  517. index1 := s - 2
  518. for index0 < index1 {
  519. cv0 := load64(src, index0)
  520. cv1 := load64(src, index1)
  521. lTable[hash7(cv0, lTableBits)] = uint16(index0)
  522. sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1)
  523. lTable[hash7(cv1, lTableBits)] = uint16(index1)
  524. sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1)
  525. index0 += 2
  526. index1 -= 2
  527. }
  528. cv = load64(src, s)
  529. continue
  530. }
  531. // Long likely matches 7, so take that.
  532. if uint32(cv) == uint32(valLong) {
  533. break
  534. }
  535. // Check our short candidate
  536. if uint32(cv) == uint32(valShort) {
  537. // Try a long candidate at s+1
  538. hashL = hash7(cv>>8, lTableBits)
  539. candidateL = int(lTable[hashL])
  540. lTable[hashL] = uint16(s + 1)
  541. if uint32(cv>>8) == load32(src, candidateL) {
  542. s++
  543. break
  544. }
  545. // Use our short candidate.
  546. candidateL = candidateS
  547. break
  548. }
  549. cv = load64(src, nextS)
  550. s = nextS
  551. }
  552. // Extend backwards
  553. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  554. candidateL--
  555. s--
  556. }
  557. // Bail if we exceed the maximum size.
  558. if d+(s-nextEmit) > dstLimit {
  559. return 0
  560. }
  561. base := s
  562. offset := base - candidateL
  563. // Extend the 4-byte match as long as possible.
  564. s += 4
  565. candidateL += 4
  566. for s < len(src) {
  567. if len(src)-s < 8 {
  568. if src[s] == src[candidateL] {
  569. s++
  570. candidateL++
  571. continue
  572. }
  573. break
  574. }
  575. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  576. s += bits.TrailingZeros64(diff) >> 3
  577. break
  578. }
  579. s += 8
  580. candidateL += 8
  581. }
  582. d += emitLiteral(dst[d:], src[nextEmit:base])
  583. if repeat == offset {
  584. d += emitRepeat(dst[d:], offset, s-base)
  585. } else {
  586. d += emitCopy(dst[d:], offset, s-base)
  587. repeat = offset
  588. }
  589. nextEmit = s
  590. if s >= sLimit {
  591. goto emitRemainder
  592. }
  593. if d > dstLimit {
  594. // Do we have space for more, if not bail.
  595. return 0
  596. }
  597. // Index short & long
  598. index0 := base + 1
  599. index1 := s - 2
  600. cv0 := load64(src, index0)
  601. cv1 := load64(src, index1)
  602. lTable[hash7(cv0, lTableBits)] = uint16(index0)
  603. sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1)
  604. // lTable could be postponed, but very minor difference.
  605. lTable[hash7(cv1, lTableBits)] = uint16(index1)
  606. sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1)
  607. index0 += 1
  608. index1 -= 1
  609. cv = load64(src, s)
  610. // Index large values sparsely in between.
  611. // We do two starting from different offsets for speed.
  612. index2 := (index0 + index1 + 1) >> 1
  613. for index2 < index1 {
  614. lTable[hash7(load64(src, index0), lTableBits)] = uint16(index0)
  615. lTable[hash7(load64(src, index2), lTableBits)] = uint16(index2)
  616. index0 += 2
  617. index2 += 2
  618. }
  619. }
  620. emitRemainder:
  621. if nextEmit < len(src) {
  622. // Bail if we exceed the maximum size.
  623. if d+len(src)-nextEmit > dstLimit {
  624. return 0
  625. }
  626. d += emitLiteral(dst[d:], src[nextEmit:])
  627. }
  628. return d
  629. }
  630. // encodeBlockBetterSnappyGo encodes a non-empty src to a guaranteed-large-enough dst. It
  631. // assumes that the varint-encoded length of the decompressed bytes has already
  632. // been written.
  633. //
  634. // It also assumes that:
  635. //
  636. // len(dst) >= MaxEncodedLen(len(src)) &&
  637. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  638. func encodeBlockBetterSnappyGo64K(dst, src []byte) (d int) {
  639. // sLimit is when to stop looking for offset/length copies. The inputMargin
  640. // lets us use a fast path for emitLiteral in the main loop, while we are
  641. // looking for copies.
  642. sLimit := len(src) - inputMargin
  643. if len(src) < minNonLiteralBlockSize {
  644. return 0
  645. }
  646. // Initialize the hash tables.
  647. // Use smaller tables for smaller blocks
  648. const (
  649. // Long hash matches.
  650. lTableBits = 15
  651. maxLTableSize = 1 << lTableBits
  652. // Short hash matches.
  653. sTableBits = 13
  654. maxSTableSize = 1 << sTableBits
  655. )
  656. var lTable [maxLTableSize]uint16
  657. var sTable [maxSTableSize]uint16
  658. // Bail if we can't compress to at least this.
  659. dstLimit := len(src) - len(src)>>5 - 6
  660. // nextEmit is where in src the next emitLiteral should start from.
  661. nextEmit := 0
  662. // The encoded form must start with a literal, as there are no previous
  663. // bytes to copy, so we start looking for hash matches at s == 1.
  664. s := 1
  665. cv := load64(src, s)
  666. const maxSkip = 100
  667. for {
  668. candidateL := 0
  669. nextS := 0
  670. for {
  671. // Next src position to check
  672. nextS = min(s+(s-nextEmit)>>6+1, s+maxSkip)
  673. if nextS > sLimit {
  674. goto emitRemainder
  675. }
  676. hashL := hash7(cv, lTableBits)
  677. hashS := hash4(cv, sTableBits)
  678. candidateL = int(lTable[hashL])
  679. candidateS := int(sTable[hashS])
  680. lTable[hashL] = uint16(s)
  681. sTable[hashS] = uint16(s)
  682. if uint32(cv) == load32(src, candidateL) {
  683. break
  684. }
  685. // Check our short candidate
  686. if uint32(cv) == load32(src, candidateS) {
  687. // Try a long candidate at s+1
  688. hashL = hash7(cv>>8, lTableBits)
  689. candidateL = int(lTable[hashL])
  690. lTable[hashL] = uint16(s + 1)
  691. if uint32(cv>>8) == load32(src, candidateL) {
  692. s++
  693. break
  694. }
  695. // Use our short candidate.
  696. candidateL = candidateS
  697. break
  698. }
  699. cv = load64(src, nextS)
  700. s = nextS
  701. }
  702. // Extend backwards
  703. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  704. candidateL--
  705. s--
  706. }
  707. // Bail if we exceed the maximum size.
  708. if d+(s-nextEmit) > dstLimit {
  709. return 0
  710. }
  711. base := s
  712. offset := base - candidateL
  713. // Extend the 4-byte match as long as possible.
  714. s += 4
  715. candidateL += 4
  716. for s < len(src) {
  717. if len(src)-s < 8 {
  718. if src[s] == src[candidateL] {
  719. s++
  720. candidateL++
  721. continue
  722. }
  723. break
  724. }
  725. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  726. s += bits.TrailingZeros64(diff) >> 3
  727. break
  728. }
  729. s += 8
  730. candidateL += 8
  731. }
  732. d += emitLiteral(dst[d:], src[nextEmit:base])
  733. d += emitCopyNoRepeat(dst[d:], offset, s-base)
  734. nextEmit = s
  735. if s >= sLimit {
  736. goto emitRemainder
  737. }
  738. if d > dstLimit {
  739. // Do we have space for more, if not bail.
  740. return 0
  741. }
  742. // Index short & long
  743. index0 := base + 1
  744. index1 := s - 2
  745. cv0 := load64(src, index0)
  746. cv1 := load64(src, index1)
  747. lTable[hash7(cv0, lTableBits)] = uint16(index0)
  748. sTable[hash4(cv0>>8, sTableBits)] = uint16(index0 + 1)
  749. lTable[hash7(cv1, lTableBits)] = uint16(index1)
  750. sTable[hash4(cv1>>8, sTableBits)] = uint16(index1 + 1)
  751. index0 += 1
  752. index1 -= 1
  753. cv = load64(src, s)
  754. // Index large values sparsely in between.
  755. // We do two starting from different offsets for speed.
  756. index2 := (index0 + index1 + 1) >> 1
  757. for index2 < index1 {
  758. lTable[hash7(load64(src, index0), lTableBits)] = uint16(index0)
  759. lTable[hash7(load64(src, index2), lTableBits)] = uint16(index2)
  760. index0 += 2
  761. index2 += 2
  762. }
  763. }
  764. emitRemainder:
  765. if nextEmit < len(src) {
  766. // Bail if we exceed the maximum size.
  767. if d+len(src)-nextEmit > dstLimit {
  768. return 0
  769. }
  770. d += emitLiteral(dst[d:], src[nextEmit:])
  771. }
  772. return d
  773. }
  774. // encodeBlockBetterDict encodes a non-empty src to a guaranteed-large-enough dst. It
  775. // assumes that the varint-encoded length of the decompressed bytes has already
  776. // been written.
  777. //
  778. // It also assumes that:
  779. //
  780. // len(dst) >= MaxEncodedLen(len(src)) &&
  781. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  782. func encodeBlockBetterDict(dst, src []byte, dict *Dict) (d int) {
  783. // sLimit is when to stop looking for offset/length copies. The inputMargin
  784. // lets us use a fast path for emitLiteral in the main loop, while we are
  785. // looking for copies.
  786. // Initialize the hash tables.
  787. const (
  788. // Long hash matches.
  789. lTableBits = betterLongTableBits
  790. maxLTableSize = betterLongTableSize
  791. // Short hash matches.
  792. sTableBits = betterShortTableBits
  793. maxSTableSize = betterShortTableSize
  794. maxAhead = 8 // maximum bytes ahead without checking sLimit
  795. debug = false
  796. )
  797. sLimit := min(len(src)-inputMargin, MaxDictSrcOffset-maxAhead)
  798. if len(src) < minNonLiteralBlockSize {
  799. return 0
  800. }
  801. dict.initBetter()
  802. tbl := getBetterTables()
  803. lTable := &tbl.lTable
  804. sTable := &tbl.sTable
  805. defer betterTablePool.Put(tbl)
  806. // Bail if we can't compress to at least this.
  807. dstLimit := len(src) - len(src)>>5 - 6
  808. // nextEmit is where in src the next emitLiteral should start from.
  809. nextEmit := 0
  810. // The encoded form must start with a literal, as there are no previous
  811. // bytes to copy, so we start looking for hash matches at s == 1.
  812. s := 0
  813. cv := load64(src, s)
  814. // We initialize repeat to 0, so we never match on first attempt
  815. repeat := len(dict.dict) - dict.repeat
  816. // While in dict
  817. searchDict:
  818. for {
  819. candidateL := 0
  820. nextS := 0
  821. for {
  822. // Next src position to check
  823. nextS = s + (s-nextEmit)>>7 + 1
  824. if nextS > sLimit {
  825. break searchDict
  826. }
  827. hashL := hash7(cv, lTableBits)
  828. hashS := hash4(cv, sTableBits)
  829. candidateL = int(lTable[hashL])
  830. candidateS := int(sTable[hashS])
  831. dictL := int(dict.betterTableLong[hashL])
  832. dictS := int(dict.betterTableShort[hashS])
  833. lTable[hashL] = uint32(s)
  834. sTable[hashS] = uint32(s)
  835. valLong := load64(src, candidateL)
  836. valShort := load64(src, candidateS)
  837. // If long matches at least 8 bytes, use that.
  838. if s != 0 {
  839. if cv == valLong {
  840. goto emitMatch
  841. }
  842. if cv == valShort {
  843. candidateL = candidateS
  844. goto emitMatch
  845. }
  846. }
  847. // Check dict repeat.
  848. if repeat >= s+4 {
  849. candidate := len(dict.dict) - repeat + s
  850. if candidate > 0 && uint32(cv) == load32(dict.dict, candidate) {
  851. // Extend back
  852. base := s
  853. for i := candidate; base > nextEmit && i > 0 && dict.dict[i-1] == src[base-1]; {
  854. i--
  855. base--
  856. }
  857. d += emitLiteral(dst[d:], src[nextEmit:base])
  858. if debug && nextEmit != base {
  859. fmt.Println("emitted ", base-nextEmit, "literals")
  860. }
  861. s += 4
  862. candidate += 4
  863. for candidate < len(dict.dict)-8 && s <= len(src)-8 {
  864. if diff := load64(src, s) ^ load64(dict.dict, candidate); diff != 0 {
  865. s += bits.TrailingZeros64(diff) >> 3
  866. break
  867. }
  868. s += 8
  869. candidate += 8
  870. }
  871. d += emitRepeat(dst[d:], repeat, s-base)
  872. if debug {
  873. fmt.Println("emitted dict repeat length", s-base, "offset:", repeat, "s:", s)
  874. }
  875. nextEmit = s
  876. if s >= sLimit {
  877. break searchDict
  878. }
  879. // Index in-between
  880. index0 := base + 1
  881. index1 := s - 2
  882. cv = load64(src, s)
  883. for index0 < index1 {
  884. cv0 := load64(src, index0)
  885. cv1 := load64(src, index1)
  886. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  887. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  888. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  889. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  890. index0 += 2
  891. index1 -= 2
  892. }
  893. continue
  894. }
  895. }
  896. // Don't try to find match at s==0
  897. if s == 0 {
  898. cv = load64(src, nextS)
  899. s = nextS
  900. continue
  901. }
  902. // Long likely matches 7, so take that.
  903. if uint32(cv) == uint32(valLong) {
  904. goto emitMatch
  905. }
  906. // Long dict...
  907. if uint32(cv) == load32(dict.dict, dictL) {
  908. candidateL = dictL
  909. goto emitDict
  910. }
  911. // Check our short candidate
  912. if uint32(cv) == uint32(valShort) {
  913. // Try a long candidate at s+1
  914. hashL = hash7(cv>>8, lTableBits)
  915. candidateL = int(lTable[hashL])
  916. lTable[hashL] = uint32(s + 1)
  917. if uint32(cv>>8) == load32(src, candidateL) {
  918. s++
  919. goto emitMatch
  920. }
  921. // Use our short candidate.
  922. candidateL = candidateS
  923. goto emitMatch
  924. }
  925. if uint32(cv) == load32(dict.dict, dictS) {
  926. // Try a long candidate at s+1
  927. hashL = hash7(cv>>8, lTableBits)
  928. candidateL = int(lTable[hashL])
  929. lTable[hashL] = uint32(s + 1)
  930. if uint32(cv>>8) == load32(src, candidateL) {
  931. s++
  932. goto emitMatch
  933. }
  934. candidateL = dictS
  935. goto emitDict
  936. }
  937. cv = load64(src, nextS)
  938. s = nextS
  939. }
  940. emitDict:
  941. {
  942. if debug {
  943. if load32(dict.dict, candidateL) != load32(src, s) {
  944. panic("dict emit mismatch")
  945. }
  946. }
  947. // Extend backwards.
  948. // The top bytes will be rechecked to get the full match.
  949. for candidateL > 0 && s > nextEmit && dict.dict[candidateL-1] == src[s-1] {
  950. candidateL--
  951. s--
  952. }
  953. // Bail if we exceed the maximum size.
  954. if d+(s-nextEmit) > dstLimit {
  955. return 0
  956. }
  957. // A 4-byte match has been found. We'll later see if more than 4 bytes
  958. // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
  959. // them as literal bytes.
  960. d += emitLiteral(dst[d:], src[nextEmit:s])
  961. if debug && nextEmit != s {
  962. fmt.Println("emitted ", s-nextEmit, "literals")
  963. }
  964. {
  965. // Invariant: we have a 4-byte match at s, and no need to emit any
  966. // literal bytes prior to s.
  967. base := s
  968. offset := s + (len(dict.dict)) - candidateL
  969. // Extend the 4-byte match as long as possible.
  970. s += 4
  971. candidateL += 4
  972. for s <= len(src)-8 && len(dict.dict)-candidateL >= 8 {
  973. if diff := load64(src, s) ^ load64(dict.dict, candidateL); diff != 0 {
  974. s += bits.TrailingZeros64(diff) >> 3
  975. break
  976. }
  977. s += 8
  978. candidateL += 8
  979. }
  980. if repeat == offset {
  981. if debug {
  982. fmt.Println("emitted dict repeat, length", s-base, "offset:", offset, "s:", s, "dict offset:", candidateL)
  983. }
  984. d += emitRepeat(dst[d:], offset, s-base)
  985. } else {
  986. if debug {
  987. fmt.Println("emitted dict copy, length", s-base, "offset:", offset, "s:", s, "dict offset:", candidateL)
  988. }
  989. // Matches longer than 64 are split.
  990. if s <= sLimit || s-base < 8 {
  991. d += emitCopy(dst[d:], offset, s-base)
  992. } else {
  993. // Split to ensure we don't start a copy within next block.
  994. d += emitCopy(dst[d:], offset, 4)
  995. d += emitRepeat(dst[d:], offset, s-base-4)
  996. }
  997. repeat = offset
  998. }
  999. if false {
  1000. // Validate match.
  1001. if s <= candidateL {
  1002. panic("s <= candidate")
  1003. }
  1004. a := src[base:s]
  1005. b := dict.dict[base-repeat : base-repeat+(s-base)]
  1006. if !bytes.Equal(a, b) {
  1007. panic("mismatch")
  1008. }
  1009. }
  1010. nextEmit = s
  1011. if s >= sLimit {
  1012. break searchDict
  1013. }
  1014. if d > dstLimit {
  1015. // Do we have space for more, if not bail.
  1016. return 0
  1017. }
  1018. // Index short & long
  1019. index0 := base + 1
  1020. index1 := s - 2
  1021. cv0 := load64(src, index0)
  1022. cv1 := load64(src, index1)
  1023. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  1024. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  1025. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  1026. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  1027. index0 += 1
  1028. index1 -= 1
  1029. cv = load64(src, s)
  1030. // index every second long in between.
  1031. for index0 < index1 {
  1032. lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0)
  1033. lTable[hash7(load64(src, index1), lTableBits)] = uint32(index1)
  1034. index0 += 2
  1035. index1 -= 2
  1036. }
  1037. }
  1038. continue
  1039. }
  1040. emitMatch:
  1041. // Extend backwards
  1042. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  1043. candidateL--
  1044. s--
  1045. }
  1046. // Bail if we exceed the maximum size.
  1047. if d+(s-nextEmit) > dstLimit {
  1048. return 0
  1049. }
  1050. base := s
  1051. offset := base - candidateL
  1052. // Extend the 4-byte match as long as possible.
  1053. s += 4
  1054. candidateL += 4
  1055. for s < len(src) {
  1056. if len(src)-s < 8 {
  1057. if src[s] == src[candidateL] {
  1058. s++
  1059. candidateL++
  1060. continue
  1061. }
  1062. break
  1063. }
  1064. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  1065. s += bits.TrailingZeros64(diff) >> 3
  1066. break
  1067. }
  1068. s += 8
  1069. candidateL += 8
  1070. }
  1071. if offset > 65535 && s-base <= 5 && repeat != offset {
  1072. // Bail if the match is equal or worse to the encoding.
  1073. s = nextS + 1
  1074. if s >= sLimit {
  1075. goto emitRemainder
  1076. }
  1077. cv = load64(src, s)
  1078. continue
  1079. }
  1080. d += emitLiteral(dst[d:], src[nextEmit:base])
  1081. if debug && nextEmit != s {
  1082. fmt.Println("emitted ", s-nextEmit, "literals")
  1083. }
  1084. if repeat == offset {
  1085. if debug {
  1086. fmt.Println("emitted match repeat, length", s-base, "offset:", offset, "s:", s)
  1087. }
  1088. d += emitRepeat(dst[d:], offset, s-base)
  1089. } else {
  1090. if debug {
  1091. fmt.Println("emitted match copy, length", s-base, "offset:", offset, "s:", s)
  1092. }
  1093. d += emitCopy(dst[d:], offset, s-base)
  1094. repeat = offset
  1095. }
  1096. nextEmit = s
  1097. if s >= sLimit {
  1098. goto emitRemainder
  1099. }
  1100. if d > dstLimit {
  1101. // Do we have space for more, if not bail.
  1102. return 0
  1103. }
  1104. // Index short & long
  1105. index0 := base + 1
  1106. index1 := s - 2
  1107. cv0 := load64(src, index0)
  1108. cv1 := load64(src, index1)
  1109. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  1110. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  1111. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  1112. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  1113. index0 += 1
  1114. index1 -= 1
  1115. cv = load64(src, s)
  1116. // Index large values sparsely in between.
  1117. // We do two starting from different offsets for speed.
  1118. index2 := (index0 + index1 + 1) >> 1
  1119. for index2 < index1 {
  1120. lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0)
  1121. lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2)
  1122. index0 += 2
  1123. index2 += 2
  1124. }
  1125. }
  1126. // Search without dict:
  1127. if repeat > s {
  1128. repeat = 0
  1129. }
  1130. // No more dict
  1131. sLimit = len(src) - inputMargin
  1132. if s >= sLimit {
  1133. goto emitRemainder
  1134. }
  1135. cv = load64(src, s)
  1136. if debug {
  1137. fmt.Println("now", s, "->", sLimit, "out:", d, "left:", len(src)-s, "nextemit:", nextEmit, "dstLimit:", dstLimit, "s:", s)
  1138. }
  1139. for {
  1140. candidateL := 0
  1141. nextS := 0
  1142. for {
  1143. // Next src position to check
  1144. nextS = s + (s-nextEmit)>>7 + 1
  1145. if nextS > sLimit {
  1146. goto emitRemainder
  1147. }
  1148. hashL := hash7(cv, lTableBits)
  1149. hashS := hash4(cv, sTableBits)
  1150. candidateL = int(lTable[hashL])
  1151. candidateS := int(sTable[hashS])
  1152. lTable[hashL] = uint32(s)
  1153. sTable[hashS] = uint32(s)
  1154. valLong := load64(src, candidateL)
  1155. valShort := load64(src, candidateS)
  1156. // If long matches at least 8 bytes, use that.
  1157. if cv == valLong {
  1158. break
  1159. }
  1160. if cv == valShort {
  1161. candidateL = candidateS
  1162. break
  1163. }
  1164. // Check repeat at offset checkRep.
  1165. const checkRep = 1
  1166. // Minimum length of a repeat. Tested with various values.
  1167. // While 4-5 offers improvements in some, 6 reduces
  1168. // regressions significantly.
  1169. const wantRepeatBytes = 6
  1170. const repeatMask = ((1 << (wantRepeatBytes * 8)) - 1) << (8 * checkRep)
  1171. if false && repeat > 0 && cv&repeatMask == load64(src, s-repeat)&repeatMask {
  1172. base := s + checkRep
  1173. // Extend back
  1174. for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
  1175. i--
  1176. base--
  1177. }
  1178. d += emitLiteral(dst[d:], src[nextEmit:base])
  1179. // Extend forward
  1180. candidate := s - repeat + wantRepeatBytes + checkRep
  1181. s += wantRepeatBytes + checkRep
  1182. for s < len(src) {
  1183. if len(src)-s < 8 {
  1184. if src[s] == src[candidate] {
  1185. s++
  1186. candidate++
  1187. continue
  1188. }
  1189. break
  1190. }
  1191. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  1192. s += bits.TrailingZeros64(diff) >> 3
  1193. break
  1194. }
  1195. s += 8
  1196. candidate += 8
  1197. }
  1198. // same as `add := emitCopy(dst[d:], repeat, s-base)` but skips storing offset.
  1199. d += emitRepeat(dst[d:], repeat, s-base)
  1200. nextEmit = s
  1201. if s >= sLimit {
  1202. goto emitRemainder
  1203. }
  1204. // Index in-between
  1205. index0 := base + 1
  1206. index1 := s - 2
  1207. for index0 < index1 {
  1208. cv0 := load64(src, index0)
  1209. cv1 := load64(src, index1)
  1210. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  1211. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  1212. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  1213. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  1214. index0 += 2
  1215. index1 -= 2
  1216. }
  1217. cv = load64(src, s)
  1218. continue
  1219. }
  1220. // Long likely matches 7, so take that.
  1221. if uint32(cv) == uint32(valLong) {
  1222. break
  1223. }
  1224. // Check our short candidate
  1225. if uint32(cv) == uint32(valShort) {
  1226. // Try a long candidate at s+1
  1227. hashL = hash7(cv>>8, lTableBits)
  1228. candidateL = int(lTable[hashL])
  1229. lTable[hashL] = uint32(s + 1)
  1230. if uint32(cv>>8) == load32(src, candidateL) {
  1231. s++
  1232. break
  1233. }
  1234. // Use our short candidate.
  1235. candidateL = candidateS
  1236. break
  1237. }
  1238. cv = load64(src, nextS)
  1239. s = nextS
  1240. }
  1241. // Extend backwards
  1242. for candidateL > 0 && s > nextEmit && src[candidateL-1] == src[s-1] {
  1243. candidateL--
  1244. s--
  1245. }
  1246. // Bail if we exceed the maximum size.
  1247. if d+(s-nextEmit) > dstLimit {
  1248. return 0
  1249. }
  1250. base := s
  1251. offset := base - candidateL
  1252. // Extend the 4-byte match as long as possible.
  1253. s += 4
  1254. candidateL += 4
  1255. for s < len(src) {
  1256. if len(src)-s < 8 {
  1257. if src[s] == src[candidateL] {
  1258. s++
  1259. candidateL++
  1260. continue
  1261. }
  1262. break
  1263. }
  1264. if diff := load64(src, s) ^ load64(src, candidateL); diff != 0 {
  1265. s += bits.TrailingZeros64(diff) >> 3
  1266. break
  1267. }
  1268. s += 8
  1269. candidateL += 8
  1270. }
  1271. if offset > 65535 && s-base <= 5 && repeat != offset {
  1272. // Bail if the match is equal or worse to the encoding.
  1273. s = nextS + 1
  1274. if s >= sLimit {
  1275. goto emitRemainder
  1276. }
  1277. cv = load64(src, s)
  1278. continue
  1279. }
  1280. d += emitLiteral(dst[d:], src[nextEmit:base])
  1281. if repeat == offset {
  1282. d += emitRepeat(dst[d:], offset, s-base)
  1283. } else {
  1284. d += emitCopy(dst[d:], offset, s-base)
  1285. repeat = offset
  1286. }
  1287. nextEmit = s
  1288. if s >= sLimit {
  1289. goto emitRemainder
  1290. }
  1291. if d > dstLimit {
  1292. // Do we have space for more, if not bail.
  1293. return 0
  1294. }
  1295. // Index short & long
  1296. index0 := base + 1
  1297. index1 := s - 2
  1298. cv0 := load64(src, index0)
  1299. cv1 := load64(src, index1)
  1300. lTable[hash7(cv0, lTableBits)] = uint32(index0)
  1301. sTable[hash4(cv0>>8, sTableBits)] = uint32(index0 + 1)
  1302. lTable[hash7(cv1, lTableBits)] = uint32(index1)
  1303. sTable[hash4(cv1>>8, sTableBits)] = uint32(index1 + 1)
  1304. index0 += 1
  1305. index1 -= 1
  1306. cv = load64(src, s)
  1307. // Index large values sparsely in between.
  1308. // We do two starting from different offsets for speed.
  1309. index2 := (index0 + index1 + 1) >> 1
  1310. for index2 < index1 {
  1311. lTable[hash7(load64(src, index0), lTableBits)] = uint32(index0)
  1312. lTable[hash7(load64(src, index2), lTableBits)] = uint32(index2)
  1313. index0 += 2
  1314. index2 += 2
  1315. }
  1316. }
  1317. emitRemainder:
  1318. if nextEmit < len(src) {
  1319. // Bail if we exceed the maximum size.
  1320. if d+len(src)-nextEmit > dstLimit {
  1321. return 0
  1322. }
  1323. d += emitLiteral(dst[d:], src[nextEmit:])
  1324. }
  1325. return d
  1326. }