private static byte *LZ4_getPosition <TTableType>(byte *p, LZ4_stream_t_internal *ctx, byte *srcBase) where TTableType : ITableTypeDirective { int h = LZ4_hashPosition <TTableType>(p); return(LZ4_getPositionOnHash <TTableType>(h, ctx, srcBase)); }
private static void LZ4_putPosition <TTableType>(byte *p, LZ4_stream_t_internal *ctx, byte *srcBase) where TTableType : ITableTypeDirective { int h = LZ4_hashPosition <TTableType>(p); LZ4_putPositionOnHash <TTableType>(p, h, ctx, srcBase); }
private static byte *LZ4_getPositionOnHash(uint h, LZ4_stream_t_internal *ctx, TableType tableType, byte *srcBase) { if (tableType == TableType.ByU32) { return(srcBase + ctx->hashTable[h]); } else { return(srcBase + ((ushort *)ctx->hashTable)[h]); } }
private static void LZ4_putPositionOnHash(byte *p, uint h, LZ4_stream_t_internal *ctx, TableType tableType, byte *srcBase) { if (tableType == TableType.ByU32) { ctx->hashTable[h] = (uint)(p - srcBase); } else { ((ushort *)ctx->hashTable)[h] = (ushort)(p - srcBase); } }
private static byte *LZ4_getPositionOnHash <TTableType>(int h, LZ4_stream_t_internal *ctx, byte *srcBase) where TTableType : ITableTypeDirective { if (typeof(TTableType) == typeof(ByU32)) { return(srcBase + ctx->hashTable[h]); } else if (typeof(TTableType) == typeof(ByU16)) { return(srcBase + ((ushort *)ctx->hashTable)[h]); } ThrowException(new NotSupportedException("TTableType directive is not supported.")); return(default(byte *)); }
private static void LZ4_putPositionOnHash <TTableType>(byte *p, int h, LZ4_stream_t_internal *ctx, byte *srcBase) where TTableType : ITableTypeDirective { if (typeof(TTableType) == typeof(ByU32)) { ctx->hashTable[h] = (int)(p - srcBase); } else if (typeof(TTableType) == typeof(ByU16)) { ((ushort *)ctx->hashTable)[h] = (ushort)(p - srcBase); } else { ThrowException(new NotSupportedException("TTableType directive is not supported.")); } }
private static int LZ4_compress_generic <TLimited, TTableType, TDictionaryType, TDictionaryIssue>(LZ4_stream_t_internal *dictPtr, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration) where TLimited : ILimitedOutputDirective where TTableType : ITableTypeDirective where TDictionaryType : IDictionaryTypeDirective where TDictionaryIssue : IDictionaryIssueDirective { LZ4_stream_t_internal *ctx = dictPtr; byte *op = dest; byte *ip = source; byte *anchor = source; byte *dictionary = ctx->dictionary; byte *dictEnd = dictionary + ctx->dictSize; byte *lowRefLimit = ip - ctx->dictSize; long dictDelta = (long)dictEnd - (long)source; byte *iend = ip + inputSize; byte *mflimit = iend - MFLIMIT; byte *matchlimit = iend - LASTLITERALS; byte *olimit = op + maxOutputSize; // Init conditions if (inputSize > LZ4_MAX_INPUT_SIZE) { return(0); // Unsupported input size, too large (or negative) } byte * @base; byte * lowLimit; if (typeof(TDictionaryType) == typeof(NoDict)) { @base = source; lowLimit = source; } else if (typeof(TDictionaryType) == typeof(WithPrefix64K)) { @base = source - ctx->currentOffset; lowLimit = source - ctx->dictSize; } else if (typeof(TDictionaryType) == typeof(UsingExtDict)) { @base = source - ctx->currentOffset; lowLimit = source; } else { throw new NotSupportedException("Unsupported IDictionaryTypeDirective."); } if ((typeof(TTableType) == typeof(ByU16)) && (inputSize >= LZ4_64Klimit)) // Size too large (not within 64K limit) { return(0); } if (inputSize < LZ4_minLength) // Input too small, no compression (all literals) { goto _last_literals; } // First Byte LZ4_putPosition <TTableType>(ip, ctx, @base); ip++; int forwardH = LZ4_hashPosition <TTableType>(ip); // Main Loop long refDelta = 0; for (;;) { byte *match; { byte *forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { int h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (forwardIp > mflimit) { goto _last_literals; } match = LZ4_getPositionOnHash <TTableType>(h, ctx, @base); if (typeof(TDictionaryType) == typeof(UsingExtDict)) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } if (typeof(TTableType) == typeof(ByU16)) { ulong value = *((ulong *)forwardIp) * prime5bytes >> (40 - ByU16HashLog); forwardH = (int)(value & ByU16HashMask); ((ushort *)ctx->hashTable)[h] = (ushort)(ip - @base); } else if (typeof(TTableType) == typeof(ByU32)) { ulong value = (*((ulong *)forwardIp) * prime5bytes >> (40 - ByU32HashLog)); forwardH = (int)(value & ByU32HashMask); ctx->hashTable[h] = (int)(ip - @base); } else { throw new NotSupportedException("TTableType directive is not supported."); } }while (((typeof(TDictionaryType) == typeof(DictSmall)) ? (match < lowRefLimit) : false) || ((typeof(TTableType) == typeof(ByU16)) ? false : (match + MAX_DISTANCE < ip)) || (*(uint *)(match + refDelta) != *((uint *)ip))); } // Catch up while ((ip > anchor) && (match + refDelta > lowLimit) && (ip[-1] == match[refDelta - 1])) { ip--; match--; } // Encode Literal length byte *token; { int litLength = (int)(ip - anchor); token = op++; if ((typeof(TLimited) == typeof(LimitedOutput)) && (op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit)) { return(0); /* Check output limit */ } if (litLength >= RUN_MASK) { int len = litLength - RUN_MASK; * token = RUN_MASK << ML_BITS; for (; len >= 255; len -= 255) { *op++ = 255; } *op++ = (byte)len; } else { *token = (byte)(litLength << ML_BITS); } /* Copy Literals */ WildCopy(op, anchor, (op + litLength)); op += litLength; } _next_match: // Encode Offset *((ushort *)op) = (ushort)(ip - match); op += sizeof(ushort); // Encode MatchLength { int matchLength; if ((typeof(TDictionaryType) == typeof(UsingExtDict)) && (lowLimit == dictionary)) { match += refDelta; byte *limit = ip + (dictEnd - match); if (limit > matchlimit) { limit = matchlimit; } matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, limit); ip += MINMATCH + matchLength; if (ip == limit) { int more = LZ4_count(ip, source, matchlimit); matchLength += more; ip += more; } } else { matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); ip += MINMATCH + matchLength; } if ((typeof(TLimited) == typeof(LimitedOutput)) && ((op + (1 + LASTLITERALS) + (matchLength >> 8)) > olimit)) { return(0); /* Check output limit */ } if (matchLength >= ML_MASK) { *token += ML_MASK; matchLength -= ML_MASK; for (; matchLength >= 510; matchLength -= 510) { *(ushort *)op = (255 << 8 | 255); op += sizeof(ushort); } if (matchLength >= 255) { matchLength -= 255; *op++ = 255; } *op++ = (byte)matchLength; } else { *token += (byte)(matchLength); } } anchor = ip; // Test end of chunk if (ip > mflimit) { break; } // Fill table LZ4_putPosition <TTableType>(ip - 2, ctx, @base); /* Test next position */ match = LZ4_getPosition <TTableType>(ip, ctx, @base); if (typeof(TDictionaryType) == typeof(UsingExtDict)) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } LZ4_putPosition <TTableType>(ip, ctx, @base); if (((typeof(TDictionaryType) == typeof(DictSmall)) ? (match >= lowRefLimit) : true) && (match + MAX_DISTANCE >= ip) && (*(uint *)(match + refDelta) == *(uint *)(ip))) { token = op++; *token = 0; goto _next_match; } /* Prepare next loop */ forwardH = LZ4_hashPosition <TTableType>(++ip); } _last_literals: /* Encode Last Literals */ { int lastRun = (int)(iend - anchor); if ((typeof(TLimited) == typeof(LimitedOutput)) && ((op - dest) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > maxOutputSize)) { return(0); // Check output limit; } if (lastRun >= RUN_MASK) { int accumulator = lastRun - RUN_MASK; * op++ = RUN_MASK << ML_BITS; for (; accumulator >= 255; accumulator -= 255) { *op++ = 255; } *op++ = (byte)accumulator; } else { *op++ = (byte)(lastRun << ML_BITS); } Unsafe.CopyBlock(op, anchor, (uint)lastRun); op += lastRun; } return((int)(op - dest)); }
private static byte *LZ4_getPosition(byte *p, LZ4_stream_t_internal *ctx, TableType tableType, byte *srcBase) { uint h = LZ4_hashPosition(p, tableType); return(LZ4_getPositionOnHash(h, ctx, tableType, srcBase)); }
private static void LZ4_putPosition(byte *p, LZ4_stream_t_internal *ctx, TableType tableType, byte *srcBase) { uint h = LZ4_hashPosition(p, tableType); LZ4_putPositionOnHash(p, h, ctx, tableType, srcBase); }
private static int LZ4_compress_generic(LZ4_stream_t_internal *dictPtr, byte *source, byte *dest, int inputSize, int maxOutputSize, LimitedOutput outputLimited, TableType tableType, DictionaryType dict, DictionaryIssue dictIssue, int acceleration) { byte *ip = source; byte *lowRefLimit = ip - dictPtr->dictSize; byte *dictionary = dictPtr->dictionary; byte *dictEnd = dictionary + dictPtr->dictSize; long dictDelta = (long)dictEnd - (long)source; byte *anchor = source; byte *iend = ip + inputSize; byte *mflimit = iend - MFLIMIT; byte *matchlimit = iend - LASTLITERALS; byte *op = (byte *)dest; byte *olimit = op + maxOutputSize; uint forwardH; long refDelta = 0; // Init conditions if (inputSize > LZ4_MAX_INPUT_SIZE) { return(0); // Unsupported input size, too large (or negative) } byte * @base; byte * lowLimit; switch (dict) { default: case DictionaryType.NoDict: @base = source; lowLimit = source; break; case DictionaryType.WithPrefix64K: @base = source - dictPtr->currentOffset; lowLimit = source - dictPtr->dictSize; break; case DictionaryType.UsingExtDict: @base = source - dictPtr->currentOffset; lowLimit = source; break; } if ((tableType == TableType.ByU16) && (inputSize >= LZ4_64Klimit)) // Size too large (not within 64K limit) { return(0); } if (inputSize < LZ4_minLength) // Input too small, no compression (all literals) { goto _last_literals; } // First Byte LZ4_putPosition(ip, dictPtr, tableType, @base); ip++; forwardH = LZ4_hashPosition(ip, tableType); // Main Loop for (;;) { byte *match; { byte *forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { uint h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if (forwardIp > mflimit) { goto _last_literals; } match = LZ4_getPositionOnHash(h, dictPtr, tableType, @base); if (dict == DictionaryType.UsingExtDict) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putPositionOnHash(ip, h, dictPtr, tableType, @base); }while (((dictIssue == DictionaryIssue.DictSmall) ? (match < lowRefLimit) : false) || ((tableType == TableType.ByU16) ? false : (match + MAX_DISTANCE < ip)) || (*(uint *)(match + refDelta) != *((uint *)ip))); } // Catch up while ((ip > anchor) && (match + refDelta > lowLimit) && (ip[-1] == match[refDelta - 1])) { ip--; match--; } // Encode Literal length byte *token; { int litLength = (int)(ip - anchor); token = op++; if ((outputLimited == LimitedOutput.LimitedOutput) && (op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit)) { return(0); /* Check output limit */ } if (litLength >= RUN_MASK) { int len = litLength - RUN_MASK; * token = RUN_MASK << ML_BITS; for (; len >= 255; len -= 255) { *op++ = 255; } *op++ = (byte)len; } else { *token = (byte)(litLength << ML_BITS); } /* Copy Literals */ WildCopy(op, anchor, op + litLength); op += litLength; } _next_match: // Encode Offset *((ushort *)op) = (ushort)(ip - match); op += sizeof(ushort); // Encode MatchLength { int matchLength; if ((dict == DictionaryType.UsingExtDict) && (lowLimit == dictionary)) { match += refDelta; byte *limit = ip + (dictEnd - match); if (limit > matchlimit) { limit = matchlimit; } matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, limit); ip += MINMATCH + matchLength; if (ip == limit) { int more = LZ4_count(ip, source, matchlimit); matchLength += more; ip += more; } } else { matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); ip += MINMATCH + matchLength; } if ((outputLimited == LimitedOutput.LimitedOutput) && ((op + (1 + LASTLITERALS) + (matchLength >> 8)) > olimit)) { return(0); /* Check output limit */ } if (matchLength >= ML_MASK) { *token += ML_MASK; matchLength -= ML_MASK; for (; matchLength >= 510; matchLength -= 510) { *op++ = 255; *op++ = 255; } if (matchLength >= 255) { matchLength -= 255; *op++ = 255; } *op++ = (byte)matchLength; } else { *token += (byte)(matchLength); } } anchor = ip; // Test end of chunk if (ip > mflimit) { break; } // Fill table LZ4_putPosition(ip - 2, dictPtr, tableType, @base); /* Test next position */ match = LZ4_getPosition(ip, dictPtr, tableType, @base); if (dict == DictionaryType.UsingExtDict) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } LZ4_putPosition(ip, dictPtr, tableType, @base); if (((dictIssue == DictionaryIssue.DictSmall) ? (match >= lowRefLimit) : true) && (match + MAX_DISTANCE >= ip) && (*(uint *)(match + refDelta) == *(uint *)(ip))) { token = op++; *token = 0; goto _next_match; } /* Prepare next loop */ forwardH = LZ4_hashPosition(++ip, tableType); } _last_literals: /* Encode Last Literals */ { int lastRun = (int)(iend - anchor); if ((outputLimited == LimitedOutput.LimitedOutput) && ((op - dest) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > maxOutputSize)) { return(0); // Check output limit; } if (lastRun >= RUN_MASK) { int accumulator = lastRun - RUN_MASK; * op++ = RUN_MASK << ML_BITS; for (; accumulator >= 255; accumulator -= 255) { *op++ = 255; } *op++ = (byte)accumulator; } else { *op++ = (byte)(lastRun << ML_BITS); } Unsafe.CopyBlock(op, anchor, (uint)lastRun); op += lastRun; } return((int)(op - dest)); }