@@ -86,8 +86,7 @@ class zlib_compressor_base : public compress_provider
86
86
87
87
if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR)
88
88
{
89
- throw std::runtime_error (" Prior unrecoverable compression stream error " +
90
- std::to_string (m_state));
89
+ throw std::runtime_error (" Prior unrecoverable compression stream error " + std::to_string (m_state));
91
90
}
92
91
93
92
if (input_size > std::numeric_limits<uInt>::max () || output_size > std::numeric_limits<uInt>::max ())
@@ -294,8 +293,17 @@ class brotli_compressor : public compress_provider
294
293
295
294
brotli_compressor (uint32_t window = BROTLI_DEFAULT_WINDOW,
296
295
uint32_t quality = BROTLI_DEFAULT_QUALITY,
297
- uint32_t mode = BROTLI_DEFAULT_MODE)
298
- : m_algorithm(BROTLI), m_window(window), m_quality(quality), m_mode(mode)
296
+ uint32_t mode = BROTLI_DEFAULT_MODE,
297
+ uint32_t block = 0 ,
298
+ uint32_t nomodel = 0 ,
299
+ uint32_t hint = 0 )
300
+ : m_algorithm(BROTLI)
301
+ , m_window(window)
302
+ , m_quality(quality)
303
+ , m_mode(mode)
304
+ , m_block(block)
305
+ , m_nomodel(nomodel)
306
+ , m_hint(hint)
299
307
{
300
308
(void )reset ();
301
309
}
@@ -323,42 +331,36 @@ class brotli_compressor : public compress_provider
323
331
}
324
332
325
333
const uint8_t * next_in = input;
326
- size_t avail_in;
334
+ size_t avail_in = 0 ;
327
335
uint8_t * next_out = output;
328
336
size_t avail_out = output_size;
329
337
size_t total_out;
330
338
331
339
if (BrotliEncoderHasMoreOutput (m_stream) == BROTLI_TRUE)
332
340
{
333
- avail_in = 0 ;
341
+ // Drain any compressed bytes remaining from a prior call
334
342
do
335
343
{
336
- m_state = BrotliEncoderCompressStream (m_stream,
337
- (hint == operation_hint::is_last) ? BROTLI_OPERATION_FINISH
338
- : BROTLI_OPERATION_FLUSH,
339
- &avail_in,
340
- &next_in,
341
- &avail_out,
342
- &next_out,
343
- &total_out);
344
+ m_state = BrotliEncoderCompressStream (
345
+ m_stream, BROTLI_OPERATION_FLUSH, &avail_in, &next_in, &avail_out, &next_out, &total_out);
344
346
} while (m_state == BROTLI_TRUE && avail_out && BrotliEncoderHasMoreOutput (m_stream) == BROTLI_TRUE);
345
347
}
346
348
347
- if (m_state == BROTLI_TRUE && avail_out)
349
+ if (m_state == BROTLI_TRUE && avail_out && input_size )
348
350
{
351
+ // Compress the caller-supplied buffer
349
352
avail_in = input_size;
350
353
do
351
354
{
352
- m_state = BrotliEncoderCompressStream (m_stream,
353
- (hint == operation_hint::is_last) ? BROTLI_OPERATION_FINISH
354
- : BROTLI_OPERATION_FLUSH,
355
- &avail_in,
356
- &next_in,
357
- &avail_out,
358
- &next_out,
359
- &total_out);
355
+ m_state = BrotliEncoderCompressStream (
356
+ m_stream, BROTLI_OPERATION_FLUSH, &avail_in, &next_in, &avail_out, &next_out, &total_out);
360
357
} while (m_state == BROTLI_TRUE && avail_out && BrotliEncoderHasMoreOutput (m_stream) == BROTLI_TRUE);
361
358
}
359
+ else
360
+ {
361
+ // We're not compressing any new data; ensure calculation sanity
362
+ input_size = 0 ;
363
+ }
362
364
363
365
if (m_state != BROTLI_TRUE)
364
366
{
@@ -367,7 +369,18 @@ class brotli_compressor : public compress_provider
367
369
368
370
if (hint == operation_hint::is_last)
369
371
{
370
- m_done = (BrotliEncoderIsFinished (m_stream) == BROTLI_TRUE);
372
+ if (avail_out)
373
+ {
374
+ // Make one more pass to finalize the compressed stream
375
+ _ASSERTE (!avail_in);
376
+ m_state = BrotliEncoderCompressStream (
377
+ m_stream, BROTLI_OPERATION_FINISH, &avail_in, &next_in, &avail_out, &next_out, &total_out);
378
+ if (m_state != BROTLI_TRUE)
379
+ {
380
+ throw std::runtime_error (" Unrecoverable error finalizing compression stream" );
381
+ }
382
+ m_done = (BrotliEncoderIsFinished (m_stream) == BROTLI_TRUE);
383
+ }
371
384
}
372
385
373
386
input_bytes_processed = input_size - avail_in;
@@ -415,7 +428,19 @@ class brotli_compressor : public compress_provider
415
428
}
416
429
if (m_state == BROTLI_TRUE && m_mode != BROTLI_DEFAULT_MODE)
417
430
{
418
- m_state = BrotliEncoderSetParameter (m_stream, BROTLI_PARAM_MODE, m_window);
431
+ m_state = BrotliEncoderSetParameter (m_stream, BROTLI_PARAM_MODE, m_mode);
432
+ }
433
+ if (m_state == BROTLI_TRUE && m_block != 0 )
434
+ {
435
+ m_state = BrotliEncoderSetParameter (m_stream, BROTLI_PARAM_LGBLOCK, m_block);
436
+ }
437
+ if (m_state == BROTLI_TRUE && m_nomodel != 0 )
438
+ {
439
+ m_state = BrotliEncoderSetParameter (m_stream, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, m_nomodel);
440
+ }
441
+ if (m_state == BROTLI_TRUE && m_hint != 0 )
442
+ {
443
+ m_state = BrotliEncoderSetParameter (m_stream, BROTLI_PARAM_SIZE_HINT, m_hint);
419
444
}
420
445
421
446
if (m_state != BROTLI_TRUE)
@@ -439,6 +464,9 @@ class brotli_compressor : public compress_provider
439
464
uint32_t m_window;
440
465
uint32_t m_quality;
441
466
uint32_t m_mode;
467
+ uint32_t m_block;
468
+ uint32_t m_nomodel;
469
+ uint32_t m_hint;
442
470
const utility::string_t & m_algorithm;
443
471
};
444
472
@@ -599,7 +627,8 @@ class generic_decompress_factory : public decompress_factory
599
627
static const std::vector<std::shared_ptr<compress_factory>> g_compress_factories
600
628
#if defined(CPPREST_HTTP_COMPRESSION)
601
629
= {std::make_shared<generic_compress_factory>(
602
- algorithm::GZIP, []() -> std::unique_ptr<compress_provider> { return utility::details::make_unique<gzip_compressor>(); }),
630
+ algorithm::GZIP,
631
+ []() -> std::unique_ptr<compress_provider> { return utility::details::make_unique<gzip_compressor>(); }),
603
632
std::make_shared<generic_compress_factory>(
604
633
algorithm::DEFLATE,
605
634
[]() -> std::unique_ptr<compress_provider> { return utility::details::make_unique<deflate_compressor>(); }),
@@ -619,15 +648,17 @@ static const std::vector<std::shared_ptr<decompress_factory>> g_decompress_facto
619
648
algorithm::GZIP,
620
649
500 ,
621
650
[]() -> std::unique_ptr<decompress_provider> { return utility::details::make_unique<gzip_decompressor>(); }),
622
- std::make_shared<generic_decompress_factory>(
623
- algorithm::DEFLATE,
624
- 500 ,
625
- []() -> std::unique_ptr<decompress_provider> { return utility::details::make_unique<deflate_decompressor>(); }),
651
+ std::make_shared<generic_decompress_factory>(algorithm::DEFLATE,
652
+ 500 ,
653
+ []() -> std::unique_ptr<decompress_provider> {
654
+ return utility::details::make_unique<deflate_decompressor>();
655
+ }),
626
656
#if defined(CPPREST_BROTLI_COMPRESSION)
627
- std::make_shared<generic_decompress_factory>(
628
- algorithm::BROTLI,
629
- 500 ,
630
- []() -> std::unique_ptr<decompress_provider> { return utility::details::make_unique<brotli_decompressor>(); })
657
+ std::make_shared<generic_decompress_factory>(algorithm::BROTLI,
658
+ 500 ,
659
+ []() -> std::unique_ptr<decompress_provider> {
660
+ return utility::details::make_unique<brotli_decompressor>();
661
+ })
631
662
#endif // CPPREST_BROTLI_COMPRESSION
632
663
};
633
664
#else // CPPREST_HTTP_COMPRESSION
@@ -713,7 +744,6 @@ std::shared_ptr<decompress_factory> get_decompress_factory(const utility::string
713
744
return std::shared_ptr<decompress_factory>();
714
745
}
715
746
716
-
717
747
std::unique_ptr<compress_provider> make_gzip_compressor (int compressionLevel, int method, int strategy, int memLevel)
718
748
{
719
749
#if defined(CPPREST_HTTP_COMPRESSION)
@@ -740,14 +770,18 @@ std::unique_ptr<compress_provider> make_deflate_compressor(int compressionLevel,
740
770
#endif // CPPREST_HTTP_COMPRESSION
741
771
}
742
772
743
- std::unique_ptr<compress_provider> make_brotli_compressor (uint32_t window, uint32_t quality, uint32_t mode)
773
+ std::unique_ptr<compress_provider> make_brotli_compressor (
774
+ uint32_t window, uint32_t quality, uint32_t mode, uint32_t block, uint32_t nomodel, uint32_t hint)
744
775
{
745
776
#if defined(CPPREST_HTTP_COMPRESSION) && defined(CPPREST_BROTLI_COMPRESSION)
746
- return utility::details::make_unique<brotli_compressor>(window, quality, mode);
777
+ return utility::details::make_unique<brotli_compressor>(window, quality, mode, block, nomodel, hint );
747
778
#else // CPPREST_BROTLI_COMPRESSION
748
779
(void )window;
749
780
(void )quality;
750
781
(void )mode;
782
+ (void )block;
783
+ (void )nomodel;
784
+ (void )hint;
751
785
return std::unique_ptr<compress_provider>();
752
786
#endif // CPPREST_BROTLI_COMPRESSION
753
787
}
0 commit comments