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
						
					
					
				| 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);
 | |
| }
 |