/*! ReadBits() : * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ public static size_t ReadBits(BIT_DStream_t bitD, U32 nbBits) { size_t value = LookBits(bitD, nbBits); SkipBits(bitD, nbBits); return(value); }
/*! LookBitsFast() : * unsafe version; only works if nbBits >= 1 */ public static size_t LookBitsFast(BIT_DStream_t bitD, U32 nbBits) { U32 regMask = sizeOfBitContainer * 8 - 1; Debug.Assert(nbBits >= 1); return((bitD.bitContainer << (int)(bitD.bitsConsumed & regMask)) >> (int)(((regMask + 1) - nbBits) & regMask)); }
/*! ReadBitsFast() : * unsafe version; only works only if nbBits >= 1 */ public static size_t ReadBitsFast(BIT_DStream_t bitD, U32 nbBits) { size_t value = LookBitsFast(bitD, nbBits); Debug.Assert(nbBits >= 1); SkipBits(bitD, nbBits); return(value); }
} /* size == U32 */ public static void InitDState(FSE_DState_t DStatePtr, BIT_DStream_t bitD, FSE_DTable *dt) { void * ptr = dt; FSE_DTableHeader *DTableH = (FSE_DTableHeader *)ptr; DStatePtr.state = ReadBits(bitD, DTableH->tableLog); ReloadDStream(bitD); DStatePtr.table = dt + 1; }
/*! DecodeSymbolFast() : * unsafe, only works if no symbol has a probability > 50% */ public static BYTE DecodeSymbolFast(FSE_DState_t DStatePtr, BIT_DStream_t bitD) { FSE_decode_t DInfo = ((FSE_decode_t *)(DStatePtr.table))[DStatePtr.state]; U32 nbBits = DInfo.nbBits; BYTE symbol = DInfo.symbol; size_t lowBits = ReadBitsFast(bitD, nbBits); DStatePtr.state = DInfo.newState + lowBits; return(symbol); }
/*! ReloadDStream() : * Refill `bitD` from buffer previously set in InitDStream() . * This function is safe, it guarantees it will not read beyond src buffer. * @return : status of `BIT_DStream_t` internal register. * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */ public static BIT_DStream_status ReloadDStream(BIT_DStream_t bitD) { if (bitD.bitsConsumed > (sizeOfBitContainer * 8)) /* overflow detected, like end of stream */ { return(BIT_DStream_status.BIT_DStream_overflow); } if (bitD.ptr >= bitD.limitPtr) { bitD.ptr -= bitD.bitsConsumed >> 3; bitD.bitsConsumed &= 7; bitD.bitContainer = MEM_readLEST(bitD.ptr); return(BIT_DStream_status.BIT_DStream_unfinished); } if (bitD.ptr == bitD.start) { if (bitD.bitsConsumed < sizeOfBitContainer * 8) { return(BIT_DStream_status.BIT_DStream_endOfBuffer); } return(BIT_DStream_status.BIT_DStream_completed); } /* start < ptr < limitPtr */ { U32 nbBytes = bitD.bitsConsumed >> 3; BIT_DStream_status result = BIT_DStream_status.BIT_DStream_unfinished; if (bitD.ptr - nbBytes < bitD.start) { nbBytes = (U32)(bitD.ptr - bitD.start); /* ptr > start */ result = BIT_DStream_status.BIT_DStream_endOfBuffer; } bitD.ptr -= nbBytes; bitD.bitsConsumed -= nbBytes * 8; bitD.bitContainer = MEM_readLEST(bitD.ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */ return(result); } }
//#ifndef FSE_COMMONDEFS_ONLY ///*-******************************************************* //* Decompression (Byte symbols) //*********************************************************/ //size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) //{ // void* ptr = dt; // FSE_DTableHeader* DTableH = (FSE_DTableHeader*)ptr; // void* dPtr = dt + 1; // FSE_decode_t* cell = (FSE_decode_t*)dPtr; // DTableH->tableLog = 0; // DTableH->fastMode = 0; // cell->newState = 0; // cell->symbol = symbolValue; // cell->nbBits = 0; // return 0; //} //size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) //{ // void* ptr = dt; // FSE_DTableHeader* DTableH = (FSE_DTableHeader*)ptr; // void* dPtr = dt + 1; // FSE_decode_t* dinfo = (FSE_decode_t*)dPtr; // unsigned tableSize = 1 << nbBits; // unsigned tableMask = tableSize - 1; // unsigned maxSV1 = tableMask+1; // unsigned s; // /* Sanity checks */ // if (nbBits < 1) return ERROR( Error.GENERIC); /* min size */ // /* Build Decoding Table */ // DTableH->tableLog = (U16)nbBits; // DTableH->fastMode = 1; // for (s=0; s<maxSV1; s++) { // dinfo[s].newState = 0; // dinfo[s].symbol = (BYTE)s; // dinfo[s].nbBits = (BYTE)nbBits; // } // return 0; //} public static size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, void *cSrc, size_t cSrcSize, FSE_DTable *dt, uint fast) { BYTE *ostart = (BYTE *)dst; BYTE *op = ostart; BYTE *omax = op + maxDstSize; BYTE *olimit = omax - 3; BIT_DStream_t bitD = new BIT_DStream_t(); FSE_DState_t state1 = new FSE_DState_t(); FSE_DState_t state2 = new FSE_DState_t(); /* Init */ { size_t errcod = InitDStream(bitD, cSrc, cSrcSize); if (IsError(errcod)) { return(errcod); } } Fse.InitDState(state1, bitD, dt); Fse.InitDState(state2, bitD, dt); //#define FSE_GETSYMBOL(statePtr) fast ? DecodeSymbolFast(statePtr, &bitD) : DecodeSymbol(statePtr, &bitD) /* 4 symbols per loop */ for (; (ReloadDStream(bitD) == BIT_DStream_status.BIT_DStream_unfinished) & (op < olimit); op += 4) { op[0] = fast != 0 ? DecodeSymbolFast(state1, bitD) : DecodeSymbol(state1, bitD); //if (FSE_MAX_TABLELOG * 2 + 7 > sizeOfBitContainer * 8) /* This test must be static */ // ReloadDStream(bitD); op[1] = fast != 0 ? DecodeSymbolFast(state2, bitD) : DecodeSymbol(state2, bitD); if (FSE_MAX_TABLELOG * 4 + 7 > sizeOfBitContainer * 8) /* This test must be static */ { if (ReloadDStream(bitD) > BIT_DStream_status.BIT_DStream_unfinished) { op += 2; break; } } op[2] = fast != 0 ? DecodeSymbolFast(state1, bitD) : DecodeSymbol(state1, bitD); //if (FSE_MAX_TABLELOG * 2 + 7 > sizeOfBitContainer * 8) /* This test must be static */ // ReloadDStream(bitD); op[3] = fast != 0 ? DecodeSymbolFast(state2, bitD) : DecodeSymbol(state2, bitD); } /* tail */ /* note : ReloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ while (true) { if (op > (omax - 2)) { return(ERROR(Error.dstSize_tooSmall)); } *op++ = fast != 0 ? DecodeSymbolFast(state1, bitD) : DecodeSymbol(state1, bitD); if (ReloadDStream(bitD) == BIT_DStream_status.BIT_DStream_overflow) { *op++ = fast != 0 ? DecodeSymbolFast(state2, bitD) : DecodeSymbol(state2, bitD); break; } if (op > (omax - 2)) { return(ERROR(Error.dstSize_tooSmall)); } *op++ = fast != 0 ? DecodeSymbolFast(state2, bitD) : DecodeSymbol(state2, bitD); if (ReloadDStream(bitD) == BIT_DStream_status.BIT_DStream_overflow) { *op++ = fast != 0 ? DecodeSymbolFast(state1, bitD) : DecodeSymbol(state1, bitD); break; } } return((size_t)(op - ostart)); }
/*! EndOfDStream() : * @return : 1 if DStream has _exactly_ reached its end (all bits consumed). */ public static uint EndOfDStream(BIT_DStream_t DStream) { return(((DStream.ptr == DStream.start) && (DStream.bitsConsumed == sizeOfBitContainer * 8)) ? (uint)1 : 0); }
public static void SkipBits(BIT_DStream_t bitD, U32 nbBits) { bitD.bitsConsumed += nbBits; }
//MEM_STATIC size_t GetUpperBits(size_t bitContainer, U32 start) //{ // return bitContainer >> start; //} //MEM_STATIC size_t GetMiddleBits(size_t bitContainer, U32 start, U32 nbBits) //{ //#if defined(__BMI__) && defined(__GNUC__) && __GNUC__*1000+__GNUC_MINOR__ >= 4008 /* experimental */ //# if defined(__x86_64__) // if (sizeof(bitContainer)==8) // return _bextr_u64(bitContainer, start, nbBits); // else //# endif // return _bextr_u32(bitContainer, start, nbBits); //#else // Debug.Assert(nbBits < BIT_MASK_SIZE); // return (bitContainer >> start) & BIT_mask[nbBits]; //#endif //} //MEM_STATIC size_t GetLowerBits(size_t bitContainer, U32 nbBits) //{ // Debug.Assert(nbBits < BIT_MASK_SIZE); // return bitContainer & BIT_mask[nbBits]; //} /*! LookBits() : * Provides next n bits from local register. * local register is not modified. * On 32-bits, maxNbBits==24. * On 64-bits, maxNbBits==56. * @return : value extracted */ public static size_t LookBits(BIT_DStream_t bitD, U32 nbBits) { U32 regMask = sizeOfBitContainer * 8 - 1; return(((bitD.bitContainer << (int)(bitD.bitsConsumed & regMask)) >> 1) >> (int)((regMask - nbBits) & regMask)); }
public const uint sizeOfBitContainer = 4; //sizeof(BIT_DStream_t.bitContainer) /*-******************************************************** * bitStream decoding **********************************************************/ /*! InitDStream() : * Initialize a BIT_DStream_t. * `bitD` : a pointer to an already allocated BIT_DStream_t structure. * `srcSize` must be the *exact* size of the bitStream, in bytes. * @return : size of stream (== srcSize), or an errorCode if a problem is detected */ public static size_t InitDStream(BIT_DStream_t bitD, void *srcBuffer, size_t srcSize) { if (srcSize < 1) { bitD.Reset(); return(ERROR(Error.srcSize_wrong)); } bitD.start = (sbyte *)srcBuffer; bitD.limitPtr = bitD.start + sizeOfBitContainer; if (srcSize >= sizeOfBitContainer) { /* normal case */ bitD.ptr = (sbyte *)srcBuffer + srcSize - sizeOfBitContainer; bitD.bitContainer = MEM_readLEST(bitD.ptr); { BYTE lastByte = ((BYTE *)srcBuffer)[srcSize - 1]; bitD.bitsConsumed = lastByte != 0 ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */ if (lastByte == 0) { return(ERROR(Error.GENERIC)); /* endMark not present */ } } } else { bitD.ptr = bitD.start; bitD.bitContainer = *(BYTE *)(bitD.start); { if (srcSize >= 7) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[6]) << (int)(sizeOfBitContainer * 8 - 16); } /* fall-through */ if (srcSize >= 6) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[5]) << (int)(sizeOfBitContainer * 8 - 24); } /* fall-through */ if (srcSize >= 5) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[4]) << (int)(sizeOfBitContainer * 8 - 32); } /* fall-through */ if (srcSize >= 4) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[3]) << 24; } /* fall-through */ if (srcSize >= 3) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[2]) << 16; } /* fall-through */ if (srcSize >= 2) { bitD.bitContainer += (size_t)(((BYTE *)(srcBuffer))[1]) << 8; } /* fall-through */ /*default: break;*/ } { BYTE lastByte = ((BYTE *)srcBuffer)[srcSize - 1]; bitD.bitsConsumed = lastByte != 0 ? 8 - BIT_highbit32(lastByte) : 0; if (lastByte == 0) { return(ERROR(Error.corruption_detected)); /* endMark not present */ } } bitD.bitsConsumed += (U32)(sizeOfBitContainer - srcSize) * 8; } return(srcSize); }