@@ -543,51 +543,100 @@ ZEND_FUNCTION(zstd_uncompress_dict)
543
543
char * input , * dict ;
544
544
size_t input_len , dict_len ;
545
545
zend_string * output ;
546
+ uint8_t streaming = 0 ;
547
+ size_t result ;
548
+ unsigned long long size ;
549
+ ZSTD_DCtx * dctx ;
550
+ ZSTD_DDict * ddict ;
546
551
547
552
ZEND_PARSE_PARAMETERS_START (2 , 2 )
548
553
Z_PARAM_STRING (input , input_len )
549
554
Z_PARAM_STRING (dict , dict_len )
550
555
ZEND_PARSE_PARAMETERS_END ();
551
556
552
- unsigned long long const rSize = ZSTD_getFrameContentSize (input ,
553
- input_len );
554
-
555
- if ( rSize == 0 || rSize == ZSTD_CONTENTSIZE_ERROR ) {
557
+ size = ZSTD_getFrameContentSize (input , input_len );
558
+ if ( size == 0 ) {
559
+ RETURN_EMPTY_STRING ();
560
+ } else if ( size == ZSTD_CONTENTSIZE_ERROR ) {
556
561
ZSTD_WARNING ("it was not compressed by zstd" );
557
562
RETURN_FALSE ;
563
+ } else if (size == ZSTD_CONTENTSIZE_UNKNOWN ) {
564
+ streaming = 1 ;
565
+ size = input_len + ZSTD_DStreamOutSize ();
558
566
}
559
567
560
- ZSTD_DCtx * const dctx = ZSTD_createDCtx ();
568
+ dctx = ZSTD_createDCtx ();
561
569
if (dctx == NULL ) {
562
- ZSTD_WARNING ("ZSTD_createDCtx() error " );
570
+ ZSTD_WARNING ("failed to prepare uncompression " );
563
571
RETURN_FALSE ;
564
572
}
565
- ZSTD_DDict * const ddict = ZSTD_createDDict (dict ,
566
- dict_len );
573
+ ddict = ZSTD_createDDict (dict , dict_len );
567
574
if (!ddict ) {
568
- ZSTD_freeDStream (dctx );
569
- ZSTD_WARNING ("ZSTD_createDDict() error " );
575
+ ZSTD_freeDCtx (dctx );
576
+ ZSTD_WARNING ("failed to load dictionary " );
570
577
RETURN_FALSE ;
571
578
}
572
579
573
- output = zend_string_alloc (rSize , 0 );
580
+ output = zend_string_alloc (size , 0 );
574
581
575
- size_t const dSize = ZSTD_decompress_usingDDict (dctx , ZSTR_VAL (output ), rSize ,
576
- input ,
577
- input_len ,
578
- ddict );
579
- if (dSize != rSize ) {
580
- ZSTD_freeDStream (dctx );
581
- ZSTD_freeDDict (ddict );
582
- zend_string_efree (output );
583
- ZSTD_WARNING ("%s" , ZSTD_getErrorName (dSize ));
584
- RETURN_FALSE ;
582
+ if (!streaming ) {
583
+ result = ZSTD_decompress_usingDDict (dctx , ZSTR_VAL (output ), size ,
584
+ input , input_len , ddict );
585
+ if (ZSTD_IS_ERROR (result )) {
586
+ zend_string_efree (output );
587
+ ZSTD_WARNING ("%s" , ZSTD_getErrorName (result ));
588
+ RETVAL_FALSE ;
589
+ } else if (result != size ) {
590
+ zend_string_efree (output );
591
+ ZSTD_WARNING ("failed to uncompress" );
592
+ RETVAL_FALSE ;
593
+ } else {
594
+ output = zstd_string_output_truncate (output , result );
595
+ RETVAL_NEW_STR (output );
596
+ }
597
+ } else {
598
+ ZSTD_inBuffer in = { NULL , 0 , 0 };
599
+ ZSTD_outBuffer out = { NULL , 0 , 0 };
600
+ size_t chunk = ZSTD_DStreamOutSize ();
601
+
602
+ ZSTD_DCtx_reset (dctx , ZSTD_reset_session_only );
603
+ ZSTD_DCtx_refDDict (dctx , ddict );
604
+
605
+ in .src = input ;
606
+ in .size = input_len ;
607
+ in .pos = 0 ;
608
+
609
+ out .dst = ZSTR_VAL (output );
610
+ out .size = size ;
611
+ out .pos = 0 ;
612
+
613
+ while (in .pos < in .size ) {
614
+ if (out .pos == out .size ) {
615
+ out .size += chunk ;
616
+ output = zend_string_extend (output , out .size , 0 );
617
+ out .dst = ZSTR_VAL (output );
618
+ }
619
+
620
+ result = ZSTD_decompressStream (dctx , & out , & in );
621
+ if (ZSTD_IS_ERROR (result )) {
622
+ zend_string_efree (output );
623
+ ZSTD_freeDCtx (dctx );
624
+ ZSTD_freeDDict (ddict );
625
+ ZSTD_WARNING ("%s" , ZSTD_getErrorName (result ));
626
+ RETURN_FALSE ;
627
+ }
628
+
629
+ if (result == 0 ) {
630
+ break ;
631
+ }
632
+ }
633
+
634
+ output = zstd_string_output_truncate (output , out .pos );
635
+ RETVAL_NEW_STR (output );
585
636
}
637
+
586
638
ZSTD_freeDCtx (dctx );
587
639
ZSTD_freeDDict (ddict );
588
-
589
- output = zstd_string_output_truncate (output , dSize );
590
- RETVAL_NEW_STR (output );
591
640
}
592
641
593
642
ZEND_FUNCTION (zstd_compress_init )
0 commit comments