encode_go.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. //go:build !amd64 || appengine || !gc || noasm
  2. package s2
  3. import (
  4. "bytes"
  5. "math/bits"
  6. )
  7. const hasAmd64Asm = false
  8. // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
  9. // assumes that the varint-encoded length of the decompressed bytes has already
  10. // been written.
  11. //
  12. // It also assumes that:
  13. //
  14. // len(dst) >= MaxEncodedLen(len(src))
  15. func encodeBlock(dst, src []byte) (d int) {
  16. if len(src) < minNonLiteralBlockSize {
  17. return 0
  18. }
  19. if len(src) <= 64<<10 {
  20. return encodeBlockGo64K(dst, src)
  21. }
  22. return encodeBlockGo(dst, src)
  23. }
  24. // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It
  25. // assumes that the varint-encoded length of the decompressed bytes has already
  26. // been written.
  27. //
  28. // It also assumes that:
  29. //
  30. // len(dst) >= MaxEncodedLen(len(src))
  31. func encodeBlockBetter(dst, src []byte) (d int) {
  32. if len(src) <= 64<<10 {
  33. return encodeBlockBetterGo64K(dst, src)
  34. }
  35. return encodeBlockBetterGo(dst, src)
  36. }
  37. // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It
  38. // assumes that the varint-encoded length of the decompressed bytes has already
  39. // been written.
  40. //
  41. // It also assumes that:
  42. //
  43. // len(dst) >= MaxEncodedLen(len(src))
  44. func encodeBlockBetterSnappy(dst, src []byte) (d int) {
  45. if len(src) <= 64<<10 {
  46. return encodeBlockBetterSnappyGo64K(dst, src)
  47. }
  48. return encodeBlockBetterSnappyGo(dst, src)
  49. }
  50. // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
  51. // assumes that the varint-encoded length of the decompressed bytes has already
  52. // been written.
  53. //
  54. // It also assumes that:
  55. //
  56. // len(dst) >= MaxEncodedLen(len(src))
  57. func encodeBlockSnappy(dst, src []byte) (d int) {
  58. if len(src) < minNonLiteralBlockSize {
  59. return 0
  60. }
  61. if len(src) <= 64<<10 {
  62. return encodeBlockSnappyGo64K(dst, src)
  63. }
  64. return encodeBlockSnappyGo(dst, src)
  65. }
  66. // emitLiteral writes a literal chunk and returns the number of bytes written.
  67. //
  68. // It assumes that:
  69. //
  70. // dst is long enough to hold the encoded bytes
  71. // 0 <= len(lit) && len(lit) <= math.MaxUint32
  72. func emitLiteral(dst, lit []byte) int {
  73. if len(lit) == 0 {
  74. return 0
  75. }
  76. const num = 63<<2 | tagLiteral
  77. i, n := 0, uint(len(lit)-1)
  78. switch {
  79. case n < 60:
  80. dst[0] = uint8(n)<<2 | tagLiteral
  81. i = 1
  82. case n < 1<<8:
  83. dst[1] = uint8(n)
  84. dst[0] = 60<<2 | tagLiteral
  85. i = 2
  86. case n < 1<<16:
  87. dst[2] = uint8(n >> 8)
  88. dst[1] = uint8(n)
  89. dst[0] = 61<<2 | tagLiteral
  90. i = 3
  91. case n < 1<<24:
  92. dst[3] = uint8(n >> 16)
  93. dst[2] = uint8(n >> 8)
  94. dst[1] = uint8(n)
  95. dst[0] = 62<<2 | tagLiteral
  96. i = 4
  97. default:
  98. dst[4] = uint8(n >> 24)
  99. dst[3] = uint8(n >> 16)
  100. dst[2] = uint8(n >> 8)
  101. dst[1] = uint8(n)
  102. dst[0] = 63<<2 | tagLiteral
  103. i = 5
  104. }
  105. return i + copy(dst[i:], lit)
  106. }
  107. // emitRepeat writes a repeat chunk and returns the number of bytes written.
  108. // Length must be at least 4 and < 1<<24
  109. func emitRepeat(dst []byte, offset, length int) int {
  110. // Repeat offset, make length cheaper
  111. length -= 4
  112. if length <= 4 {
  113. dst[0] = uint8(length)<<2 | tagCopy1
  114. dst[1] = 0
  115. return 2
  116. }
  117. if length < 8 && offset < 2048 {
  118. // Encode WITH offset
  119. dst[1] = uint8(offset)
  120. dst[0] = uint8(offset>>8)<<5 | uint8(length)<<2 | tagCopy1
  121. return 2
  122. }
  123. if length < (1<<8)+4 {
  124. length -= 4
  125. dst[2] = uint8(length)
  126. dst[1] = 0
  127. dst[0] = 5<<2 | tagCopy1
  128. return 3
  129. }
  130. if length < (1<<16)+(1<<8) {
  131. length -= 1 << 8
  132. dst[3] = uint8(length >> 8)
  133. dst[2] = uint8(length >> 0)
  134. dst[1] = 0
  135. dst[0] = 6<<2 | tagCopy1
  136. return 4
  137. }
  138. const maxRepeat = (1 << 24) - 1
  139. length -= 1 << 16
  140. left := 0
  141. if length > maxRepeat {
  142. left = length - maxRepeat + 4
  143. length = maxRepeat - 4
  144. }
  145. dst[4] = uint8(length >> 16)
  146. dst[3] = uint8(length >> 8)
  147. dst[2] = uint8(length >> 0)
  148. dst[1] = 0
  149. dst[0] = 7<<2 | tagCopy1
  150. if left > 0 {
  151. return 5 + emitRepeat(dst[5:], offset, left)
  152. }
  153. return 5
  154. }
  155. // emitCopy writes a copy chunk and returns the number of bytes written.
  156. //
  157. // It assumes that:
  158. //
  159. // dst is long enough to hold the encoded bytes
  160. // 1 <= offset && offset <= math.MaxUint32
  161. // 4 <= length && length <= 1 << 24
  162. func emitCopy(dst []byte, offset, length int) int {
  163. if offset >= 65536 {
  164. i := 0
  165. if length > 64 {
  166. // Emit a length 64 copy, encoded as 5 bytes.
  167. dst[4] = uint8(offset >> 24)
  168. dst[3] = uint8(offset >> 16)
  169. dst[2] = uint8(offset >> 8)
  170. dst[1] = uint8(offset)
  171. dst[0] = 63<<2 | tagCopy4
  172. length -= 64
  173. if length >= 4 {
  174. // Emit remaining as repeats
  175. return 5 + emitRepeat(dst[5:], offset, length)
  176. }
  177. i = 5
  178. }
  179. if length == 0 {
  180. return i
  181. }
  182. // Emit a copy, offset encoded as 4 bytes.
  183. dst[i+0] = uint8(length-1)<<2 | tagCopy4
  184. dst[i+1] = uint8(offset)
  185. dst[i+2] = uint8(offset >> 8)
  186. dst[i+3] = uint8(offset >> 16)
  187. dst[i+4] = uint8(offset >> 24)
  188. return i + 5
  189. }
  190. // Offset no more than 2 bytes.
  191. if length > 64 {
  192. off := 3
  193. if offset < 2048 {
  194. // emit 8 bytes as tagCopy1, rest as repeats.
  195. dst[1] = uint8(offset)
  196. dst[0] = uint8(offset>>8)<<5 | uint8(8-4)<<2 | tagCopy1
  197. length -= 8
  198. off = 2
  199. } else {
  200. // Emit a length 60 copy, encoded as 3 bytes.
  201. // Emit remaining as repeat value (minimum 4 bytes).
  202. dst[2] = uint8(offset >> 8)
  203. dst[1] = uint8(offset)
  204. dst[0] = 59<<2 | tagCopy2
  205. length -= 60
  206. }
  207. // Emit remaining as repeats, at least 4 bytes remain.
  208. return off + emitRepeat(dst[off:], offset, length)
  209. }
  210. if length >= 12 || offset >= 2048 {
  211. // Emit the remaining copy, encoded as 3 bytes.
  212. dst[2] = uint8(offset >> 8)
  213. dst[1] = uint8(offset)
  214. dst[0] = uint8(length-1)<<2 | tagCopy2
  215. return 3
  216. }
  217. // Emit the remaining copy, encoded as 2 bytes.
  218. dst[1] = uint8(offset)
  219. dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1
  220. return 2
  221. }
  222. // emitCopyNoRepeat writes a copy chunk and returns the number of bytes written.
  223. //
  224. // It assumes that:
  225. //
  226. // dst is long enough to hold the encoded bytes
  227. // 1 <= offset && offset <= math.MaxUint32
  228. // 4 <= length && length <= 1 << 24
  229. func emitCopyNoRepeat(dst []byte, offset, length int) int {
  230. if offset >= 65536 {
  231. i := 0
  232. if length > 64 {
  233. // Emit a length 64 copy, encoded as 5 bytes.
  234. dst[4] = uint8(offset >> 24)
  235. dst[3] = uint8(offset >> 16)
  236. dst[2] = uint8(offset >> 8)
  237. dst[1] = uint8(offset)
  238. dst[0] = 63<<2 | tagCopy4
  239. length -= 64
  240. if length >= 4 {
  241. // Emit remaining as repeats
  242. return 5 + emitCopyNoRepeat(dst[5:], offset, length)
  243. }
  244. i = 5
  245. }
  246. if length == 0 {
  247. return i
  248. }
  249. // Emit a copy, offset encoded as 4 bytes.
  250. dst[i+0] = uint8(length-1)<<2 | tagCopy4
  251. dst[i+1] = uint8(offset)
  252. dst[i+2] = uint8(offset >> 8)
  253. dst[i+3] = uint8(offset >> 16)
  254. dst[i+4] = uint8(offset >> 24)
  255. return i + 5
  256. }
  257. // Offset no more than 2 bytes.
  258. if length > 64 {
  259. // Emit a length 60 copy, encoded as 3 bytes.
  260. // Emit remaining as repeat value (minimum 4 bytes).
  261. dst[2] = uint8(offset >> 8)
  262. dst[1] = uint8(offset)
  263. dst[0] = 59<<2 | tagCopy2
  264. length -= 60
  265. // Emit remaining as repeats, at least 4 bytes remain.
  266. return 3 + emitCopyNoRepeat(dst[3:], offset, length)
  267. }
  268. if length >= 12 || offset >= 2048 {
  269. // Emit the remaining copy, encoded as 3 bytes.
  270. dst[2] = uint8(offset >> 8)
  271. dst[1] = uint8(offset)
  272. dst[0] = uint8(length-1)<<2 | tagCopy2
  273. return 3
  274. }
  275. // Emit the remaining copy, encoded as 2 bytes.
  276. dst[1] = uint8(offset)
  277. dst[0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1
  278. return 2
  279. }
  280. // matchLen returns how many bytes match in a and b
  281. //
  282. // It assumes that:
  283. //
  284. // len(a) <= len(b)
  285. func matchLen(a []byte, b []byte) int {
  286. b = b[:len(a)]
  287. var checked int
  288. if len(a) > 4 {
  289. // Try 4 bytes first
  290. if diff := load32(a, 0) ^ load32(b, 0); diff != 0 {
  291. return bits.TrailingZeros32(diff) >> 3
  292. }
  293. // Switch to 8 byte matching.
  294. checked = 4
  295. a = a[4:]
  296. b = b[4:]
  297. for len(a) >= 8 {
  298. b = b[:len(a)]
  299. if diff := load64(a, 0) ^ load64(b, 0); diff != 0 {
  300. return checked + (bits.TrailingZeros64(diff) >> 3)
  301. }
  302. checked += 8
  303. a = a[8:]
  304. b = b[8:]
  305. }
  306. }
  307. b = b[:len(a)]
  308. for i := range a {
  309. if a[i] != b[i] {
  310. return int(i) + checked
  311. }
  312. }
  313. return len(a) + checked
  314. }
  315. // input must be > inputMargin
  316. func calcBlockSize(src []byte, _ *[32768]byte) (d int) {
  317. // Initialize the hash table.
  318. const (
  319. tableBits = 13
  320. maxTableSize = 1 << tableBits
  321. )
  322. var table [maxTableSize]uint32
  323. // sLimit is when to stop looking for offset/length copies. The inputMargin
  324. // lets us use a fast path for emitLiteral in the main loop, while we are
  325. // looking for copies.
  326. sLimit := len(src) - inputMargin
  327. // Bail if we can't compress to at least this.
  328. dstLimit := len(src) - len(src)>>5 - 5
  329. // nextEmit is where in src the next emitLiteral should start from.
  330. nextEmit := 0
  331. // The encoded form must start with a literal, as there are no previous
  332. // bytes to copy, so we start looking for hash matches at s == 1.
  333. s := 1
  334. cv := load64(src, s)
  335. // We search for a repeat at -1, but don't output repeats when nextEmit == 0
  336. repeat := 1
  337. for {
  338. candidate := 0
  339. for {
  340. // Next src position to check
  341. nextS := s + (s-nextEmit)>>6 + 4
  342. if nextS > sLimit {
  343. goto emitRemainder
  344. }
  345. hash0 := hash6(cv, tableBits)
  346. hash1 := hash6(cv>>8, tableBits)
  347. candidate = int(table[hash0])
  348. candidate2 := int(table[hash1])
  349. table[hash0] = uint32(s)
  350. table[hash1] = uint32(s + 1)
  351. hash2 := hash6(cv>>16, tableBits)
  352. // Check repeat at offset checkRep.
  353. const checkRep = 1
  354. if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
  355. base := s + checkRep
  356. // Extend back
  357. for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
  358. i--
  359. base--
  360. }
  361. d += emitLiteralSize(src[nextEmit:base])
  362. // Extend forward
  363. candidate := s - repeat + 4 + checkRep
  364. s += 4 + checkRep
  365. for s <= sLimit {
  366. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  367. s += bits.TrailingZeros64(diff) >> 3
  368. break
  369. }
  370. s += 8
  371. candidate += 8
  372. }
  373. d += emitCopyNoRepeatSize(repeat, s-base)
  374. nextEmit = s
  375. if s >= sLimit {
  376. goto emitRemainder
  377. }
  378. cv = load64(src, s)
  379. continue
  380. }
  381. if uint32(cv) == load32(src, candidate) {
  382. break
  383. }
  384. candidate = int(table[hash2])
  385. if uint32(cv>>8) == load32(src, candidate2) {
  386. table[hash2] = uint32(s + 2)
  387. candidate = candidate2
  388. s++
  389. break
  390. }
  391. table[hash2] = uint32(s + 2)
  392. if uint32(cv>>16) == load32(src, candidate) {
  393. s += 2
  394. break
  395. }
  396. cv = load64(src, nextS)
  397. s = nextS
  398. }
  399. // Extend backwards
  400. for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] {
  401. candidate--
  402. s--
  403. }
  404. // Bail if we exceed the maximum size.
  405. if d+(s-nextEmit) > dstLimit {
  406. return 0
  407. }
  408. // A 4-byte match has been found. We'll later see if more than 4 bytes
  409. // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
  410. // them as literal bytes.
  411. d += emitLiteralSize(src[nextEmit:s])
  412. // Call emitCopy, and then see if another emitCopy could be our next
  413. // move. Repeat until we find no match for the input immediately after
  414. // what was consumed by the last emitCopy call.
  415. //
  416. // If we exit this loop normally then we need to call emitLiteral next,
  417. // though we don't yet know how big the literal will be. We handle that
  418. // by proceeding to the next iteration of the main loop. We also can
  419. // exit this loop via goto if we get close to exhausting the input.
  420. for {
  421. // Invariant: we have a 4-byte match at s, and no need to emit any
  422. // literal bytes prior to s.
  423. base := s
  424. repeat = base - candidate
  425. // Extend the 4-byte match as long as possible.
  426. s += 4
  427. candidate += 4
  428. for s <= len(src)-8 {
  429. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  430. s += bits.TrailingZeros64(diff) >> 3
  431. break
  432. }
  433. s += 8
  434. candidate += 8
  435. }
  436. d += emitCopyNoRepeatSize(repeat, s-base)
  437. if false {
  438. // Validate match.
  439. a := src[base:s]
  440. b := src[base-repeat : base-repeat+(s-base)]
  441. if !bytes.Equal(a, b) {
  442. panic("mismatch")
  443. }
  444. }
  445. nextEmit = s
  446. if s >= sLimit {
  447. goto emitRemainder
  448. }
  449. if d > dstLimit {
  450. // Do we have space for more, if not bail.
  451. return 0
  452. }
  453. // Check for an immediate match, otherwise start search at s+1
  454. x := load64(src, s-2)
  455. m2Hash := hash6(x, tableBits)
  456. currHash := hash6(x>>16, tableBits)
  457. candidate = int(table[currHash])
  458. table[m2Hash] = uint32(s - 2)
  459. table[currHash] = uint32(s)
  460. if uint32(x>>16) != load32(src, candidate) {
  461. cv = load64(src, s+1)
  462. s++
  463. break
  464. }
  465. }
  466. }
  467. emitRemainder:
  468. if nextEmit < len(src) {
  469. // Bail if we exceed the maximum size.
  470. if d+len(src)-nextEmit > dstLimit {
  471. return 0
  472. }
  473. d += emitLiteralSize(src[nextEmit:])
  474. }
  475. return d
  476. }
  477. // length must be > inputMargin.
  478. func calcBlockSizeSmall(src []byte, _ *[2048]byte) (d int) {
  479. // Initialize the hash table.
  480. const (
  481. tableBits = 9
  482. maxTableSize = 1 << tableBits
  483. )
  484. var table [maxTableSize]uint32
  485. // sLimit is when to stop looking for offset/length copies. The inputMargin
  486. // lets us use a fast path for emitLiteral in the main loop, while we are
  487. // looking for copies.
  488. sLimit := len(src) - inputMargin
  489. // Bail if we can't compress to at least this.
  490. dstLimit := len(src) - len(src)>>5 - 5
  491. // nextEmit is where in src the next emitLiteral should start from.
  492. nextEmit := 0
  493. // The encoded form must start with a literal, as there are no previous
  494. // bytes to copy, so we start looking for hash matches at s == 1.
  495. s := 1
  496. cv := load64(src, s)
  497. // We search for a repeat at -1, but don't output repeats when nextEmit == 0
  498. repeat := 1
  499. for {
  500. candidate := 0
  501. for {
  502. // Next src position to check
  503. nextS := s + (s-nextEmit)>>6 + 4
  504. if nextS > sLimit {
  505. goto emitRemainder
  506. }
  507. hash0 := hash6(cv, tableBits)
  508. hash1 := hash6(cv>>8, tableBits)
  509. candidate = int(table[hash0])
  510. candidate2 := int(table[hash1])
  511. table[hash0] = uint32(s)
  512. table[hash1] = uint32(s + 1)
  513. hash2 := hash6(cv>>16, tableBits)
  514. // Check repeat at offset checkRep.
  515. const checkRep = 1
  516. if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
  517. base := s + checkRep
  518. // Extend back
  519. for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
  520. i--
  521. base--
  522. }
  523. d += emitLiteralSize(src[nextEmit:base])
  524. // Extend forward
  525. candidate := s - repeat + 4 + checkRep
  526. s += 4 + checkRep
  527. for s <= sLimit {
  528. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  529. s += bits.TrailingZeros64(diff) >> 3
  530. break
  531. }
  532. s += 8
  533. candidate += 8
  534. }
  535. d += emitCopyNoRepeatSize(repeat, s-base)
  536. nextEmit = s
  537. if s >= sLimit {
  538. goto emitRemainder
  539. }
  540. cv = load64(src, s)
  541. continue
  542. }
  543. if uint32(cv) == load32(src, candidate) {
  544. break
  545. }
  546. candidate = int(table[hash2])
  547. if uint32(cv>>8) == load32(src, candidate2) {
  548. table[hash2] = uint32(s + 2)
  549. candidate = candidate2
  550. s++
  551. break
  552. }
  553. table[hash2] = uint32(s + 2)
  554. if uint32(cv>>16) == load32(src, candidate) {
  555. s += 2
  556. break
  557. }
  558. cv = load64(src, nextS)
  559. s = nextS
  560. }
  561. // Extend backwards
  562. for candidate > 0 && s > nextEmit && src[candidate-1] == src[s-1] {
  563. candidate--
  564. s--
  565. }
  566. // Bail if we exceed the maximum size.
  567. if d+(s-nextEmit) > dstLimit {
  568. return 0
  569. }
  570. // A 4-byte match has been found. We'll later see if more than 4 bytes
  571. // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit
  572. // them as literal bytes.
  573. d += emitLiteralSize(src[nextEmit:s])
  574. // Call emitCopy, and then see if another emitCopy could be our next
  575. // move. Repeat until we find no match for the input immediately after
  576. // what was consumed by the last emitCopy call.
  577. //
  578. // If we exit this loop normally then we need to call emitLiteral next,
  579. // though we don't yet know how big the literal will be. We handle that
  580. // by proceeding to the next iteration of the main loop. We also can
  581. // exit this loop via goto if we get close to exhausting the input.
  582. for {
  583. // Invariant: we have a 4-byte match at s, and no need to emit any
  584. // literal bytes prior to s.
  585. base := s
  586. repeat = base - candidate
  587. // Extend the 4-byte match as long as possible.
  588. s += 4
  589. candidate += 4
  590. for s <= len(src)-8 {
  591. if diff := load64(src, s) ^ load64(src, candidate); diff != 0 {
  592. s += bits.TrailingZeros64(diff) >> 3
  593. break
  594. }
  595. s += 8
  596. candidate += 8
  597. }
  598. d += emitCopyNoRepeatSize(repeat, s-base)
  599. if false {
  600. // Validate match.
  601. a := src[base:s]
  602. b := src[base-repeat : base-repeat+(s-base)]
  603. if !bytes.Equal(a, b) {
  604. panic("mismatch")
  605. }
  606. }
  607. nextEmit = s
  608. if s >= sLimit {
  609. goto emitRemainder
  610. }
  611. if d > dstLimit {
  612. // Do we have space for more, if not bail.
  613. return 0
  614. }
  615. // Check for an immediate match, otherwise start search at s+1
  616. x := load64(src, s-2)
  617. m2Hash := hash6(x, tableBits)
  618. currHash := hash6(x>>16, tableBits)
  619. candidate = int(table[currHash])
  620. table[m2Hash] = uint32(s - 2)
  621. table[currHash] = uint32(s)
  622. if uint32(x>>16) != load32(src, candidate) {
  623. cv = load64(src, s+1)
  624. s++
  625. break
  626. }
  627. }
  628. }
  629. emitRemainder:
  630. if nextEmit < len(src) {
  631. // Bail if we exceed the maximum size.
  632. if d+len(src)-nextEmit > dstLimit {
  633. return 0
  634. }
  635. d += emitLiteralSize(src[nextEmit:])
  636. }
  637. return d
  638. }
  639. // emitLiteral writes a literal chunk and returns the number of bytes written.
  640. //
  641. // It assumes that:
  642. //
  643. // dst is long enough to hold the encoded bytes
  644. // 0 <= len(lit) && len(lit) <= math.MaxUint32
  645. func emitLiteralSize(lit []byte) int {
  646. if len(lit) == 0 {
  647. return 0
  648. }
  649. switch {
  650. case len(lit) <= 60:
  651. return len(lit) + 1
  652. case len(lit) <= 1<<8:
  653. return len(lit) + 2
  654. case len(lit) <= 1<<16:
  655. return len(lit) + 3
  656. case len(lit) <= 1<<24:
  657. return len(lit) + 4
  658. default:
  659. return len(lit) + 5
  660. }
  661. }
  662. func cvtLZ4BlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) {
  663. panic("cvtLZ4BlockAsm should be unreachable")
  664. }
  665. func cvtLZ4BlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) {
  666. panic("cvtLZ4BlockSnappyAsm should be unreachable")
  667. }
  668. func cvtLZ4sBlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) {
  669. panic("cvtLZ4sBlockAsm should be unreachable")
  670. }
  671. func cvtLZ4sBlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) {
  672. panic("cvtLZ4sBlockSnappyAsm should be unreachable")
  673. }