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