radio/libjs/wContainer/abstractmap.js
2018-08-05 00:48:17 +03:00

143 lines
3.8 KiB
JavaScript

"use strict";
var Class = require("../utils/class");
var RBTree = require("bintrees").RBTree;
var AbstractPair = require("./abstractpair");
var AbstractMap = Class.inherit({
"className": "AbstractMap",
"constructor": function(owning) {
Class.fn.constructor.call(this);
this._owning = owning !== false;
this._data = new RBTree(function (a, b) {
if (a[">"](b)) {
return 1;
}
if (a["<"](b)) {
return -1
}
if (a["=="](b)) {
return 0;
}
});
},
"destructor": function() {
this.clear();
Class.fn.destructor.call(this);
},
"begin": function() {
var itr = this._data.iterator();
if (itr.next() !== null) {
return new Iterator(itr);
}
return this.end();
},
"clear": function() {
if (this._owning) {
this._data.each(function(data) {
data.destructor();
});
}
this._data.clear();
},
"each": function(funct) {
this._data.each(funct);
},
"end": function() {
return new Iterator(this._data.iterator());
},
"erase": function(itr) {
var pair = itr["*"]();
if (!this._data.remove(pair)) {
throw new Error("An attempt to remove non-existing map element");
}
if (this._owning) {
pair.destructor();
}
},
"find": function(key) {
var pair = new this.constructor.dataType(key);
var iter = this._data.findIter(pair);
if (iter === null) {
return this.end();
}
return new Iterator(iter);
},
"insert": function(key, value) {
var pair = new this.constructor.dataType(key, value);
if (!this._data.insert(pair)) {
throw new Error("An attempt to insert already existing element into a map");
}
},
"r_each": function(funct) {
this._data.reach(funct);
},
"size": function() {
return this._data.size;
},
"lowerBound": function(key) {
var pair = new this.constructor.dataType(key);
return new Iterator(this._data.lowerBound(pair));
},
"upperBound": function(key) {
var pair = new this.constructor.dataType(key);
return new Iterator(this._data.upperBound(pair));
}
});
var Iterator = Class.inherit({
"className": "MapIterator",
"constructor": function(rbtree_iterator) {
Class.fn.constructor.call(this);
this._itr = rbtree_iterator;
},
"++": function() {
if ((this._itr._cursor === null)) {
throw new Error("An attempt to increment an iterator pointing to the end of the map");
}
this._itr.next();
},
"--": function() {
this._itr.prev();
if ((this._itr._cursor === null)) {
throw new Error("An attempt to decrement an iterator pointing to the beginning of the map");
}
},
"==": function(other) {
return this._itr.data() === other._itr.data();
},
"*": function() {
if ((this._itr._cursor === null)) {
throw new Error("An attempt to dereference an iterator pointing to the end of the map");
}
return this._itr.data();
}
});
AbstractMap.dataType = undefined;
AbstractMap.iterator = Iterator;
AbstractMap.template = function(first, second) {
var dt = AbstractPair.template(first, second);
var Map = AbstractMap.inherit({
"className": "Map",
"constructor": function(owning) {
AbstractMap.fn.constructor.call(this, owning);
}
});
Map.dataType = dt;
return Map;
};
module.exports = AbstractMap;