@@ -378,5 +378,187 @@ private static uint BIT_endOfDStream(BIT_DStream_t* DStream)
378
378
{
379
379
return DStream ->ptr == DStream ->start && DStream ->bitsConsumed == ( uint ) ( sizeof ( nuint ) * 8 ) ? 1U : 0U ;
380
380
}
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
+ }
381
563
}
382
564
}
0 commit comments