index.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. module.exports = Buffers;
  2. function Buffers (bufs) {
  3. if (!(this instanceof Buffers)) return new Buffers(bufs);
  4. this.buffers = bufs || [];
  5. this.length = this.buffers.reduce(function (size, buf) {
  6. return size + buf.length
  7. }, 0);
  8. }
  9. Buffers.prototype.push = function () {
  10. for (var i = 0; i < arguments.length; i++) {
  11. if (!Buffer.isBuffer(arguments[i])) {
  12. throw new TypeError('Tried to push a non-buffer');
  13. }
  14. }
  15. for (var i = 0; i < arguments.length; i++) {
  16. var buf = arguments[i];
  17. this.buffers.push(buf);
  18. this.length += buf.length;
  19. }
  20. return this.length;
  21. };
  22. Buffers.prototype.unshift = function () {
  23. for (var i = 0; i < arguments.length; i++) {
  24. if (!Buffer.isBuffer(arguments[i])) {
  25. throw new TypeError('Tried to unshift a non-buffer');
  26. }
  27. }
  28. for (var i = 0; i < arguments.length; i++) {
  29. var buf = arguments[i];
  30. this.buffers.unshift(buf);
  31. this.length += buf.length;
  32. }
  33. return this.length;
  34. };
  35. Buffers.prototype.copy = function (dst, dStart, start, end) {
  36. return this.slice(start, end).copy(dst, dStart, 0, end - start);
  37. };
  38. Buffers.prototype.splice = function (i, howMany) {
  39. var buffers = this.buffers;
  40. var index = i >= 0 ? i : this.length - i;
  41. var reps = [].slice.call(arguments, 2);
  42. if (howMany === undefined) {
  43. howMany = this.length - index;
  44. }
  45. else if (howMany > this.length - index) {
  46. howMany = this.length - index;
  47. }
  48. for (var i = 0; i < reps.length; i++) {
  49. this.length += reps[i].length;
  50. }
  51. var removed = new Buffers();
  52. var bytes = 0;
  53. var startBytes = 0;
  54. for (
  55. var ii = 0;
  56. ii < buffers.length && startBytes + buffers[ii].length < index;
  57. ii ++
  58. ) { startBytes += buffers[ii].length }
  59. if (index - startBytes > 0) {
  60. var start = index - startBytes;
  61. if (start + howMany < buffers[ii].length) {
  62. removed.push(buffers[ii].slice(start, start + howMany));
  63. var orig = buffers[ii];
  64. //var buf = new Buffer(orig.length - howMany);
  65. var buf0 = new Buffer(start);
  66. for (var i = 0; i < start; i++) {
  67. buf0[i] = orig[i];
  68. }
  69. var buf1 = new Buffer(orig.length - start - howMany);
  70. for (var i = start + howMany; i < orig.length; i++) {
  71. buf1[ i - howMany - start ] = orig[i]
  72. }
  73. if (reps.length > 0) {
  74. var reps_ = reps.slice();
  75. reps_.unshift(buf0);
  76. reps_.push(buf1);
  77. buffers.splice.apply(buffers, [ ii, 1 ].concat(reps_));
  78. ii += reps_.length;
  79. reps = [];
  80. }
  81. else {
  82. buffers.splice(ii, 1, buf0, buf1);
  83. //buffers[ii] = buf;
  84. ii += 2;
  85. }
  86. }
  87. else {
  88. removed.push(buffers[ii].slice(start));
  89. buffers[ii] = buffers[ii].slice(0, start);
  90. ii ++;
  91. }
  92. }
  93. if (reps.length > 0) {
  94. buffers.splice.apply(buffers, [ ii, 0 ].concat(reps));
  95. ii += reps.length;
  96. }
  97. while (removed.length < howMany) {
  98. var buf = buffers[ii];
  99. var len = buf.length;
  100. var take = Math.min(len, howMany - removed.length);
  101. if (take === len) {
  102. removed.push(buf);
  103. buffers.splice(ii, 1);
  104. }
  105. else {
  106. removed.push(buf.slice(0, take));
  107. buffers[ii] = buffers[ii].slice(take);
  108. }
  109. }
  110. this.length -= removed.length;
  111. return removed;
  112. };
  113. Buffers.prototype.slice = function (i, j) {
  114. var buffers = this.buffers;
  115. if (j === undefined) j = this.length;
  116. if (i === undefined) i = 0;
  117. if (j > this.length) j = this.length;
  118. var startBytes = 0;
  119. for (
  120. var si = 0;
  121. si < buffers.length && startBytes + buffers[si].length <= i;
  122. si ++
  123. ) { startBytes += buffers[si].length }
  124. var target = new Buffer(j - i);
  125. var ti = 0;
  126. for (var ii = si; ti < j - i && ii < buffers.length; ii++) {
  127. var len = buffers[ii].length;
  128. var start = ti === 0 ? i - startBytes : 0;
  129. var end = ti + len >= j - i
  130. ? Math.min(start + (j - i) - ti, len)
  131. : len
  132. ;
  133. buffers[ii].copy(target, ti, start, end);
  134. ti += end - start;
  135. }
  136. return target;
  137. };
  138. Buffers.prototype.pos = function (i) {
  139. if (i < 0 || i >= this.length) throw new Error('oob');
  140. var l = i, bi = 0, bu = null;
  141. for (;;) {
  142. bu = this.buffers[bi];
  143. if (l < bu.length) {
  144. return {buf: bi, offset: l};
  145. } else {
  146. l -= bu.length;
  147. }
  148. bi++;
  149. }
  150. };
  151. Buffers.prototype.get = function get (i) {
  152. var pos = this.pos(i);
  153. return this.buffers[pos.buf].get(pos.offset);
  154. };
  155. Buffers.prototype.set = function set (i, b) {
  156. var pos = this.pos(i);
  157. return this.buffers[pos.buf].set(pos.offset, b);
  158. };
  159. Buffers.prototype.indexOf = function (needle, offset) {
  160. if ("string" === typeof needle) {
  161. needle = new Buffer(needle);
  162. } else if (needle instanceof Buffer) {
  163. // already a buffer
  164. } else {
  165. throw new Error('Invalid type for a search string');
  166. }
  167. if (!needle.length) {
  168. return 0;
  169. }
  170. if (!this.length) {
  171. return -1;
  172. }
  173. var i = 0, j = 0, match = 0, mstart, pos = 0;
  174. // start search from a particular point in the virtual buffer
  175. if (offset) {
  176. var p = this.pos(offset);
  177. i = p.buf;
  178. j = p.offset;
  179. pos = offset;
  180. }
  181. // for each character in virtual buffer
  182. for (;;) {
  183. while (j >= this.buffers[i].length) {
  184. j = 0;
  185. i++;
  186. if (i >= this.buffers.length) {
  187. // search string not found
  188. return -1;
  189. }
  190. }
  191. var char = this.buffers[i][j];
  192. if (char == needle[match]) {
  193. // keep track where match started
  194. if (match == 0) {
  195. mstart = {
  196. i: i,
  197. j: j,
  198. pos: pos
  199. };
  200. }
  201. match++;
  202. if (match == needle.length) {
  203. // full match
  204. return mstart.pos;
  205. }
  206. } else if (match != 0) {
  207. // a partial match ended, go back to match starting position
  208. // this will continue the search at the next character
  209. i = mstart.i;
  210. j = mstart.j;
  211. pos = mstart.pos;
  212. match = 0;
  213. }
  214. j++;
  215. pos++;
  216. }
  217. };
  218. Buffers.prototype.toBuffer = function() {
  219. return this.slice();
  220. }
  221. Buffers.prototype.toString = function(encoding, start, end) {
  222. return this.slice(start, end).toString(encoding);
  223. }