You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					270 lines
				
				6.9 KiB
			
		
		
			
		
	
	
					270 lines
				
				6.9 KiB
			| 
											2 years ago
										 | module.exports = Buffers; | ||
|  | 
 | ||
|  | function Buffers (bufs) { | ||
|  |     if (!(this instanceof Buffers)) return new Buffers(bufs); | ||
|  |     this.buffers = bufs || []; | ||
|  |     this.length = this.buffers.reduce(function (size, buf) { | ||
|  |         return size + buf.length | ||
|  |     }, 0); | ||
|  | } | ||
|  | 
 | ||
|  | Buffers.prototype.push = function () { | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |         if (!Buffer.isBuffer(arguments[i])) { | ||
|  |             throw new TypeError('Tried to push a non-buffer'); | ||
|  |         } | ||
|  |     } | ||
|  |      | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |         var buf = arguments[i]; | ||
|  |         this.buffers.push(buf); | ||
|  |         this.length += buf.length; | ||
|  |     } | ||
|  |     return this.length; | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.unshift = function () { | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |         if (!Buffer.isBuffer(arguments[i])) { | ||
|  |             throw new TypeError('Tried to unshift a non-buffer'); | ||
|  |         } | ||
|  |     } | ||
|  |      | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |         var buf = arguments[i]; | ||
|  |         this.buffers.unshift(buf); | ||
|  |         this.length += buf.length; | ||
|  |     } | ||
|  |     return this.length; | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.copy = function (dst, dStart, start, end) { | ||
|  |     return this.slice(start, end).copy(dst, dStart, 0, end - start); | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.splice = function (i, howMany) { | ||
|  |     var buffers = this.buffers; | ||
|  |     var index = i >= 0 ? i : this.length - i; | ||
|  |     var reps = [].slice.call(arguments, 2); | ||
|  |      | ||
|  |     if (howMany === undefined) { | ||
|  |         howMany = this.length - index; | ||
|  |     } | ||
|  |     else if (howMany > this.length - index) { | ||
|  |         howMany = this.length - index; | ||
|  |     } | ||
|  |      | ||
|  |     for (var i = 0; i < reps.length; i++) { | ||
|  |         this.length += reps[i].length; | ||
|  |     } | ||
|  |      | ||
|  |     var removed = new Buffers(); | ||
|  |     var bytes = 0; | ||
|  |      | ||
|  |     var startBytes = 0; | ||
|  |     for ( | ||
|  |         var ii = 0; | ||
|  |         ii < buffers.length && startBytes + buffers[ii].length < index; | ||
|  |         ii ++ | ||
|  |     ) { startBytes += buffers[ii].length } | ||
|  |      | ||
|  |     if (index - startBytes > 0) { | ||
|  |         var start = index - startBytes; | ||
|  |          | ||
|  |         if (start + howMany < buffers[ii].length) { | ||
|  |             removed.push(buffers[ii].slice(start, start + howMany)); | ||
|  |              | ||
|  |             var orig = buffers[ii]; | ||
|  |             //var buf = new Buffer(orig.length - howMany);
 | ||
|  |             var buf0 = new Buffer(start); | ||
|  |             for (var i = 0; i < start; i++) { | ||
|  |                 buf0[i] = orig[i]; | ||
|  |             } | ||
|  |              | ||
|  |             var buf1 = new Buffer(orig.length - start - howMany); | ||
|  |             for (var i = start + howMany; i < orig.length; i++) { | ||
|  |                 buf1[ i - howMany - start ] = orig[i] | ||
|  |             } | ||
|  |              | ||
|  |             if (reps.length > 0) { | ||
|  |                 var reps_ = reps.slice(); | ||
|  |                 reps_.unshift(buf0); | ||
|  |                 reps_.push(buf1); | ||
|  |                 buffers.splice.apply(buffers, [ ii, 1 ].concat(reps_)); | ||
|  |                 ii += reps_.length; | ||
|  |                 reps = []; | ||
|  |             } | ||
|  |             else { | ||
|  |                 buffers.splice(ii, 1, buf0, buf1); | ||
|  |                 //buffers[ii] = buf;
 | ||
|  |                 ii += 2; | ||
|  |             } | ||
|  |         } | ||
|  |         else { | ||
|  |             removed.push(buffers[ii].slice(start)); | ||
|  |             buffers[ii] = buffers[ii].slice(0, start); | ||
|  |             ii ++; | ||
|  |         } | ||
|  |     } | ||
|  |      | ||
|  |     if (reps.length > 0) { | ||
|  |         buffers.splice.apply(buffers, [ ii, 0 ].concat(reps)); | ||
|  |         ii += reps.length; | ||
|  |     } | ||
|  |      | ||
|  |     while (removed.length < howMany) { | ||
|  |         var buf = buffers[ii]; | ||
|  |         var len = buf.length; | ||
|  |         var take = Math.min(len, howMany - removed.length); | ||
|  |          | ||
|  |         if (take === len) { | ||
|  |             removed.push(buf); | ||
|  |             buffers.splice(ii, 1); | ||
|  |         } | ||
|  |         else { | ||
|  |             removed.push(buf.slice(0, take)); | ||
|  |             buffers[ii] = buffers[ii].slice(take); | ||
|  |         } | ||
|  |     } | ||
|  |      | ||
|  |     this.length -= removed.length; | ||
|  |      | ||
|  |     return removed; | ||
|  | }; | ||
|  |   | ||
|  | Buffers.prototype.slice = function (i, j) { | ||
|  |     var buffers = this.buffers; | ||
|  |     if (j === undefined) j = this.length; | ||
|  |     if (i === undefined) i = 0; | ||
|  |      | ||
|  |     if (j > this.length) j = this.length; | ||
|  |      | ||
|  |     var startBytes = 0; | ||
|  |     for ( | ||
|  |         var si = 0; | ||
|  |         si < buffers.length && startBytes + buffers[si].length <= i; | ||
|  |         si ++ | ||
|  |     ) { startBytes += buffers[si].length } | ||
|  |      | ||
|  |     var target = new Buffer(j - i); | ||
|  |      | ||
|  |     var ti = 0; | ||
|  |     for (var ii = si; ti < j - i && ii < buffers.length; ii++) { | ||
|  |         var len = buffers[ii].length; | ||
|  |          | ||
|  |         var start = ti === 0 ? i - startBytes : 0; | ||
|  |         var end = ti + len >= j - i | ||
|  |             ? Math.min(start + (j - i) - ti, len) | ||
|  |             : len | ||
|  |         ; | ||
|  |          | ||
|  |         buffers[ii].copy(target, ti, start, end); | ||
|  |         ti += end - start; | ||
|  |     } | ||
|  |      | ||
|  |     return target; | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.pos = function (i) { | ||
|  |     if (i < 0 || i >= this.length) throw new Error('oob'); | ||
|  |     var l = i, bi = 0, bu = null; | ||
|  |     for (;;) { | ||
|  |         bu = this.buffers[bi]; | ||
|  |         if (l < bu.length) { | ||
|  |             return {buf: bi, offset: l}; | ||
|  |         } else { | ||
|  |             l -= bu.length; | ||
|  |         } | ||
|  |         bi++; | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.get = function get (i) { | ||
|  |     var pos = this.pos(i); | ||
|  | 
 | ||
|  |     return this.buffers[pos.buf].get(pos.offset); | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.set = function set (i, b) { | ||
|  |     var pos = this.pos(i); | ||
|  | 
 | ||
|  |     return this.buffers[pos.buf].set(pos.offset, b); | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.indexOf = function (needle, offset) { | ||
|  |     if ("string" === typeof needle) { | ||
|  |         needle = new Buffer(needle); | ||
|  |     } else if (needle instanceof Buffer) { | ||
|  |         // already a buffer
 | ||
|  |     } else { | ||
|  |         throw new Error('Invalid type for a search string'); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!needle.length) { | ||
|  |         return 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!this.length) { | ||
|  |         return -1; | ||
|  |     } | ||
|  | 
 | ||
|  |     var i = 0, j = 0, match = 0, mstart, pos = 0; | ||
|  | 
 | ||
|  |     // start search from a particular point in the virtual buffer
 | ||
|  |     if (offset) { | ||
|  |         var p = this.pos(offset); | ||
|  |         i = p.buf; | ||
|  |         j = p.offset; | ||
|  |         pos = offset; | ||
|  |     } | ||
|  | 
 | ||
|  |     // for each character in virtual buffer
 | ||
|  |     for (;;) { | ||
|  |         while (j >= this.buffers[i].length) { | ||
|  |             j = 0; | ||
|  |             i++; | ||
|  | 
 | ||
|  |             if (i >= this.buffers.length) { | ||
|  |                 // search string not found
 | ||
|  |                 return -1; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         var char = this.buffers[i][j]; | ||
|  | 
 | ||
|  |         if (char == needle[match]) { | ||
|  |             // keep track where match started
 | ||
|  |             if (match == 0) { | ||
|  |                 mstart = { | ||
|  |                     i: i, | ||
|  |                     j: j, | ||
|  |                     pos: pos | ||
|  |                 }; | ||
|  |             } | ||
|  |             match++; | ||
|  |             if (match == needle.length) { | ||
|  |                 // full match
 | ||
|  |                 return mstart.pos; | ||
|  |             } | ||
|  |         } else if (match != 0) { | ||
|  |             // a partial match ended, go back to match starting position
 | ||
|  |             // this will continue the search at the next character
 | ||
|  |             i = mstart.i; | ||
|  |             j = mstart.j; | ||
|  |             pos = mstart.pos; | ||
|  |             match = 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         j++; | ||
|  |         pos++; | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Buffers.prototype.toBuffer = function() { | ||
|  |     return this.slice(); | ||
|  | } | ||
|  | 
 | ||
|  | Buffers.prototype.toString = function(encoding, start, end) { | ||
|  |     return this.slice(start, end).toString(encoding); | ||
|  | } |