private static int LZ4HC_CommonLength_32(LZ4HC_Data_Structure ctx, int p1, int p2)
        {
            int[] debruijn32 = DEBRUIJN_TABLE_32;
            byte[] src = ctx.src;
            int src_LASTLITERALS = ctx.src_LASTLITERALS;

            int p1t = p1;

            while (p1t < src_LASTLITERALS - (STEPSIZE_32 - 1)) {
                var diff = (int) Xor4(src, p2, p1t);
                if (diff == 0) {
                    p1t += STEPSIZE_32;
                    p2 += STEPSIZE_32;
                    continue;
                }
                p1t += debruijn32[((uint) ((diff) & -(diff)) * 0x077CB531u) >> 27];
                return (p1t - p1);
            }
            if ((p1t < (src_LASTLITERALS - 1)) && (Equal2(src, p2, p1t))) {
                p1t += 2;
                p2 += 2;
            }
            if ((p1t < src_LASTLITERALS) && (src[p2] == src[p1t])) {
                p1t++;
            }
            return (p1t - p1);
        }
        private static int LZ4HC_CommonLength_64(LZ4HC_Data_Structure ctx, int p1, int p2)
        {
            int[] debruijn64 = DEBRUIJN_TABLE_64;
            byte[] src = ctx.src;
            int src_LASTLITERALS = ctx.src_LASTLITERALS;
            int p1t = p1;

            while (p1t < src_LASTLITERALS - (STEPSIZE_64 - 1)) {
                var diff = (long) Xor8(src, p2, p1t);
                if (diff == 0) {
                    p1t += STEPSIZE_64;
                    p2 += STEPSIZE_64;
                    continue;
                }
                p1t += debruijn64[((ulong) ((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
                return (p1t - p1);
            }
            if ((p1t < (src_LASTLITERALS - 3)) && (Equal4(src, p2, p1t))) {
                p1t += 4;
                p2 += 4;
            }
            if ((p1t < (src_LASTLITERALS - 1)) && (Equal2(src, p2, p1t))) {
                p1t += 2;
                p2 += 2;
            }
            if ((p1t < src_LASTLITERALS) && (src[p2] == src[p1t])) {
                p1t++;
            }
            return (p1t - p1);
        }
		// Update chains up to ip (excluded)
		private static unsafe void LZ4HC_Insert_64(LZ4HC_Data_Structure hc4, byte* src_p)
		{
			fixed (ushort* chainTable = hc4.chainTable)
			fixed (int* hashTable = hc4.hashTable)
			{
				var src_base = hc4.src_base;
				while (hc4.nextToUpdate < src_p)
				{
					var p = hc4.nextToUpdate;
					var delta = (int)((p) - (hashTable[((((*(uint*)(p))) * 2654435761u) >> HASHHC_ADJUST)] + src_base));
					if (delta > MAX_DISTANCE) delta = MAX_DISTANCE;
					chainTable[((int)p) & MAXD_MASK] = (ushort)delta;
					hashTable[((((*(uint*)(p))) * 2654435761u) >> HASHHC_ADJUST)] = (int)(p - src_base);
					hc4.nextToUpdate++;
				}
			}
		}
		// Update chains up to ip (excluded)
		private static void LZ4HC_Insert_32(LZ4HC_Data_Structure ctx, int src_p)
		{
			var chainTable = ctx.chainTable;
			var hashTable = ctx.hashTable;
			var nextToUpdate = ctx.nextToUpdate;
			var src = ctx.src;
			var src_base = ctx.src_base;

			while (nextToUpdate < src_p)
			{
				var p = nextToUpdate;
				var delta = (p) - (hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
				if (delta > MAX_DISTANCE) delta = MAX_DISTANCE;
				chainTable[(p) & MAXD_MASK] = (ushort)delta;
				hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] = ((p) - src_base);
				nextToUpdate++;
			}

			ctx.nextToUpdate = nextToUpdate;
		}
		private static unsafe int LZ4HC_InsertAndGetWiderMatch_64(
			LZ4HC_Data_Structure hc4, byte* src_p, byte* startLimit, byte* src_LASTLITERALS, int longest,
			ref byte* matchpos, ref byte* startpos)
		{
			fixed (ushort* chainTable = hc4.chainTable)
			fixed (int* hashTable = hc4.hashTable)
			fixed (int* debruijn64 = DEBRUIJN_TABLE_64)
			{
				var src_base = hc4.src_base;
				var nbAttempts = MAX_NB_ATTEMPTS;
				var delta = (int)(src_p - startLimit);

				// First Match
				LZ4HC_Insert_64(hc4, src_p);
				var src_ref = (hashTable[((((*(uint*)(src_p))) * 2654435761u) >> HASHHC_ADJUST)] + src_base);

				while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
				{
					nbAttempts--;
					if (*(startLimit + longest) == *(src_ref - delta + longest))
					{
						if ((*(uint*)(src_ref)) == (*(uint*)(src_p)))
						{
							var reft = src_ref + MINMATCH;
							var ipt = src_p + MINMATCH;
							var startt = src_p;

							while (ipt < src_LASTLITERALS - (STEPSIZE_64 - 1))
							{
								var diff = (*(long*)(reft)) ^ (*(long*)(ipt));
								if (diff == 0)
								{
									ipt += STEPSIZE_64;
									reft += STEPSIZE_64;
									continue;
								}
								ipt += debruijn64[(((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL)) >> 58];
								goto _endCount;
							}
							if ((ipt < (src_LASTLITERALS - 3)) && ((*(uint*)(reft)) == (*(uint*)(ipt))))
							{
								ipt += 4;
								reft += 4;
							}
							if ((ipt < (src_LASTLITERALS - 1)) && ((*(ushort*)(reft)) == (*(ushort*)(ipt))))
							{
								ipt += 2;
								reft += 2;
							}
							if ((ipt < src_LASTLITERALS) && (*reft == *ipt)) ipt++;

						_endCount:
							reft = src_ref;

							while ((startt > startLimit) && (reft > hc4.src_base) && (startt[-1] == reft[-1]))
							{
								startt--;
								reft--;
							}

							if ((ipt - startt) > longest)
							{
								longest = (int)(ipt - startt);
								matchpos = reft;
								startpos = startt;
							}
						}
					}
					src_ref = ((src_ref) - chainTable[((int)src_ref) & MAXD_MASK]);
				}

				return longest;
			}
		}
		private static unsafe int LZ4HC_InsertAndFindBestMatch_64(
			LZ4HC_Data_Structure hc4, byte* src_p, byte* src_LASTLITERALS, ref byte* matchpos)
		{
			fixed (ushort* chainTable = hc4.chainTable)
			fixed (int* hashTable = hc4.hashTable)
			{
				var src_base = hc4.src_base;
				var nbAttempts = MAX_NB_ATTEMPTS;
				int repl = 0, ml = 0;
				ushort delta = 0;

				// HC4 match finder
				LZ4HC_Insert_64(hc4, src_p);
				var src_ref = (hashTable[((((*(uint*)(src_p))) * 2654435761u) >> HASHHC_ADJUST)] + src_base);

				// Detect repetitive sequences of length <= 4
				if (src_ref >= src_p - 4) // potential repetition
				{
					if ((*(uint*)(src_ref)) == (*(uint*)(src_p))) // confirmed
					{
						delta = (ushort)(src_p - src_ref);
						repl = ml = LZ4HC_CommonLength_64(src_p + MINMATCH, src_ref + MINMATCH, src_LASTLITERALS) + MINMATCH;
						matchpos = src_ref;
					}
					src_ref = ((src_ref) - chainTable[((int)src_ref) & MAXD_MASK]);
				}

				while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
				{
					nbAttempts--;
					if (*(src_ref + ml) == *(src_p + ml))
						if ((*(uint*)(src_ref)) == (*(uint*)(src_p)))
						{
							var mlt = LZ4HC_CommonLength_64(src_p + MINMATCH, src_ref + MINMATCH, src_LASTLITERALS) + MINMATCH;
							if (mlt > ml)
							{
								ml = mlt;
								matchpos = src_ref;
							}
						}
					src_ref = ((src_ref) - chainTable[((int)src_ref) & MAXD_MASK]);
				}

				// Complete table
				if (repl != 0)
				{
					var ptr = src_p;

					var end = src_p + repl - (MINMATCH - 1);
					while (ptr < end - delta)
					{
						chainTable[((int)ptr) & MAXD_MASK] = delta; // Pre-Load
						ptr++;
					}
					do
					{
						chainTable[((int)ptr) & MAXD_MASK] = delta;
						hashTable[((((*(uint*)(ptr))) * 2654435761u) >> HASHHC_ADJUST)] = (int)(ptr - src_base); // Head of chain
						ptr++;
					} while (ptr < end);
					hc4.nextToUpdate = end;
				}

				return ml;
			}
		}
示例#7
0
        // ReSharper disable InconsistentNaming
        // ReSharper restore InconsistentNaming
        private static unsafe LZ4HC_Data_Structure LZ4HC_Create(byte* src)
        {
            var hc4 = new LZ4HC_Data_Structure {
                hashTable = new int[HASHHC_TABLESIZE],
                chainTable = new ushort[MAXD]
            };

            fixed (ushort* ct = &hc4.chainTable[0]) {
                BlockFill((byte*) ct, MAXD * sizeof (ushort), 0xFF);
            }

            hc4.src_base = src;
            hc4.nextToUpdate = src + 1;

            return hc4;
        }
		private static int LZ4HC_InsertAndGetWiderMatch_32(
			LZ4HC_Data_Structure ctx, int src_p, int startLimit, int longest, ref int matchpos, ref int startpos)
		{
			var chainTable = ctx.chainTable;
			var hashTable = ctx.hashTable;
			var src = ctx.src;
			var src_base = ctx.src_base;
			var src_LASTLITERALS = ctx.src_LASTLITERALS;
			var debruijn32 = DEBRUIJN_TABLE_32;
			var nbAttempts = MAX_NB_ATTEMPTS;
			var delta = (src_p - startLimit);

			// First Match
			LZ4HC_Insert_32(ctx, src_p);
			var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);

			while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
			{
				nbAttempts--;
				if (src[(startLimit + longest)] == src[(src_ref - delta + longest)])
				{
					if (Equal4(src, src_ref, src_p))
					{
						var reft = src_ref + MINMATCH;
						var ipt = src_p + MINMATCH;
						var startt = src_p;

						while (ipt < src_LASTLITERALS - (STEPSIZE_32 - 1))
						{
							var diff = (int)Xor4(src, reft, ipt);
							if (diff == 0)
							{
								ipt += STEPSIZE_32;
								reft += STEPSIZE_32;
								continue;
							}
							ipt += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27];
							goto _endCount;
						}
						if ((ipt < (src_LASTLITERALS - 1)) && (Equal2(src, reft, ipt)))
						{
							ipt += 2;
							reft += 2;
						}
						if ((ipt < src_LASTLITERALS) && (src[reft] == src[ipt])) ipt++;

					_endCount:
						reft = src_ref;

						while ((startt > startLimit) && (reft > src_base) && (src[startt - 1] == src[reft - 1]))
						{
							startt--;
							reft--;
						}

						if ((ipt - startt) > longest)
						{
							longest = (ipt - startt);
							matchpos = reft;
							startpos = startt;
						}
					}
				}
				src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
			}

			return longest;
		}
		private static int LZ4_encodeSequence_32(
			LZ4HC_Data_Structure ctx, ref int src_p, ref int dst_p, ref int src_anchor, int matchLength, int src_ref, int dst_end)
		{
			int len;
			var src = ctx.src;
			var dst = ctx.dst;

			// Encode Literal length
			var length = src_p - src_anchor;
			var dst_token = dst_p++;
			if ((dst_p + length + (2 + 1 + LASTLITERALS) + (length >> 8)) > dst_end) return 1; // Check output limit
			if (length >= RUN_MASK)
			{
				dst[dst_token] = (RUN_MASK << ML_BITS);
				len = length - RUN_MASK;
				for (; len > 254; len -= 255) dst[dst_p++] = 255;
				dst[dst_p++] = (byte)len;
			}
			else
			{
				dst[dst_token] = (byte)(length << ML_BITS);
			}

			// Copy Literals
			if (length > 0)
			{
				var _i = dst_p + length;
				src_anchor += WildCopy(src, src_anchor, dst, dst_p, _i);
				dst_p = _i;
			}

			// Encode Offset
			Poke2(dst, dst_p, (ushort)(src_p - src_ref));
			dst_p += 2;

			// Encode MatchLength
			len = (matchLength - MINMATCH);
			if (dst_p + (1 + LASTLITERALS) + (length >> 8) > dst_end) return 1; // Check output limit
			if (len >= ML_MASK)
			{
				dst[dst_token] += ML_MASK;
				len -= ML_MASK;
				for (; len > 509; len -= 510)
				{
					dst[(dst_p)++] = 255;
					dst[(dst_p)++] = 255;
				}
				if (len > 254)
				{
					len -= 255;
					dst[(dst_p)++] = 255;
				}
				dst[(dst_p)++] = (byte)len;
			}
			else
			{
				dst[dst_token] += (byte)len;
			}

			// Prepare next loop
			src_p += matchLength;
			src_anchor = src_p;

			return 0;
		}
        private static unsafe int LZ4HC_InsertAndGetWiderMatch_32(
            LZ4HC_Data_Structure hc4, byte* src_p, byte* startLimit, byte* src_LASTLITERALS, int longest,
            ref byte* matchpos, ref byte* startpos)
        {
            fixed (ushort* chainTable = hc4.chainTable)
            fixed (int* hashTable = hc4.hashTable)
            fixed (int* debruijn32 = DEBRUIJN_TABLE_32)
            {
                var src_base = hc4.src_base;
                var nbAttempts = MAX_NB_ATTEMPTS;
                var delta = (int) (src_p - startLimit);

                // First Match
                LZ4HC_Insert_32(hc4, src_p);
                var xxx_ref = hashTable[(*(uint*) src_p*2654435761u) >> HASHHC_ADJUST] + src_base;

                while ((xxx_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
                {
                    nbAttempts--;
                    if (*(startLimit + longest) == *(xxx_ref - delta + longest))
                    {
                        if (*(uint*) xxx_ref == *(uint*) src_p)
                        {
                            var reft = xxx_ref + MINMATCH;
                            var ipt = src_p + MINMATCH;
                            var startt = src_p;

                            while (ipt < src_LASTLITERALS - (STEPSIZE_32 - 1))
                            {
                                var diff = *(int*) reft ^ *(int*) ipt;
                                if (diff == 0)
                                {
                                    ipt += STEPSIZE_32;
                                    reft += STEPSIZE_32;
                                    continue;
                                }
                                ipt += debruijn32[(uint) (diff & -diff)*0x077CB531u >> 27];
                                goto _endCount;
                            }
                            if ((ipt < src_LASTLITERALS - 1) && (*(ushort*) reft == *(ushort*) ipt))
                            {
                                ipt += 2;
                                reft += 2;
                            }
                            if ((ipt < src_LASTLITERALS) && (*reft == *ipt)) ipt++;
                            _endCount:
                            reft = xxx_ref;

                            while ((startt > startLimit) && (reft > hc4.src_base) && (startt[-1] == reft[-1]))
                            {
                                startt--;
                                reft--;
                            }

                            if (ipt - startt > longest)
                            {
                                longest = (int) (ipt - startt);
                                matchpos = reft;
                                startpos = startt;
                            }
                        }
                    }
                    xxx_ref = xxx_ref - chainTable[(int) xxx_ref & MAXD_MASK];
                }

                return longest;
            }
        }
示例#11
0
 // Update chains up to ip (excluded)
 private static void LZ4HC_Insert(LZ4HC_Data_Structure hc4, byte* src_p)
 {
     fixed (ushort* chainTable = hc4.chainTable)
     {
         fixed (int* hashTable = hc4.hashTable)
         {
             var src_base = hc4.src_base;
             while (hc4.nextToUpdate < src_p)
             {
                 var p = hc4.nextToUpdate;
                 var delta =
                     (int)((p) - (hashTable[((((*(uint*)(p))) * 2654435761u) >> HashHCAdjust)] + src_base));
                 if (delta > MaxDistance)
                 {
                     delta = MaxDistance;
                 }
                 chainTable[((int)p) & MaxDMask] = (ushort)delta;
                 hashTable[((((*(uint*)(p))) * 2654435761u) >> HashHCAdjust)] = (int)(p - src_base);
                 hc4.nextToUpdate++;
             }
         }
     }
 }
        private static void LZ4HC_Insert_64(LZ4HC_Data_Structure ctx, int src_p)
        {
            ushort[] chainTable = ctx.chainTable;
            int[] hashTable = ctx.hashTable;
            byte[] src = ctx.src;
            int src_base = ctx.src_base;
            int nextToUpdate = ctx.nextToUpdate;

            while (nextToUpdate < src_p) {
                int p = nextToUpdate;
                int delta = (p) - (hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);
                if (delta > MAX_DISTANCE) {
                    delta = MAX_DISTANCE;
                }
                chainTable[(p) & MAXD_MASK] = (ushort) delta;
                hashTable[(((Peek4(src, p)) * 2654435761u) >> HASHHC_ADJUST)] = ((p) - src_base);
                nextToUpdate++;
            }

            ctx.nextToUpdate = nextToUpdate;
        }
        private static int LZ4_compressHCCtx_64(LZ4HC_Data_Structure ctx)
        {
            byte[] src = ctx.src;
            int src_p = ctx.src_base;
            int src_end = ctx.src_end;
            int dst_0 = ctx.dst_base;
            int src_anchor = src_p;
            int src_mflimit = src_end - MFLIMIT;
            byte[] dst = ctx.dst;
            int dst_len = ctx.dst_len;
            int dst_p = ctx.dst_base;

            int xxx_ref = 0;
            int start2 = 0;
            int ref2 = 0;
            int start3 = 0;
            int ref3 = 0;

            src_p++;

            // Main Loop
            while (src_p < src_mflimit) {
                int ml = LZ4HC_InsertAndFindBestMatch_64(ctx, src_p, ref xxx_ref);
                if (ml == 0) {
                    src_p++;
                    continue;
                }

                // saved, in case we would skip too much
                int start0 = src_p;
                int ref0 = xxx_ref;
                int ml0 = ml;

                _Search2:
                int ml2 = src_p + ml < src_mflimit
                    ? LZ4HC_InsertAndGetWiderMatch_64(ctx, src_p + ml - 2, src_p + 1, ml, ref ref2, ref start2)
                    : ml;

                if (ml2 == ml) // No better match
                {
                    if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) {
                        return 0;
                    }
                    continue;
                }

                if (start0 < src_p) {
                    if (start2 < src_p + ml0) // empirical
                    {
                        src_p = start0;
                        xxx_ref = ref0;
                        ml = ml0;
                    }
                }

                // Here, start0==ip
                if ((start2 - src_p) < 3) // First Match too small : removed
                {
                    ml = ml2;
                    src_p = start2;
                    xxx_ref = ref2;
                    goto _Search2;
                }

                _Search3:
                // Currently we have :
                // ml2 > ml1, and
                // ip1+3 <= ip2 (usually < ip1+ml1)
                if ((start2 - src_p) < OPTIMAL_ML) {
                    int new_ml = ml;
                    if (new_ml > OPTIMAL_ML) {
                        new_ml = OPTIMAL_ML;
                    }
                    if (src_p + new_ml > start2 + ml2 - MINMATCH) {
                        new_ml = (start2 - src_p) + ml2 - MINMATCH;
                    }
                    int correction = new_ml - (start2 - src_p);
                    if (correction > 0) {
                        start2 += correction;
                        ref2 += correction;
                        ml2 -= correction;
                    }
                }
                // Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18)

                int ml3 = start2 + ml2 < src_mflimit
                    ? LZ4HC_InsertAndGetWiderMatch_64(ctx, start2 + ml2 - 3, start2, ml2, ref ref3, ref start3)
                    : ml2;

                if (ml3 == ml2) // No better match : 2 sequences to encode
                {
                    // ip & ref are known; Now for ml
                    if (start2 < src_p + ml) {
                        ml = (start2 - src_p);
                    }
                    // Now, encode 2 sequences
                    if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) {
                        return 0;
                    }
                    src_p = start2;
                    if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml2, ref2) != 0) {
                        return 0;
                    }
                    continue;
                }

                if (start3 < src_p + ml + 3) // Not enough space for match 2 : remove it
                {
                    if (start3 >= (src_p + ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
                    {
                        if (start2 < src_p + ml) {
                            int correction = (src_p + ml - start2);
                            start2 += correction;
                            ref2 += correction;
                            ml2 -= correction;
                            if (ml2 < MINMATCH) {
                                start2 = start3;
                                ref2 = ref3;
                                ml2 = ml3;
                            }
                        }

                        if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) {
                            return 0;
                        }
                        src_p = start3;
                        xxx_ref = ref3;
                        ml = ml3;

                        start0 = start2;
                        ref0 = ref2;
                        ml0 = ml2;
                        goto _Search2;
                    }

                    start2 = start3;
                    ref2 = ref3;
                    ml2 = ml3;
                    goto _Search3;
                }

                // OK, now we have 3 ascending matches; let's write at least the first one
                // ip & ref are known; Now for ml
                if (start2 < src_p + ml) {
                    if ((start2 - src_p) < ML_MASK) {
                        if (ml > OPTIMAL_ML) {
                            ml = OPTIMAL_ML;
                        }
                        if (src_p + ml > start2 + ml2 - MINMATCH) {
                            ml = (start2 - src_p) + ml2 - MINMATCH;
                        }
                        int correction = ml - (start2 - src_p);
                        if (correction > 0) {
                            start2 += correction;
                            ref2 += correction;
                            ml2 -= correction;
                        }
                    } else {
                        ml = (start2 - src_p);
                    }
                }
                if (LZ4_encodeSequence_64(ctx, ref src_p, ref dst_p, ref src_anchor, ml, xxx_ref) != 0) {
                    return 0;
                }

                src_p = start2;
                xxx_ref = ref2;
                ml = ml2;

                start2 = start3;
                ref2 = ref3;
                ml2 = ml3;

                goto _Search3;
            }

            // Encode Last Literals
            {
                int lastRun = (src_end - src_anchor);
                if ((dst_p - dst_0) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (uint) dst_len) {
                    return 0; // Check output limit
                }
                if (lastRun >= RUN_MASK) {
                    dst[dst_p++] = (RUN_MASK << ML_BITS);
                    lastRun -= RUN_MASK;
                    for (; lastRun > 254; lastRun -= 255) {
                        dst[dst_p++] = 255;
                    }
                    dst[dst_p++] = (byte) lastRun;
                } else {
                    dst[dst_p++] = (byte) (lastRun << ML_BITS);
                }
                BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor);
                dst_p += src_end - src_anchor;
            }

            // End
            return (dst_p - dst_0);
        }
        private static int LZ4HC_InsertAndGetWiderMatch_64(LZ4HC_Data_Structure ctx, int src_p, int startLimit,
            int longest, ref int matchpos, ref int startpos)
        {
            int[] debruijn64 = DEBRUIJN_TABLE_64;
            ushort[] chainTable = ctx.chainTable;
            int[] hashTable = ctx.hashTable;
            byte[] src = ctx.src;
            int src_base = ctx.src_base;
            int src_LASTLITERALS = ctx.src_LASTLITERALS;
            int nbAttempts = MAX_NB_ATTEMPTS;
            int delta = (src_p - startLimit);

            // First Match
            LZ4HC_Insert_64(ctx, src_p);
            int src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);

            while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0)) {
                nbAttempts--;
                if (src[startLimit + longest] == src[src_ref - delta + longest]) {
                    if (Equal4(src, src_ref, src_p)) {
                        int reft = src_ref + MINMATCH;
                        int ipt = src_p + MINMATCH;
                        int startt = src_p;

                        while (ipt < src_LASTLITERALS - (STEPSIZE_64 - 1)) {
                            var diff = (long) Xor8(src, reft, ipt);
                            if (diff == 0) {
                                ipt += STEPSIZE_64;
                                reft += STEPSIZE_64;
                                continue;
                            }
                            ipt += debruijn64[((ulong) ((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58];
                            goto _endCount;
                        }
                        if ((ipt < (src_LASTLITERALS - 3)) && (Equal4(src, reft, ipt))) {
                            ipt += 4;
                            reft += 4;
                        }
                        if ((ipt < (src_LASTLITERALS - 1)) && (Equal2(src, reft, ipt))) {
                            ipt += 2;
                            reft += 2;
                        }
                        if ((ipt < src_LASTLITERALS) && (src[reft] == src[ipt])) {
                            ipt++;
                        }

                        _endCount:
                        reft = src_ref;

                        while ((startt > startLimit) && (reft > src_base) && (src[startt - 1] == src[reft - 1])) {
                            startt--;
                            reft--;
                        }

                        if ((ipt - startt) > longest) {
                            longest = (ipt - startt);
                            matchpos = reft;
                            startpos = startt;
                        }
                    }
                }
                src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
            }

            return longest;
        }
示例#15
0
        private static int LZ4HC_InsertAndGetWiderMatch(
            LZ4HC_Data_Structure hc4, byte* src_p, byte* startLimit, byte* src_LASTLITERALS, int longest,
            ref byte* matchpos, ref byte* startpos)
        {
            fixed (ushort* chainTable = hc4.chainTable)
            {
                fixed (int* hashTable = hc4.hashTable)
                {
                    fixed (int* debruijn64 = DebruijnTable)
                    {
                        var src_base = hc4.src_base;
                        var nbAttempts = MaxAttempts;
                        var delta = (int)(src_p - startLimit);

                        // First Match
                        LZ4HC_Insert(hc4, src_p);
                        var src_ref = (hashTable[((((*(uint*)(src_p))) * 2654435761u) >> HashHCAdjust)] + src_base);

                        while ((src_ref >= src_p - MaxDistance) && (nbAttempts != 0))
                        {
                            nbAttempts--;
                            if (*(startLimit + longest) == *(src_ref - delta + longest))
                            {
                                if ((*(uint*)(src_ref)) == (*(uint*)(src_p)))
                                {
                                    var reft = src_ref + MinMatch;
                                    var ipt = src_p + MinMatch;
                                    var startt = src_p;

                                    while (ipt < src_LASTLITERALS - (StepSize - 1))
                                    {
                                        var diff = (*(long*)(reft)) ^ (*(long*)(ipt));
                                        if (diff == 0)
                                        {
                                            ipt += StepSize;
                                            reft += StepSize;
                                            continue;
                                        }
                                        ipt += debruijn64[(((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL)) >> 58];
                                        goto _endCount;
                                    }
                                    if ((ipt < (src_LASTLITERALS - 3)) && ((*(uint*)(reft)) == (*(uint*)(ipt))))
                                    {
                                        ipt += 4;
                                        reft += 4;
                                    }
                                    if ((ipt < (src_LASTLITERALS - 1)) && ((*(ushort*)(reft)) == (*(ushort*)(ipt))))
                                    {
                                        ipt += 2;
                                        reft += 2;
                                    }
                                    if ((ipt < src_LASTLITERALS) && (*reft == *ipt))
                                    {
                                        ipt++;
                                    }

                                    _endCount:
                                    reft = src_ref;

                                    while ((startt > startLimit) && (reft > hc4.src_base) && (startt[-1] == reft[-1]))
                                    {
                                        startt--;
                                        reft--;
                                    }

                                    if ((ipt - startt) > longest)
                                    {
                                        longest = (int)(ipt - startt);
                                        matchpos = reft;
                                        startpos = startt;
                                    }
                                }
                            }
                            src_ref = ((src_ref) - chainTable[((int)src_ref) & MaxDMask]);
                        }

                        return longest;
                    }
                }
            }
        }
示例#16
0
        private static int LZ4HC_InsertAndFindBestMatch(
            LZ4HC_Data_Structure hc4, byte* src_p, byte* src_LASTLITERALS, ref byte* matchpos)
        {
            fixed (ushort* chainTable = hc4.chainTable)
            {
                fixed (int* hashTable = hc4.hashTable)
                {
                    var src_base = hc4.src_base;
                    var nbAttempts = MaxAttempts;
                    int repl = 0, ml = 0;
                    ushort delta = 0;

                    // HC4 match finder
                    LZ4HC_Insert(hc4, src_p);
                    var src_ref = (hashTable[((((*(uint*)(src_p))) * 2654435761u) >> HashHCAdjust)] + src_base);

                    // Detect repetitive sequences of length <= 4
                    if (src_ref >= src_p - 4) // potential repetition
                    {
                        if ((*(uint*)(src_ref)) == (*(uint*)(src_p))) // confirmed
                        {
                            delta = (ushort)(src_p - src_ref);
                            repl =
                                ml =
                                LZ4HC_CommonLength(src_p + MinMatch, src_ref + MinMatch, src_LASTLITERALS) + MinMatch;
                            matchpos = src_ref;
                        }
                        src_ref = ((src_ref) - chainTable[((int)src_ref) & MaxDMask]);
                    }

                    while ((src_ref >= src_p - MaxDistance) && (nbAttempts != 0))
                    {
                        nbAttempts--;
                        if (*(src_ref + ml) == *(src_p + ml))
                        {
                            if ((*(uint*)(src_ref)) == (*(uint*)(src_p)))
                            {
                                var mlt = LZ4HC_CommonLength(src_p + MinMatch, src_ref + MinMatch, src_LASTLITERALS) +
                                          MinMatch;
                                if (mlt > ml)
                                {
                                    ml = mlt;
                                    matchpos = src_ref;
                                }
                            }
                        }
                        src_ref = ((src_ref) - chainTable[((int)src_ref) & MaxDMask]);
                    }

                    // Complete table
                    if (repl != 0)
                    {
                        var ptr = src_p;

                        var end = src_p + repl - (MinMatch - 1);
                        while (ptr < end - delta)
                        {
                            chainTable[((int)ptr) & MaxDMask] = delta; // Pre-Load
                            ptr++;
                        }
                        do
                        {
                            chainTable[((int)ptr) & MaxDMask] = delta;
                            hashTable[((((*(uint*)(ptr))) * 2654435761u) >> HashHCAdjust)] = (int)(ptr - src_base);
                            // Head of chain
                            ptr++;
                        } while (ptr < end);
                        hc4.nextToUpdate = end;
                    }

                    return ml;
                }
            }
        }
		private static unsafe int LZ4_compressHCCtx_64(
			LZ4HC_Data_Structure ctx,
			byte* src,
			byte* dst,
			int src_len,
			int dst_maxlen)
		{
			var src_p = src;
			var src_anchor = src_p;
			var src_end = src_p + src_len;
			var src_mflimit = src_end - MFLIMIT;
			var src_LASTLITERALS = (src_end - LASTLITERALS);

			var dst_p = dst;
			var dst_end = dst_p + dst_maxlen;

			byte* src_ref = null;
			byte* start2 = null;
			byte* ref2 = null;
			byte* start3 = null;
			byte* ref3 = null;

			src_p++;

			// Main Loop
			while (src_p < src_mflimit)
			{
				var ml = LZ4HC_InsertAndFindBestMatch_64(ctx, src_p, src_LASTLITERALS, ref src_ref);
				if (ml == 0)
				{
					src_p++;
					continue;
				}

				// saved, in case we would skip too much
				var start0 = src_p;
				var ref0 = src_ref;
				var ml0 = ml;

			_Search2:
				var ml2 = src_p + ml < src_mflimit
					? LZ4HC_InsertAndGetWiderMatch_64(ctx, src_p + ml - 2, src_p + 1, src_LASTLITERALS, ml, ref ref2, ref start2)
					: ml;

				if (ml2 == ml) // No better match
				{
					if (LZ4_encodeSequence_64(ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
					continue;
				}

				if (start0 < src_p && start2 < src_p + ml0)
				{
					src_p = start0;
					src_ref = ref0;
					ml = ml0;
				}

				// Here, start0==ip
				if ((start2 - src_p) < 3) // First Match too small : removed
				{
					ml = ml2;
					src_p = start2;
					src_ref = ref2;
					goto _Search2;
				}

			_Search3:
				// Currently we have :
				// ml2 > ml1, and
				// ip1+3 <= ip2 (usually < ip1+ml1)
				if ((start2 - src_p) < OPTIMAL_ML)
				{
					var new_ml = ml;
					if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
					if (src_p + new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - src_p) + ml2 - MINMATCH;
					var correction = new_ml - (int)(start2 - src_p);
					if (correction > 0)
					{
						start2 += correction;
						ref2 += correction;
						ml2 -= correction;
					}
				}

				// Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18)

				var ml3 = start2 + ml2 < src_mflimit
					? LZ4HC_InsertAndGetWiderMatch_64(ctx, start2 + ml2 - 3, start2, src_LASTLITERALS, ml2, ref ref3, ref start3)
					: ml2;

				if (ml3 == ml2) // No better match : 2 sequences to encode
				{
					// ip & ref are known; Now for ml
					if (start2 < src_p + ml) ml = (int)(start2 - src_p);

					// Now, encode 2 sequences
					if (LZ4_encodeSequence_64(ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
					src_p = start2;
					if (LZ4_encodeSequence_64(ref src_p, ref dst_p, ref src_anchor, ml2, ref2, dst_end) != 0) return 0;
					continue;
				}

				if (start3 < src_p + ml + 3) // Not enough space for match 2 : remove it
				{
					if (start3 >= src_p + ml) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
					{
						if (start2 < src_p + ml)
						{
							var correction = (int)(src_p + ml - start2);
							start2 += correction;
							ref2 += correction;
							ml2 -= correction;
							if (ml2 < MINMATCH)
							{
								start2 = start3;
								ref2 = ref3;
								ml2 = ml3;
							}
						}

						if (LZ4_encodeSequence_64(ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0) return 0;
						src_p = start3;
						src_ref = ref3;
						ml = ml3;

						start0 = start2;
						ref0 = ref2;
						ml0 = ml2;
						goto _Search2;
					}

					start2 = start3;
					ref2 = ref3;
					ml2 = ml3;
					goto _Search3;
				}

				// OK, now we have 3 ascending matches; let's write at least the first one
				// ip & ref are known; Now for ml
				if (start2 < src_p + ml)
				{
					if (start2 - src_p < ML_MASK)
					{
						if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
						if (src_p + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - src_p) + ml2 - MINMATCH;
						var correction = ml - (int)(start2 - src_p);
						if (correction > 0)
						{
							start2 += correction;
							ref2 += correction;
							ml2 -= correction;
						}
					}
					else
					{
						ml = (int)(start2 - src_p);
					}
				}

				if (LZ4_encodeSequence_64(ref src_p, ref dst_p, ref src_anchor, ml, src_ref, dst_end) != 0)
					return 0;

				src_p = start2;
				src_ref = ref2;
				ml = ml2;

				start2 = start3;
				ref2 = ref3;
				ml2 = ml3;

				goto _Search3;
			}

			// Encode Last Literals
			var lastRun = (int)(src_end - src_anchor);
			if ((dst_p - dst) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (uint)dst_maxlen) return 0; // Check output limit
			if (lastRun >= RUN_MASK)
			{
				*dst_p++ = (RUN_MASK << ML_BITS);
				lastRun -= RUN_MASK;
				for (; lastRun > 254; lastRun -= 255) *dst_p++ = 255;
				*dst_p++ = (byte)lastRun;
			}
			else
			{
				*dst_p++ = (byte)(lastRun << ML_BITS);
			}
			BlockCopy(src_anchor, dst_p, (int)(src_end - src_anchor));
			dst_p += src_end - src_anchor;

			// End
			return (int)((dst_p) - dst);
		}
		private static int LZ4HC_InsertAndFindBestMatch_32(LZ4HC_Data_Structure ctx, int src_p, ref int src_match)
		{
			var chainTable = ctx.chainTable;
			var hashTable = ctx.hashTable;
			var src = ctx.src;
			var src_base = ctx.src_base;

			var nbAttempts = MAX_NB_ATTEMPTS;
			int repl = 0, ml = 0;
			ushort delta = 0;

			// HC4 match finder
			LZ4HC_Insert_32(ctx, src_p);
			var src_ref = (hashTable[(((Peek4(src, src_p)) * 2654435761u) >> HASHHC_ADJUST)] + src_base);


			// Detect repetitive sequences of length <= 4
			if (src_ref >= src_p - 4) // potential repetition
			{
				if (Equal4(src, src_ref, src_p)) // confirmed
				{
					delta = (ushort)(src_p - src_ref);
					repl = ml = LZ4HC_CommonLength_32(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
					src_match = src_ref;
				}
				src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
			}

			while ((src_ref >= src_p - MAX_DISTANCE) && (nbAttempts != 0))
			{
				nbAttempts--;
				if (src[(src_ref + ml)] == src[(src_p + ml)])
				{
					if (Equal4(src, src_ref, src_p))
					{
						var mlt = LZ4HC_CommonLength_32(ctx, src_p + MINMATCH, src_ref + MINMATCH) + MINMATCH;
						if (mlt > ml)
						{
							ml = mlt;
							src_match = src_ref;
						}
					}
				}
				src_ref = ((src_ref) - chainTable[(src_ref) & MAXD_MASK]);
			}


			// Complete table
			if (repl != 0)
			{
				var src_ptr = src_p;

				var end = src_p + repl - (MINMATCH - 1);
				while (src_ptr < end - delta)
				{
					chainTable[(src_ptr) & MAXD_MASK] = delta; // Pre-Load
					src_ptr++;
				}
				do
				{
					chainTable[(src_ptr) & MAXD_MASK] = delta;
					hashTable[(((Peek4(src, src_ptr)) * 2654435761u) >> HASHHC_ADJUST)] = ((src_ptr) - src_base); // Head of chain
					src_ptr++;
				} while (src_ptr < end);
				ctx.nextToUpdate = end;
			}

			return ml;
		}
示例#19
0
		// ReSharper restore InconsistentNaming


		private static LZ4HC_Data_Structure LZ4HC_Create(byte[] src, int src_0, int src_len, byte[] dst, int dst_0, int dst_len)
		{
			var hc4 = new LZ4HC_Data_Structure {
				src = src,
				src_base = src_0,
				src_end = src_0 + src_len,
				src_LASTLITERALS = (src_0 + src_len - LASTLITERALS),
				dst = dst,
				dst_base = dst_0,
				dst_len = dst_len,
				dst_end = dst_0 + dst_len,
				hashTable = new int[HASHHC_TABLESIZE],
				chainTable = new ushort[MAXD],
				nextToUpdate = src_0 + 1,
			};

			var ct = hc4.chainTable;
			for (var i = ct.Length - 1; i >= 0; i--) ct[i] = unchecked((ushort)-1);

			return hc4;
		}
示例#20
0
        private static LZ4HC_Data_Structure LZ4HC_Create(byte* src)
        {
            var hc4 = new LZ4HC_Data_Structure
                      {
                          hashTable = new int[HashHCTableSize],
                          chainTable = new ushort[MaxD]
                      };

            fixed (ushort* ct = &hc4.chainTable[0])
            {
                BufferFill((byte*)ct, MaxD * sizeof(ushort), 0xFF);
            }

            hc4.src_base = src;
            hc4.nextToUpdate = src + 1;

            return hc4;
        }