encodeBlockBetterSnappyGo encodes a non-empty src to a guaranteed-large-enough dst. It assumes that the varint-encoded length of the decompressed bytes has already been written. It also assumes that: len(dst) >= MaxEncodedLen(len(src)) && minNonLiteralBlockSize <= len(src) && len(src) <= maxBloc
(dst, src []byte)
| 308 | // len(dst) >= MaxEncodedLen(len(src)) && |
| 309 | // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize |
| 310 | func encodeBlockBetterSnappyGo(dst, src []byte) (d int) { |
| 311 | // sLimit is when to stop looking for offset/length copies. The inputMargin |
| 312 | // lets us use a fast path for emitLiteral in the main loop, while we are |
| 313 | // looking for copies. |
| 314 | sLimit := len(src) - inputMargin |
| 315 | if len(src) < minNonLiteralBlockSize { |
| 316 | return 0 |
| 317 | } |
| 318 | |
| 319 | // Initialize the hash tables. |
| 320 | const ( |
| 321 | // Long hash matches. |
| 322 | lTableBits = betterSnappyLongTableBits |
| 323 | maxLTableSize = betterSnappyLongTableSize |
| 324 | |
| 325 | // Short hash matches. |
| 326 | sTableBits = betterShortTableBits |
| 327 | maxSTableSize = betterShortTableSize |
| 328 | ) |
| 329 | |
| 330 | tbl := getBetterSnappyTables() |
| 331 | lTable := &tbl.lTable |
| 332 | sTable := &tbl.sTable |
| 333 | defer betterSnappyTablePool.Put(tbl) |
| 334 | |
| 335 | // Bail if we can't compress to at least this. |
| 336 | dstLimit := len(src) - len(src)>>5 - 6 |
| 337 | |
| 338 | // nextEmit is where in src the next emitLiteral should start from. |
| 339 | nextEmit := 0 |
| 340 | |
| 341 | // The encoded form must start with a literal, as there are no previous |
| 342 | // bytes to copy, so we start looking for hash matches at s == 1. |
| 343 | s := 1 |
| 344 | cv := load64(src, s) |
| 345 | |
| 346 | // We initialize repeat to 0, so we never match on first attempt |
| 347 | repeat := 0 |
| 348 | const maxSkip = 100 |
| 349 | |
| 350 | for { |
| 351 | candidateL := 0 |
| 352 | nextS := 0 |
| 353 | for { |
| 354 | // Next src position to check |
| 355 | nextS = min(s+(s-nextEmit)>>7+1, s+maxSkip) |
| 356 | |
| 357 | if nextS > sLimit { |
| 358 | goto emitRemainder |
| 359 | } |
| 360 | hashL := hash7(cv, lTableBits) |
| 361 | hashS := hash4(cv, sTableBits) |
| 362 | candidateL = int(lTable[hashL]) |
| 363 | candidateS := int(sTable[hashS]) |
| 364 | lTable[hashL] = uint32(s) |
| 365 | sTable[hashS] = uint32(s) |
| 366 | |
| 367 | if uint32(cv) == load32(src, candidateL) { |
searching dependent graphs…