@@ -543,51 +543,100 @@ ZEND_FUNCTION(zstd_uncompress_dict)
543543 char * input , * dict ;
544544 size_t input_len , dict_len ;
545545 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 ;
546551
547552 ZEND_PARSE_PARAMETERS_START (2 , 2 )
548553 Z_PARAM_STRING (input , input_len )
549554 Z_PARAM_STRING (dict , dict_len )
550555 ZEND_PARSE_PARAMETERS_END ();
551556
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 ) {
556561 ZSTD_WARNING ("it was not compressed by zstd" );
557562 RETURN_FALSE ;
563+ } else if (size == ZSTD_CONTENTSIZE_UNKNOWN ) {
564+ streaming = 1 ;
565+ size = input_len + ZSTD_DStreamOutSize ();
558566 }
559567
560- ZSTD_DCtx * const dctx = ZSTD_createDCtx ();
568+ dctx = ZSTD_createDCtx ();
561569 if (dctx == NULL ) {
562- ZSTD_WARNING ("ZSTD_createDCtx() error " );
570+ ZSTD_WARNING ("failed to prepare uncompression " );
563571 RETURN_FALSE ;
564572 }
565- ZSTD_DDict * const ddict = ZSTD_createDDict (dict ,
566- dict_len );
573+ ddict = ZSTD_createDDict (dict , dict_len );
567574 if (!ddict ) {
568- ZSTD_freeDStream (dctx );
569- ZSTD_WARNING ("ZSTD_createDDict() error " );
575+ ZSTD_freeDCtx (dctx );
576+ ZSTD_WARNING ("failed to load dictionary " );
570577 RETURN_FALSE ;
571578 }
572579
573- output = zend_string_alloc (rSize , 0 );
580+ output = zend_string_alloc (size , 0 );
574581
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 );
585636 }
637+
586638 ZSTD_freeDCtx (dctx );
587639 ZSTD_freeDDict (ddict );
588-
589- output = zstd_string_output_truncate (output , dSize );
590- RETVAL_NEW_STR (output );
591640}
592641
593642ZEND_FUNCTION (zstd_compress_init )
0 commit comments