@@ -161,7 +161,7 @@ static size_t ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc,
161161 zc -> seqStore .buffer = (void * ) (zc -> contentTable + ((size_t )1 << contentLog ));
162162 }
163163
164- zc -> nextToUpdate = 0 ;
164+ zc -> nextToUpdate = 1 ;
165165 zc -> end = NULL ;
166166 zc -> base = NULL ;
167167 zc -> dictBase = NULL ;
@@ -316,7 +316,7 @@ size_t ZSTD_HC_compressBlock_fast(ZSTD_HC_CCtx* ctx,
316316***************************************/
317317/** ZSTD_HC_insertBt1 : add one ptr to tree
318318 @ip : assumed <= iend-8 */
319- static void ZSTD_HC_insertBt1 (ZSTD_HC_CCtx * zc , const BYTE * const ip , const U32 mls , const BYTE * const iend , U32 nbCompares )
319+ static U32 ZSTD_HC_insertBt1 (ZSTD_HC_CCtx * zc , const BYTE * const ip , const U32 mls , const BYTE * const iend , U32 nbCompares )
320320{
321321 U32 * const hashTable = zc -> hashTable ;
322322 const U32 hashLog = zc -> params .hashLog ;
@@ -327,22 +327,30 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32
327327 U32 matchIndex = hashTable [h ];
328328 size_t commonLengthSmaller = 0 , commonLengthLarger = 0 ;
329329 const BYTE * const base = zc -> base ;
330- const U32 current = (U32 )(ip - base );
330+ const BYTE * match = base + matchIndex ;
331+ U32 current = (U32 )(ip - base );
331332 const U32 btLow = btMask >= current ? 0 : current - btMask ;
332333 U32 * smallerPtr = bt + 2 * (current & btMask );
333334 U32 * largerPtr = bt + 2 * (current & btMask ) + 1 ;
334335 U32 dummy32 ; /* to be nullified at the end */
335336 const U32 windowSize = 1 << zc -> params .windowLog ;
336337 const U32 windowLow = windowSize >= current ? 0 : current - windowSize ;
337338
338- hashTable [h ] = (U32 )(ip - base ); /* Update Hash Table */
339+ if ((current - matchIndex == 1 ) /* RLE */
340+ && MEM_read64 (match ) == MEM_read64 (ip ))
341+ {
342+ size_t rleLength = ZSTD_count (ip + sizeof (size_t ), match + sizeof (size_t ), iend ) + sizeof (size_t );
343+ return (U32 )(rleLength - mls );
344+ }
345+
346+ hashTable [h ] = (U32 )(ip - base ); /* Update Hash Table */
339347
340348 while (nbCompares -- && (matchIndex > windowLow ))
341349 {
342350 U32 * nextPtr = bt + 2 * (matchIndex & btMask );
343- const BYTE * match = base + matchIndex ;
344351 size_t matchLength = MIN (commonLengthSmaller , commonLengthLarger ); /* guaranteed minimum nb of common bytes */
345352
353+ match = base + matchIndex ;
346354 matchLength += ZSTD_count (ip + matchLength , match + matchLength , iend );
347355
348356 if (ip + matchLength == iend ) /* equal : no way to know if inf or sup */
@@ -369,6 +377,7 @@ static void ZSTD_HC_insertBt1(ZSTD_HC_CCtx* zc, const BYTE* const ip, const U32
369377 }
370378
371379 * smallerPtr = * largerPtr = 0 ;
380+ return 1 ;
372381}
373382
374383
@@ -412,49 +421,49 @@ size_t ZSTD_HC_insertBtAndFindBestMatch (
412421 if ( (4 * (int )(matchLength - bestLength )) > (int )(ZSTD_highbit (current - matchIndex + 1 ) - ZSTD_highbit ((U32 )offsetPtr [0 ]+ 1 )) )
413422 bestLength = matchLength , * offsetPtr = current - matchIndex ;
414423 if (ip + matchLength == iend ) /* equal : no way to know if inf or sup */
415- break ; /* drop, next to null, to guarantee consistency (is there a way to do better ? ) */
424+ break ; /* just drop, to guarantee consistency (miss a little bit of compression ) */
416425 }
417426
418427 if (match [matchLength ] < ip [matchLength ])
419428 {
420429 /* match is smaller than current */
421430 * smallerPtr = matchIndex ; /* update smaller idx */
422431 commonLengthSmaller = matchLength ; /* all smaller will now have at least this guaranteed common length */
423- if (matchIndex <= btLow ) { smallerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
424432 smallerPtr = nextPtr + 1 ; /* new "smaller" => larger of match */
425- matchIndex = nextPtr [1 ]; /* new matchIndex larger than previous (closer to current) */
433+ if (matchIndex <= btLow ) smallerPtr = & dummy32 ; /* beyond tree size, stop the search */
434+ matchIndex = (matchIndex <= btLow ) ? windowLow : nextPtr [1 ];
426435 }
427436 else
428437 {
429438 /* match is larger than current */
430439 * largerPtr = matchIndex ;
431440 commonLengthLarger = matchLength ;
432- if (matchIndex <= btLow ) { largerPtr = & dummy32 ; break ; } /* beyond tree size, stop the search */
433441 largerPtr = nextPtr ;
434- matchIndex = nextPtr [0 ];
442+ if (matchIndex <= btLow ) largerPtr = & dummy32 ; /* beyond tree size, stop the search */
443+ matchIndex = (matchIndex <= btLow ) ? windowLow : nextPtr [0 ];
435444 }
436445 }
437446
438447 * smallerPtr = * largerPtr = 0 ;
439448
440449 zc -> nextToUpdate = current + 1 ; /* current has been inserted */
441- if (bestLength < MINMATCH ) return 0 ;
442450 return bestLength ;
443451}
444452
445453
446- static void ZSTD_HC_updateTree (ZSTD_HC_CCtx * zc , const BYTE * const ip , const BYTE * const iend , const U32 nbCompares , const U32 mls )
454+ static const BYTE * ZSTD_HC_updateTree (ZSTD_HC_CCtx * zc , const BYTE * const ip , const BYTE * const iend , const U32 nbCompares , const U32 mls )
447455{
448456 const BYTE * const base = zc -> base ;
449457 const U32 target = (U32 )(ip - base );
450458 U32 idx = zc -> nextToUpdate ;
451459 //size_t dummy;
452460
453- for ( ; idx < target ; idx ++ )
454- ZSTD_HC_insertBt1 (zc , base + idx , mls , iend , nbCompares );
461+ for ( ; idx < target ; )
462+ idx += ZSTD_HC_insertBt1 (zc , base + idx , mls , iend , nbCompares );
455463 //ZSTD_HC_insertBtAndFindBestMatch(zc, base+idx, iend, &dummy, nbCompares, mls);
456464
457- zc -> nextToUpdate = target ;
465+ zc -> nextToUpdate = idx ;
466+ return base + idx ;
458467}
459468
460469
@@ -466,7 +475,13 @@ size_t ZSTD_HC_BtFindBestMatch (
466475 size_t * offsetPtr ,
467476 const U32 maxNbAttempts , const U32 mls )
468477{
469- ZSTD_HC_updateTree (zc , ip , iLimit , maxNbAttempts , mls );
478+ const BYTE * nextToUpdate = ZSTD_HC_updateTree (zc , ip , iLimit , maxNbAttempts , mls );
479+ if (nextToUpdate > ip )
480+ {
481+ /* RLE data */
482+ * offsetPtr = 1 ;
483+ return ZSTD_count (ip , ip - 1 , iLimit );
484+ }
470485 return ZSTD_HC_insertBtAndFindBestMatch (zc , ip , iLimit , offsetPtr , maxNbAttempts , mls );
471486}
472487
@@ -546,22 +561,21 @@ size_t ZSTD_HC_HcFindBestMatch (
546561 if (matchIndex >= dictLimit )
547562 {
548563 match = base + matchIndex ;
549- if ( (match [ml ] == ip [ml ])
550- && (MEM_read32 (match ) == MEM_read32 (ip )) ) /* ensures minimum match of 4 */
564+ if (match [ml ] == ip [ml ]) /* potentially better */
551565 {
552- const size_t mlt = ZSTD_count (ip + MINMATCH , match + MINMATCH , iLimit ) + MINMATCH ;
566+ const size_t mlt = ZSTD_count (ip , match , iLimit );
553567 if (mlt > ml )
554568 //if (((int)(4*mlt) - (int)ZSTD_highbit((U32)(ip-match)+1)) > ((int)(4*ml) - (int)ZSTD_highbit((U32)((*offsetPtr)+1))))
555569 {
556570 ml = mlt ; * offsetPtr = ip - match ;
557- if (ip + ml >= iLimit ) break ;
571+ if (ip + mlt >= iLimit ) break ;
558572 }
559573 }
560574 }
561575 else
562576 {
563577 match = dictBase + matchIndex ;
564- if (MEM_read32 (match ) == MEM_read32 (ip ))
578+ if (MEM_read32 (match ) == MEM_read32 (ip )) /* beware of end of dict */
565579 {
566580 size_t mlt ;
567581 const BYTE * vLimit = ip + (dictLimit - matchIndex );
@@ -647,7 +661,11 @@ size_t ZSTD_HC_compressBlock_lazy_generic(ZSTD_HC_CCtx* ctx,
647661
648662 offset_2 = offset_1 ;
649663 matchLength = searchMax (ctx , ip , iend , & offset , maxSearches , mls );
650- if (!matchLength ) { ip ++ ; continue ; }
664+ if (matchLength < MINMATCH )
665+ {
666+ ip += ((ip - anchor ) >> g_searchStrength ) + 1 ; /* jump faster over incompressible sections */
667+ continue ;
668+ }
651669
652670 /* let's try to find a better solution */
653671 start = ip ;
@@ -660,15 +678,15 @@ size_t ZSTD_HC_compressBlock_lazy_generic(ZSTD_HC_CCtx* ctx,
660678 size_t ml2 = ZSTD_count (ip + MINMATCH , ip + MINMATCH - offset_1 , iend ) + MINMATCH ;
661679 int gain2 = (int )(ml2 * 3 );
662680 int gain1 = (int )(matchLength * 3 - ZSTD_highbit ((U32 )offset + 1 ) + 1 );
663- if (gain2 > gain1 )
681+ if (( ml2 >= MINMATCH ) && ( gain2 > gain1 ) )
664682 matchLength = ml2 , offset = 0 , start = ip ;
665683 }
666684 {
667685 size_t offset2 = 999999 ;
668686 size_t ml2 = searchMax (ctx , ip , iend , & offset2 , maxSearches , mls );
669687 int gain2 = (int )(ml2 * (3 + deep ) - ZSTD_highbit ((U32 )offset2 + 1 )); /* raw approx */
670688 int gain1 = (int )(matchLength * (3 + deep ) - ZSTD_highbit ((U32 )offset + 1 ) + (3 + deep ));
671- if (gain2 > gain1 )
689+ if (( ml2 >= MINMATCH ) && ( gain2 > gain1 ) )
672690 {
673691 matchLength = ml2 , offset = offset2 , start = ip ;
674692 continue ; /* search a better one */
@@ -684,15 +702,15 @@ size_t ZSTD_HC_compressBlock_lazy_generic(ZSTD_HC_CCtx* ctx,
684702 size_t ml2 = ZSTD_count (ip + MINMATCH , ip + MINMATCH - offset_1 , iend ) + MINMATCH ;
685703 int gain2 = (int )(ml2 * 4 );
686704 int gain1 = (int )(matchLength * 4 - ZSTD_highbit ((U32 )offset + 1 ) + 1 );
687- if (gain2 > gain1 )
705+ if (( ml2 >= MINMATCH ) && ( gain2 > gain1 ) )
688706 matchLength = ml2 , offset = 0 , start = ip ;
689707 }
690708 {
691709 size_t offset2 = 999999 ;
692710 size_t ml2 = searchMax (ctx , ip , iend , & offset2 , maxSearches , mls );
693711 int gain2 = (int )(ml2 * 4 - ZSTD_highbit ((U32 )offset2 + 1 )); /* raw approx */
694712 int gain1 = (int )(matchLength * 4 - ZSTD_highbit ((U32 )offset + 1 ) + 7 );
695- if (gain2 > gain1 )
713+ if (( ml2 >= MINMATCH ) && ( gain2 > gain1 ) )
696714 {
697715 matchLength = ml2 , offset = offset2 , start = ip ;
698716 continue ;
@@ -702,13 +720,19 @@ size_t ZSTD_HC_compressBlock_lazy_generic(ZSTD_HC_CCtx* ctx,
702720 break ; /* nothing found : store previous solution */
703721 }
704722
723+ /* catch up */
724+ if (offset )
725+ {
726+ while ((start > anchor ) && (start > ctx -> base + offset ) && (start [-1 ] == start [-1 - offset ]))
727+ { start -- ; matchLength ++ ; }
728+ }
729+
705730 /* store sequence */
706731 {
707732 size_t litLength = start - anchor ;
708733 if (offset ) offset_1 = offset ;
709734 ZSTD_storeSeq (seqStorePtr , litLength , anchor , offset , matchLength - MINMATCH );
710- ip = start + matchLength ;
711- anchor = ip ;
735+ anchor = ip = start + matchLength ;
712736 }
713737
714738 }
@@ -793,8 +817,12 @@ size_t ZSTD_HC_compressBlock_greedy(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstS
793817 {
794818 size_t offset = 999999 ;
795819 size_t matchLength = ZSTD_HC_HcFindBestMatch_selectMLS (ctx , ip , iend , & offset , maxSearches , mls );
796- if (!matchLength ) { ip ++ ; continue ; }
797- while ((ip > anchor ) && (ip - offset > ctx -> base ) && (ip [-1 ] == ip [-1 - offset ])) { ip -- ; } /* catch up */
820+ if (matchLength < MINMATCH )
821+ {
822+ ip += ((ip - anchor ) >> g_searchStrength ) + 1 ; /* jump faster over incompressible sections */
823+ continue ;
824+ }
825+ while ((ip > anchor ) && (ip - offset > ctx -> base ) && (ip [-1 ] == ip [-1 - offset ])) { ip -- ; matchLength ++ ; } /* catch up */
798826 /* store sequence */
799827 {
800828 size_t litLength = ip - anchor ;
0 commit comments