@@ -378,5 +378,187 @@ private static uint BIT_endOfDStream(BIT_DStream_t* DStream)
378378 {
379379 return DStream ->ptr == DStream ->start && DStream ->bitsConsumed == ( uint ) ( sizeof ( nuint ) * 8 ) ? 1U : 0U ;
380380 }
381+
382+ /*-********************************************************
383+ * bitStream decoding
384+ **********************************************************/
385+ /*! BIT_initDStream() :
386+ * Initialize a BIT_DStream_t.
387+ * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
388+ * `srcSize` must be the *exact* size of the bitStream, in bytes.
389+ * @return : size of stream (== srcSize), or an errorCode if a problem is detected
390+ */
391+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
392+ private static nuint BIT_initDStream ( ref BIT_DStream_t bitD , void * srcBuffer , nuint srcSize )
393+ {
394+ if ( srcSize < 1 )
395+ {
396+ memset ( ref bitD , 0 , ( uint ) sizeof ( BIT_DStream_t ) ) ;
397+ return unchecked ( ( nuint ) ( - ( int ) ZSTD_ErrorCode . ZSTD_error_srcSize_wrong ) ) ;
398+ }
399+
400+ bitD . start = ( sbyte * ) srcBuffer ;
401+ bitD . limitPtr = bitD . start + sizeof ( nuint ) ;
402+ if ( srcSize >= ( nuint ) sizeof ( nuint ) )
403+ {
404+ bitD . ptr = ( sbyte * ) srcBuffer + srcSize - sizeof ( nuint ) ;
405+ bitD . bitContainer = MEM_readLEST ( bitD . ptr ) ;
406+ {
407+ byte lastByte = ( ( byte * ) srcBuffer ) [ srcSize - 1 ] ;
408+ bitD . bitsConsumed = lastByte != 0 ? 8 - ZSTD_highbit32 ( lastByte ) : 0 ;
409+ if ( lastByte == 0 )
410+ return unchecked ( ( nuint ) ( - ( int ) ZSTD_ErrorCode . ZSTD_error_GENERIC ) ) ;
411+ }
412+ }
413+ else
414+ {
415+ bitD . ptr = bitD . start ;
416+ bitD . bitContainer = * ( byte * ) bitD . start ;
417+ switch ( srcSize )
418+ {
419+ case 7 :
420+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer) [ 6 ] << sizeof ( nuint ) * 8 - 16 ;
421+ goto case 6 ;
422+ case 6 :
423+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer ) [ 5 ] << sizeof ( nuint ) * 8 - 24 ;
424+ goto case 5 ;
425+ case 5 :
426+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer ) [ 4 ] << sizeof ( nuint ) * 8 - 32 ;
427+ goto case 4 ;
428+ case 4 :
429+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer ) [ 3 ] << 24 ;
430+ goto case 3 ;
431+ case 3 :
432+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer ) [ 2 ] << 16 ;
433+ goto case 2 ;
434+ case 2 :
435+ bitD . bitContainer += ( nuint ) ( ( byte * ) srcBuffer ) [ 1 ] << 8 ;
436+ goto default ;
437+ default :
438+ break ;
439+ }
440+
441+ {
442+ byte lastByte = ( ( byte * ) srcBuffer ) [ srcSize - 1 ] ;
443+ bitD . bitsConsumed = lastByte != 0 ? 8 - ZSTD_highbit32 ( lastByte ) : 0 ;
444+ if ( lastByte == 0 )
445+ return unchecked ( ( nuint ) ( - ( int ) ZSTD_ErrorCode . ZSTD_error_corruption_detected ) ) ;
446+ }
447+
448+ bitD . bitsConsumed += ( uint ) ( ( nuint ) sizeof ( nuint ) - srcSize ) * 8 ;
449+ }
450+
451+ return srcSize ;
452+ }
453+
454+ /*! BIT_lookBits() :
455+ * Provides next n bits from local register.
456+ * local register is not modified.
457+ * On 32-bits, maxNbBits==24.
458+ * On 64-bits, maxNbBits==56.
459+ * @return : value extracted */
460+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
461+ private static nuint BIT_lookBits ( ref BIT_DStream_t bitD , uint nbBits )
462+ {
463+ return BIT_getMiddleBits ( bitD . bitContainer , ( uint ) ( sizeof ( nuint ) * 8 ) - bitD . bitsConsumed - nbBits , nbBits ) ;
464+ }
465+
466+ /*! BIT_lookBitsFast() :
467+ * unsafe version; only works if nbBits >= 1 */
468+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
469+ [ InlineMethod . Inline ]
470+ private static nuint BIT_lookBitsFast ( ref BIT_DStream_t bitD , uint nbBits )
471+ {
472+ uint regMask = ( uint ) ( sizeof ( nuint ) * 8 - 1 ) ;
473+ assert ( nbBits >= 1 ) ;
474+ return bitD . bitContainer << ( int ) ( bitD . bitsConsumed & regMask ) >> ( int ) ( regMask + 1 - nbBits & regMask ) ;
475+ }
476+
477+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
478+ [ InlineMethod . Inline ]
479+ private static void BIT_skipBits ( ref BIT_DStream_t bitD , uint nbBits )
480+ {
481+ bitD . bitsConsumed += nbBits ;
482+ }
483+
484+ /*! BIT_readBits() :
485+ * Read (consume) next n bits from local register and update.
486+ * Pay attention to not read more than nbBits contained into local register.
487+ * @return : extracted value. */
488+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
489+ private static nuint BIT_readBits ( ref BIT_DStream_t bitD , uint nbBits )
490+ {
491+ nuint value = BIT_lookBits ( ref bitD , nbBits ) ;
492+ BIT_skipBits ( ref bitD , nbBits ) ;
493+ return value ;
494+ }
495+
496+ /*! BIT_readBitsFast() :
497+ * unsafe version; only works if nbBits >= 1 */
498+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
499+ private static nuint BIT_readBitsFast ( ref BIT_DStream_t bitD , uint nbBits )
500+ {
501+ nuint value = BIT_lookBitsFast ( ref bitD , nbBits ) ;
502+ assert ( nbBits >= 1 ) ;
503+ BIT_skipBits ( ref bitD , nbBits ) ;
504+ return value ;
505+ }
506+
507+ /*! BIT_reloadDStreamFast() :
508+ * Similar to BIT_reloadDStream(), but with two differences:
509+ * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
510+ * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
511+ * point you must use BIT_reloadDStream() to reload.
512+ */
513+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
514+ [ InlineMethod . Inline ]
515+ private static BIT_DStream_status BIT_reloadDStreamFast ( ref BIT_DStream_t bitD )
516+ {
517+ if ( bitD . ptr < bitD . limitPtr )
518+ return BIT_DStream_status . BIT_DStream_overflow ;
519+ assert ( bitD . bitsConsumed <= ( uint ) ( sizeof ( nuint ) * 8 ) ) ;
520+ bitD . ptr -= bitD . bitsConsumed >> 3 ;
521+ bitD . bitsConsumed &= 7 ;
522+ bitD . bitContainer = MEM_readLEST ( bitD . ptr ) ;
523+ return BIT_DStream_status . BIT_DStream_unfinished ;
524+ }
525+
526+ /*! BIT_reloadDStream() :
527+ * Refill `bitD` from buffer previously set in BIT_initDStream() .
528+ * This function is safe, it guarantees it will not read beyond src buffer.
529+ * @return : status of `BIT_DStream_t` internal register.
530+ * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
531+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
532+ private static BIT_DStream_status BIT_reloadDStream ( ref BIT_DStream_t bitD )
533+ {
534+ if ( bitD . bitsConsumed > ( uint ) ( sizeof ( nuint ) * 8 ) )
535+ return BIT_DStream_status . BIT_DStream_overflow ;
536+ if ( bitD . ptr >= bitD . limitPtr )
537+ {
538+ return BIT_reloadDStreamFast ( ref bitD ) ;
539+ }
540+
541+ if ( bitD . ptr == bitD . start )
542+ {
543+ if ( bitD . bitsConsumed < ( uint ) ( sizeof ( nuint ) * 8 ) )
544+ return BIT_DStream_status . BIT_DStream_endOfBuffer ;
545+ return BIT_DStream_status . BIT_DStream_completed ;
546+ }
547+
548+ {
549+ uint nbBytes = bitD . bitsConsumed >> 3 ;
550+ BIT_DStream_status result = BIT_DStream_status . BIT_DStream_unfinished ;
551+ if ( bitD . ptr - nbBytes < bitD . start )
552+ {
553+ nbBytes = ( uint ) ( bitD . ptr - bitD . start ) ;
554+ result = BIT_DStream_status . BIT_DStream_endOfBuffer ;
555+ }
556+
557+ bitD . ptr -= nbBytes ;
558+ bitD . bitsConsumed -= nbBytes * 8 ;
559+ bitD . bitContainer = MEM_readLEST ( bitD . ptr ) ;
560+ return result ;
561+ }
562+ }
381563 }
382564}
0 commit comments