Add initial ol.structs.Buffer
This commit is contained in:
137
src/ol/structs/buffer.js
Normal file
137
src/ol/structs/buffer.js
Normal file
@@ -0,0 +1,137 @@
|
||||
goog.provide('ol.structs.Buffer');
|
||||
|
||||
goog.require('ol.structs.IntegerSet');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Array.<number>=} opt_arr Array.
|
||||
* @param {number=} opt_used Used.
|
||||
* @param {boolean=} opt_dirty Dirty.
|
||||
*/
|
||||
ol.structs.Buffer = function(opt_arr, opt_used, opt_dirty) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.arr_ = goog.isDef(opt_arr) ? opt_arr : [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.structs.IntegerSet}
|
||||
*/
|
||||
this.dirtySet_ = new ol.structs.IntegerSet();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.structs.IntegerSet}
|
||||
*/
|
||||
this.freeSet_ = new ol.structs.IntegerSet();
|
||||
|
||||
var used = goog.isDef(opt_used) ? opt_used : this.arr_.length;
|
||||
if (used < this.arr_.length) {
|
||||
this.freeSet_.addRange(used, this.arr_.length);
|
||||
}
|
||||
if (opt_dirty && used !== 0) {
|
||||
this.dirtySet_.addRange(0, used);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} values Values.
|
||||
* @return {number} Index.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.add = function(values) {
|
||||
var size = values.length;
|
||||
goog.asserts.assert(size > 0);
|
||||
var index = this.freeSet_.findRange(size);
|
||||
goog.asserts.assert(index != -1); // FIXME
|
||||
this.freeSet_.removeRange(index, index + size);
|
||||
var i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
this.arr_[index + i] = values[i];
|
||||
}
|
||||
this.dirtySet_.addRange(index, index + size);
|
||||
return index;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(this: T, number, number)} f Callback.
|
||||
* @param {T=} opt_obj The object to be used as the value of 'this' within f.
|
||||
* @template T
|
||||
*/
|
||||
ol.structs.Buffer.prototype.forEachRange = function(f, opt_obj) {
|
||||
if (this.arr_.length !== 0) {
|
||||
this.freeSet_.forEachRangeInverted(0, this.arr_.length, f, opt_obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<number>} Array.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.getArray = function() {
|
||||
return this.arr_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Count.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.getCount = function() {
|
||||
return this.arr_.length - this.freeSet_.getSize();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.structs.IntegerSet} Dirty set.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.getDirtySet = function() {
|
||||
return this.dirtySet_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.structs.IntegerSet} Free set.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.getFreeSet = function() {
|
||||
return this.freeSet_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @param {number} size Size.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.remove = function(index, size) {
|
||||
this.freeSet_.addRange(index, index + size);
|
||||
this.dirtySet_.removeRange(index, index + size);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} index Index.
|
||||
* @param {Array.<number>} values Values.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.set = function(index, values) {
|
||||
var arr = this.arr_;
|
||||
var n = values.length;
|
||||
goog.asserts.assert(0 <= index && index + n <= arr.length);
|
||||
for (i = 0; i < n; ++i) {
|
||||
arr[index + i] = values[i];
|
||||
}
|
||||
this.dirtySet_.addRange(index, index + n);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Marks the buffer as being clean.
|
||||
*/
|
||||
ol.structs.Buffer.prototype.setClean = function() {
|
||||
this.dirtySet_.clear();
|
||||
};
|
||||
279
test/spec/ol/structs/buffer.test.js
Normal file
279
test/spec/ol/structs/buffer.test.js
Normal file
@@ -0,0 +1,279 @@
|
||||
goog.provide('ol.test.structs.Buffer');
|
||||
|
||||
|
||||
describe('ol.structs.Buffer', function() {
|
||||
|
||||
describe('constructor', function() {
|
||||
|
||||
describe('without an argument', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
b = new ol.structs.Buffer();
|
||||
});
|
||||
|
||||
it('constructs an empty instance', function() {
|
||||
expect(b.getArray()).to.be.empty();
|
||||
expect(b.getCount()).to.be(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with a single array argument', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
b = new ol.structs.Buffer([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
it('constructs a populated instance', function() {
|
||||
expect(b.getArray()).to.equalArray([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with an empty instance', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
b = new ol.structs.Buffer();
|
||||
});
|
||||
|
||||
describe('forEachRange', function() {
|
||||
|
||||
it('does not call the callback', function() {
|
||||
var callback = sinon.spy();
|
||||
b.forEachRange(callback);
|
||||
expect(callback).not.to.be.called();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getArray', function() {
|
||||
|
||||
it('returns an empty array', function() {
|
||||
expect(b.getArray()).to.be.empty();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns 0', function() {
|
||||
expect(b.getCount()).to.be(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getDirtySet', function() {
|
||||
|
||||
it('returns an empty set', function() {
|
||||
expect(b.getDirtySet().isEmpty()).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with an empty instance with spare capacity', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
b = new ol.structs.Buffer(new Array(4), 0);
|
||||
});
|
||||
|
||||
describe('add', function() {
|
||||
|
||||
it('allows elements to be added', function() {
|
||||
expect(b.add([0, 1, 2, 3])).to.be(0);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('forEachRange', function() {
|
||||
|
||||
it('does not call the callback', function() {
|
||||
var callback = sinon.spy();
|
||||
b.forEachRange(callback);
|
||||
expect(callback).not.to.be.called();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns 0', function() {
|
||||
expect(b.getCount()).to.be(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with an instance with no spare capacity', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
b = new ol.structs.Buffer([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
describe('add', function() {
|
||||
|
||||
it('throws an exception', function() {
|
||||
expect(function() {
|
||||
b.add([4, 5]);
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('forEachRange', function() {
|
||||
|
||||
it('calls the callback', function() {
|
||||
var callback = sinon.spy();
|
||||
b.forEachRange(callback);
|
||||
expect(callback.calledOnce).to.be(true);
|
||||
expect(callback.args[0]).to.equalArray([0, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
expect(b.getCount()).to.be(4);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getDirtySet', function() {
|
||||
|
||||
it('returns an empty set', function() {
|
||||
expect(b.getDirtySet().isEmpty()).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('remove', function() {
|
||||
|
||||
it('allows items to be removes', function() {
|
||||
expect(function() {
|
||||
b.remove(2, 4);
|
||||
}).to.not.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('set', function() {
|
||||
|
||||
it('updates the items', function() {
|
||||
b.set(2, [5, 6]);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 5, 6]);
|
||||
});
|
||||
|
||||
it('marks the set items as dirty', function() {
|
||||
b.set(2, [5, 6]);
|
||||
var dirtySet = b.getDirtySet();
|
||||
expect(dirtySet.isEmpty()).to.be(false);
|
||||
expect(dirtySet.getArray()).to.equalArray([2, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with an instance with spare capacity', function() {
|
||||
|
||||
var b;
|
||||
beforeEach(function() {
|
||||
var arr = [0, 1, 2, 3];
|
||||
arr.length = 8;
|
||||
b = new ol.structs.Buffer(arr, 4);
|
||||
});
|
||||
|
||||
describe('add', function() {
|
||||
|
||||
it('allows more items to be added', function() {
|
||||
expect(b.add([4, 5, 6, 7])).to.be(4);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('forEachRange', function() {
|
||||
|
||||
it('calls the callback with the expected values', function() {
|
||||
var callback = sinon.spy();
|
||||
b.forEachRange(callback);
|
||||
expect(callback.calledOnce).to.be(true);
|
||||
expect(callback.args[0]).to.equalArray([0, 4]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getCount', function() {
|
||||
|
||||
it('returns the expected value', function() {
|
||||
expect(b.getCount()).to.be(4);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getDirtySet', function() {
|
||||
|
||||
it('returns an empty set', function() {
|
||||
expect(b.getDirtySet().isEmpty()).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getFreeSet', function() {
|
||||
|
||||
it('returns the expected set', function() {
|
||||
var freeSet = b.getFreeSet();
|
||||
expect(freeSet.isEmpty()).to.be(false);
|
||||
expect(freeSet.getArray()).to.equalArray([4, 8]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('usage tests', function() {
|
||||
|
||||
it('allows multiple adds and removes', function() {
|
||||
var b = new ol.structs.Buffer(new Array(8), 0);
|
||||
expect(b.add([0, 1])).to.be(0);
|
||||
expect(b.getArray()).to.equalArray([
|
||||
0, 1,
|
||||
undefined, undefined,
|
||||
undefined, undefined,
|
||||
undefined, undefined
|
||||
]);
|
||||
expect(b.getCount()).to.be(2);
|
||||
expect(b.add([2, 3, 4, 5])).to.be(2);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([6, 7])).to.be(6);
|
||||
expect(b.getCount()).to.be(8);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
b.remove(2, 2);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([8, 9])).to.be(2);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 8, 9, 4, 5, 6, 7]);
|
||||
b.remove(1, 1);
|
||||
b.remove(4, 4);
|
||||
expect(b.add([10, 11, 12])).to.be(4);
|
||||
expect(b.getArray()).to.equalArray([0, 1, 8, 9, 10, 11, 12, 7]);
|
||||
expect(b.add([13])).to.be(1);
|
||||
expect(b.getArray()).to.equalArray([0, 13, 8, 9, 10, 11, 12, 7]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
goog.require('ol.structs.Buffer');
|
||||
Reference in New Issue
Block a user