sync-inflate.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. "use strict";
  2. let assert = require("assert").ok;
  3. let zlib = require("zlib");
  4. let util = require("util");
  5. let kMaxLength = require("buffer").kMaxLength;
  6. function Inflate(opts) {
  7. if (!(this instanceof Inflate)) {
  8. return new Inflate(opts);
  9. }
  10. if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
  11. opts.chunkSize = zlib.Z_MIN_CHUNK;
  12. }
  13. zlib.Inflate.call(this, opts);
  14. // Node 8 --> 9 compatibility check
  15. this._offset = this._offset === undefined ? this._outOffset : this._offset;
  16. this._buffer = this._buffer || this._outBuffer;
  17. if (opts && opts.maxLength != null) {
  18. this._maxLength = opts.maxLength;
  19. }
  20. }
  21. function createInflate(opts) {
  22. return new Inflate(opts);
  23. }
  24. function _close(engine, callback) {
  25. if (callback) {
  26. process.nextTick(callback);
  27. }
  28. // Caller may invoke .close after a zlib error (which will null _handle).
  29. if (!engine._handle) {
  30. return;
  31. }
  32. engine._handle.close();
  33. engine._handle = null;
  34. }
  35. Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
  36. if (typeof asyncCb === "function") {
  37. return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
  38. }
  39. let self = this;
  40. let availInBefore = chunk && chunk.length;
  41. let availOutBefore = this._chunkSize - this._offset;
  42. let leftToInflate = this._maxLength;
  43. let inOff = 0;
  44. let buffers = [];
  45. let nread = 0;
  46. let error;
  47. this.on("error", function (err) {
  48. error = err;
  49. });
  50. function handleChunk(availInAfter, availOutAfter) {
  51. if (self._hadError) {
  52. return;
  53. }
  54. let have = availOutBefore - availOutAfter;
  55. assert(have >= 0, "have should not go down");
  56. if (have > 0) {
  57. let out = self._buffer.slice(self._offset, self._offset + have);
  58. self._offset += have;
  59. if (out.length > leftToInflate) {
  60. out = out.slice(0, leftToInflate);
  61. }
  62. buffers.push(out);
  63. nread += out.length;
  64. leftToInflate -= out.length;
  65. if (leftToInflate === 0) {
  66. return false;
  67. }
  68. }
  69. if (availOutAfter === 0 || self._offset >= self._chunkSize) {
  70. availOutBefore = self._chunkSize;
  71. self._offset = 0;
  72. self._buffer = Buffer.allocUnsafe(self._chunkSize);
  73. }
  74. if (availOutAfter === 0) {
  75. inOff += availInBefore - availInAfter;
  76. availInBefore = availInAfter;
  77. return true;
  78. }
  79. return false;
  80. }
  81. assert(this._handle, "zlib binding closed");
  82. let res;
  83. do {
  84. res = this._handle.writeSync(
  85. flushFlag,
  86. chunk, // in
  87. inOff, // in_off
  88. availInBefore, // in_len
  89. this._buffer, // out
  90. this._offset, //out_off
  91. availOutBefore
  92. ); // out_len
  93. // Node 8 --> 9 compatibility check
  94. res = res || this._writeState;
  95. } while (!this._hadError && handleChunk(res[0], res[1]));
  96. if (this._hadError) {
  97. throw error;
  98. }
  99. if (nread >= kMaxLength) {
  100. _close(this);
  101. throw new RangeError(
  102. "Cannot create final Buffer. It would be larger than 0x" +
  103. kMaxLength.toString(16) +
  104. " bytes"
  105. );
  106. }
  107. let buf = Buffer.concat(buffers, nread);
  108. _close(this);
  109. return buf;
  110. };
  111. util.inherits(Inflate, zlib.Inflate);
  112. function zlibBufferSync(engine, buffer) {
  113. if (typeof buffer === "string") {
  114. buffer = Buffer.from(buffer);
  115. }
  116. if (!(buffer instanceof Buffer)) {
  117. throw new TypeError("Not a string or buffer");
  118. }
  119. let flushFlag = engine._finishFlushFlag;
  120. if (flushFlag == null) {
  121. flushFlag = zlib.Z_FINISH;
  122. }
  123. return engine._processChunk(buffer, flushFlag);
  124. }
  125. function inflateSync(buffer, opts) {
  126. return zlibBufferSync(new Inflate(opts), buffer);
  127. }
  128. module.exports = exports = inflateSync;
  129. exports.Inflate = Inflate;
  130. exports.createInflate = createInflate;
  131. exports.inflateSync = inflateSync;