/*
* ISet.js - ilib Set class definition for platforms older than ES6
*
* Copyright © 2015, JEDLSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Create a new set with elements in the given array. The type of
* the set is gleaned from the type of the first element in the
* elements array, or the first element added to the set. The type
* may be "string" or "number", and all elements will be returned
* as elements of that type.
*
* @class
* @param {Array.<string|number>=} elements initial elements to add to the set
* @constructor
*/
var ISet = function(elements) {
this.elements = {};
if (elements && elements.length) {
for (var i = 0; i < elements.length; i++) {
this.elements[elements[i]] = true;
}
this.type = typeof(elements[0]);
}
};
/**
* @private
*/
ISet.prototype._addOne = function(element) {
if (this.isEmpty()) {
this.type = typeof(element);
}
if (!this.elements[element]) {
this.elements[element] = true;
return true;
}
return false;
};
/**
* Adds the specified element or array of elements to this set if it is or they are not
* already present.
*
* @param {*|Array.<*>} element element or array of elements to add
* @return {boolean} true if this set did not already contain the specified element[s]
*/
ISet.prototype.add = function(element) {
var ret = false;
if (typeof(element) === "object") {
for (var i = 0; i < element.length; i++) {
ret = this._addOne(element[i]) || ret;
}
} else {
ret = this._addOne(element);
}
return ret;
};
/**
* Removes all of the elements from this set.
*/
ISet.prototype.clear = function() {
this.elements = {};
};
/**
* Returns true if this set contains the specified element.
* @param {*} element the element to test
* @return {boolean}
*/
ISet.prototype.contains = function(element) {
return this.elements[element] || false;
};
ISet.prototype.has = ISet.prototype.contains; // for compatibility with ES6
/**
* Returns true if this set contains no elements.
* @return {boolean}
*/
ISet.prototype.isEmpty = function() {
return (Object.keys(this.elements).length === 0);
};
/**
* Removes the specified element from this set if it is present.
* @param {*} element the element to remove
* @return {boolean} true if the set contained the specified element
*/
ISet.prototype.remove = function(element) {
if (this.elements[element]) {
delete this.elements[element];
return true;
}
return false;
};
/**
* Return the set as a javascript array.
* @return {Array.<*>} the set represented as a javascript array
*/
ISet.prototype.asArray = function() {
var keys = Object.keys(this.elements);
// keys is an array of strings. Convert to numbers if necessary
if (this.type === "number") {
var tmp = [];
for (var i = 0; i < keys.length; i++) {
tmp.push(Number(keys[i]).valueOf());
}
keys = tmp;
}
return keys;
};
/**
* Represents the current set as json.
* @return {string} the current set represented as json
*/
ISet.prototype.toJson = function() {
return JSON.stringify(this.asArray());
};
/**
* Convert to a javascript representation of this object.
* In this case, it is a normal JS array.
* @return {*} the JS representation of this object
*/
ISet.prototype.toJS = function() {
return this.asArray();
};
/**
* Convert from a js representation to an internal one.
* @return {ISet|undefined} the current object, or undefined if the conversion did not work
*/
ISet.prototype.fromJS = function(obj) {
return this.add(obj) ? this : undefined;
};
module.exports = ISet;
Source