Source: util/dynamic-buffer.js

  1. /**
  2. * Encapsulate a Buffer and support dynamic reallocation.
  3. * Copyright (C) 2013-2016 Regents of the University of California.
  4. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. * A copy of the GNU Lesser General Public License is in the file COPYING.
  19. */
  20. /**
  21. * Create a DynamicBuffer where this.array is a Buffer of size length.
  22. * To access the array, use this.array or call slice.
  23. * @constructor
  24. * @param {number} length the initial length of the array. If null, use a default.
  25. */
  26. var DynamicBuffer = function DynamicBuffer(length)
  27. {
  28. if (!length)
  29. length = 16;
  30. this.array = new Buffer(length);
  31. };
  32. exports.DynamicBuffer = DynamicBuffer;
  33. /**
  34. * Ensure that this.array has the length, reallocate and copy if necessary.
  35. * Update the length of this.array which may be greater than length.
  36. * @param {number} length The minimum length for the array.
  37. */
  38. DynamicBuffer.prototype.ensureLength = function(length)
  39. {
  40. if (this.array.length >= length)
  41. return;
  42. // See if double is enough.
  43. var newLength = this.array.length * 2;
  44. if (length > newLength)
  45. // The needed length is much greater, so use it.
  46. newLength = length;
  47. var newArray = new Buffer(newLength);
  48. this.array.copy(newArray);
  49. this.array = newArray;
  50. };
  51. /**
  52. * Copy the value to this.array at offset, reallocating if necessary.
  53. * @param {Buffer} value The buffer to copy.
  54. * @param {number} offset The offset in the buffer to start copying into.
  55. * @returns {number} The new offset which is offset + value.length.
  56. */
  57. DynamicBuffer.prototype.copy = function(value, offset)
  58. {
  59. this.ensureLength(value.length + offset);
  60. if (Buffer.isBuffer(value))
  61. value.copy(this.array, offset);
  62. else
  63. // Need to make value a Buffer to copy.
  64. new Buffer(value).copy(this.array, offset);
  65. return offset + value.length;
  66. };
  67. /**
  68. * Ensure that this.array has the length. If necessary, reallocate the array
  69. * and shift existing data to the back of the new array.
  70. * Update the length of this.array which may be greater than length.
  71. * @param {number} length The minimum length for the array.
  72. */
  73. DynamicBuffer.prototype.ensureLengthFromBack = function(length)
  74. {
  75. if (this.array.length >= length)
  76. return;
  77. // See if double is enough.
  78. var newLength = this.array.length * 2;
  79. if (length > newLength)
  80. // The needed length is much greater, so use it.
  81. newLength = length;
  82. var newArray = new Buffer(newLength);
  83. // Copy to the back of newArray.
  84. this.array.copy(newArray, newArray.length - this.array.length);
  85. this.array = newArray;
  86. };
  87. /**
  88. * First call ensureLengthFromBack to make sure the bytearray has
  89. * offsetFromBack bytes, then copy value into the array starting
  90. * offsetFromBack bytes from the back of the array.
  91. * @param {Buffer} value The buffer to copy.
  92. * @param {number} offsetFromBack The offset from the back of the array to start
  93. * copying.
  94. */
  95. DynamicBuffer.prototype.copyFromBack = function(value, offsetFromBack)
  96. {
  97. this.ensureLengthFromBack(offsetFromBack);
  98. if (Buffer.isBuffer(value))
  99. value.copy(this.array, this.array.length - offsetFromBack);
  100. else
  101. // Need to make value a Buffer to copy.
  102. new Buffer(value).copy(this.array, this.array.length - offsetFromBack);
  103. };
  104. /**
  105. * Return this.array.slice(begin, end);
  106. * @param {number} begin The begin index for the slice.
  107. * @param {number} end (optional) The end index for the slice.
  108. * @returns {Buffer} The buffer slice.
  109. */
  110. DynamicBuffer.prototype.slice = function(begin, end)
  111. {
  112. if (end == undefined)
  113. return this.array.slice(begin);
  114. else
  115. return this.array.slice(begin, end);
  116. };