private void MakeWriteable(Partition partition) { if (partition.Writeable) { return; } // we can safely pass the raw pointer here and dispose DirectAdd scope immediately because // filter's content will be written to an overflow Debug.Assert(_tree.ShouldGoToOverflowPage(_ptrSize)); using (_tree.DirectAdd(partition.Key, Partition.PartitionSize, out byte *ptr)) { if (partition.IsEmpty == false) { UnmanagedMemory.Copy(ptr, partition.Ptr, Partition.PartitionSize); } partition.Writeable = true; partition.IsEmpty = false; partition.Ptr = ptr; } Writeable = true; }
private void MakeWriteable() { if (Writeable) { return; } var ptr = _tree.DirectAdd(_key, PtrSize); UnmanagedMemory.Copy(ptr, _basePtr, PtrSize); Initialize(ptr); Writeable = true; }
private static int LZ4_decompress_generic <TEndCondition, TEarlyEnd, TDictionaryType>(byte *source, byte *dest, int inputSize, int outputSize, int targetOutputSize, byte *lowPrefix, byte *dictStart, int dictSize) where TEndCondition : IEndConditionDirective where TEarlyEnd : IEarlyEndDirective where TDictionaryType : IDictionaryTypeDirective { /* Local Variables */ byte *ip = source; byte *iend = ip + inputSize; byte *op = dest; byte *oend = op + outputSize; byte *oexit = op + targetOutputSize; byte *lowLimit = lowPrefix - dictSize; byte *dictEnd = dictStart + dictSize; bool checkOffset = ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (dictSize < 64 * Constants.Size.Kilobyte)); // Special Cases if ((typeof(TEarlyEnd) == typeof(Partial)) && (oexit > oend - MFLIMIT)) { oexit = oend - MFLIMIT; // targetOutputSize too high => decode everything } if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (outputSize == 0)) { return(((inputSize == 1) && (*ip == 0)) ? 0 : -1); // Empty output buffer } if ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (outputSize == 0)) { return(*ip == 0 ? 1 : -1); } // Main Loop while (true) { int length; /* get literal length */ byte token = *ip++; if ((length = (token >> ML_BITS)) == RUN_MASK) { byte s; do { s = *ip++; length += s; }while (((typeof(TEndCondition) == typeof(EndOnInputSize)) ? ip < iend - RUN_MASK : true) && (s == 255)); if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (op + length) < op) { goto _output_error; /* overflow detection */ } if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip + length) < ip) { goto _output_error; /* overflow detection */ } } // copy literals byte *cpy = op + length; if (((typeof(TEndCondition) == typeof(EndOnInputSize)) && ((cpy > (typeof(TEarlyEnd) == typeof(Partial) ? oexit : oend - MFLIMIT)) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) || ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (cpy > oend - COPYLENGTH))) { if (typeof(TEarlyEnd) == typeof(Partial)) { if (cpy > oend) { goto _output_error; /* Error : write attempt beyond end of output buffer */ } if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip + length > iend)) { goto _output_error; /* Error : read attempt beyond end of input buffer */ } } else { if ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (cpy != oend)) { goto _output_error; /* Error : block decoding must stop exactly there */ } if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && ((ip + length != iend) || (cpy > oend))) { goto _output_error; /* Error : input must be consumed */ } } UnmanagedMemory.Copy(op, ip, length); ip += length; op += length; break; /* Necessarily EOF, due to parsing restrictions */ } WildCopy(op, ip, cpy); ip += length; op = cpy; /* get offset */ byte *match = cpy - *((ushort *)ip); ip += sizeof(ushort); if ((checkOffset) && (match < lowLimit)) { goto _output_error; /* Error : offset outside destination buffer */ } /* get matchlength */ if ((length = (token & ML_MASK)) == ML_MASK) { byte s; do { if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip > iend - LASTLITERALS)) { goto _output_error; } s = *ip++; length += s; }while (s == 255); if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (op + length) < op) { goto _output_error; /* overflow detection */ } } length += MINMATCH; /* check external dictionary */ if ((typeof(TDictionaryType) == typeof(UsingExtDict)) && (match < lowPrefix)) { if (op + length > oend - LASTLITERALS) { goto _output_error; /* doesn't respect parsing restriction */ } if (length <= (int)(lowPrefix - match)) { /* match can be copied as a single segment from external dictionary */ match = dictEnd - (lowPrefix - match); UnmanagedMemory.Move(op, match, length); // TODO: Check if move is required. op += length; } else { /* match encompass external dictionary and current segment */ int copySize = (int)(lowPrefix - match); UnmanagedMemory.Copy(op, dictEnd - copySize, copySize); op += copySize; copySize = length - copySize; if (copySize > (int)(op - lowPrefix)) /* overlap within current segment */ { byte *endOfMatch = op + copySize; byte *copyFrom = lowPrefix; while (op < endOfMatch) { *op++ = *copyFrom++; } } else { UnmanagedMemory.Copy(op, lowPrefix, copySize); op += copySize; } } continue; } /* copy repeated sequence */ cpy = op + length; if ((op - match) < 8) { int dec64 = dec64table[op - match]; op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; match += dec32table[op - match]; *((uint *)(op + 4)) = *(uint *)match; op += 8; match -= dec64; } else { *((ulong *)op) = *(ulong *)match; op += sizeof(ulong); match += sizeof(ulong); } if (cpy > oend - 12) { if (cpy > oend - LASTLITERALS) { goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ } if (op < oend - 8) { WildCopy(op, match, (oend - 8)); match += (oend - 8) - op; op = oend - 8; } while (op < cpy) { *op++ = *match++; } } else { WildCopy(op, match, cpy); } op = cpy; /* correction */ } /* end of decoding */ if (typeof(TEndCondition) == typeof(EndOnInputSize)) { return((int)(op - dest)); /* Nb of output bytes decoded */ } else { return((int)(ip - source)); /* Nb of input bytes read */ } /* Overflow error detected */ _output_error: return((int)(-(ip - source)) - 1); }
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) { *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 <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); } UnmanagedMemory.Copy(op, anchor, lastRun); op += lastRun; } return((int)(op - dest)); }