5252#include < cstdlib>
5353#include < cstring>
5454#include < optional>
55+ #include < utility>
56+ #include < vector>
5557
5658namespace node {
5759
@@ -178,6 +180,18 @@ struct CompressionError {
178180 inline bool IsError () const { return code != nullptr ; }
179181};
180182
183+ void RecordBrotliParam (std::vector<std::pair<int , uint32_t >>* params,
184+ int key,
185+ uint32_t value) {
186+ for (auto & entry : *params) {
187+ if (entry.first == key) {
188+ entry.second = value;
189+ return ;
190+ }
191+ }
192+ params->emplace_back (key, value);
193+ }
194+
181195class ZlibContext final : public MemoryRetainer {
182196 public:
183197 ZlibContext () = default ;
@@ -286,6 +300,8 @@ class BrotliEncoderContext final : public BrotliContext {
286300 prepared_dictionary_;
287301 // Dictionary data must remain valid while the prepared dictionary is alive.
288302 std::vector<uint8_t > dictionary_;
303+ // Last successful parameters, replayed by ResetStream.
304+ std::vector<std::pair<int , uint32_t >> params_;
289305};
290306
291307class BrotliDecoderContext final : public BrotliContext {
@@ -308,6 +324,8 @@ class BrotliDecoderContext final : public BrotliContext {
308324 DeleteFnPtr<BrotliDecoderState, BrotliDecoderDestroyInstance> state_;
309325 // Dictionary data must remain valid for the lifetime of the decoder.
310326 std::vector<uint8_t > dictionary_;
327+ // Last successful parameters, replayed by ResetStream.
328+ std::vector<std::pair<int , uint32_t >> params_;
311329};
312330
313331class ZstdContext : public MemoryRetainer {
@@ -1505,6 +1523,7 @@ void BrotliEncoderContext::Close() {
15051523 state_.reset ();
15061524 prepared_dictionary_.reset ();
15071525 dictionary_.clear ();
1526+ params_.clear ();
15081527 mode_ = NONE ;
15091528}
15101529
@@ -1518,6 +1537,7 @@ CompressionError BrotliEncoderContext::Init(std::vector<uint8_t>&& dictionary) {
15181537 // Clean up any previous dictionary state before re-initializing.
15191538 prepared_dictionary_.reset ();
15201539 dictionary_.clear ();
1540+ params_.clear ();
15211541
15221542 state_.reset (BrotliEncoderCreateInstance (alloc, free, opaque));
15231543 if (!state_) {
@@ -1557,7 +1577,19 @@ CompressionError BrotliEncoderContext::Init(std::vector<uint8_t>&& dictionary) {
15571577}
15581578
15591579CompressionError BrotliEncoderContext::ResetStream () {
1560- return Init ();
1580+ std::vector<uint8_t > dictionary = dictionary_;
1581+ const auto params = params_;
1582+ CompressionError err = Init (std::move (dictionary));
1583+ if (err.IsError ()) {
1584+ return err;
1585+ }
1586+ for (const auto & entry : params) {
1587+ err = SetParams (entry.first , entry.second );
1588+ if (err.IsError ()) {
1589+ return err;
1590+ }
1591+ }
1592+ return CompressionError{};
15611593}
15621594
15631595CompressionError BrotliEncoderContext::SetParams (int key, uint32_t value) {
@@ -1568,6 +1600,7 @@ CompressionError BrotliEncoderContext::SetParams(int key, uint32_t value) {
15681600 " ERR_BROTLI_PARAM_SET_FAILED" ,
15691601 -1 );
15701602 } else {
1603+ RecordBrotliParam (¶ms_, key, value);
15711604 return CompressionError {};
15721605 }
15731606}
@@ -1586,6 +1619,7 @@ CompressionError BrotliEncoderContext::GetErrorInfo() const {
15861619void BrotliDecoderContext::Close () {
15871620 state_.reset ();
15881621 dictionary_.clear ();
1622+ params_.clear ();
15891623 mode_ = NONE ;
15901624}
15911625
@@ -1615,6 +1649,7 @@ CompressionError BrotliDecoderContext::Init(std::vector<uint8_t>&& dictionary) {
16151649
16161650 // Clean up any previous dictionary state before re-initializing.
16171651 dictionary_.clear ();
1652+ params_.clear ();
16181653
16191654 state_.reset (BrotliDecoderCreateInstance (alloc, free, opaque));
16201655 if (!state_) {
@@ -1642,7 +1677,19 @@ CompressionError BrotliDecoderContext::Init(std::vector<uint8_t>&& dictionary) {
16421677}
16431678
16441679CompressionError BrotliDecoderContext::ResetStream () {
1645- return Init ();
1680+ std::vector<uint8_t > dictionary = dictionary_;
1681+ const auto params = params_;
1682+ CompressionError err = Init (std::move (dictionary));
1683+ if (err.IsError ()) {
1684+ return err;
1685+ }
1686+ for (const auto & entry : params) {
1687+ err = SetParams (entry.first , entry.second );
1688+ if (err.IsError ()) {
1689+ return err;
1690+ }
1691+ }
1692+ return CompressionError{};
16461693}
16471694
16481695CompressionError BrotliDecoderContext::SetParams (int key, uint32_t value) {
@@ -1653,6 +1700,7 @@ CompressionError BrotliDecoderContext::SetParams(int key, uint32_t value) {
16531700 " ERR_BROTLI_PARAM_SET_FAILED" ,
16541701 -1 );
16551702 } else {
1703+ RecordBrotliParam (¶ms_, key, value);
16561704 return CompressionError {};
16571705 }
16581706}
0 commit comments