encode_go.go 18 KB

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