179 lines
3.9 KiB
TypeScript
179 lines
3.9 KiB
TypeScript
/**
|
|
* libjass
|
|
*
|
|
* https://github.com/Arnavion/libjass
|
|
*
|
|
* Copyright 2013 Arnav Singh
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/**
|
|
* Set implementation for browsers that don't support it. Only supports Number and String elements.
|
|
*
|
|
* Elements are stored as properties of an object, with names derived from their type.
|
|
*
|
|
* @param {!Array.<T>=} iterable Only an array of values is supported.
|
|
*/
|
|
class SimpleSet<T> implements Set<T> {
|
|
private _elements: { [key: string]: T };
|
|
private _size: number;
|
|
|
|
constructor(iterable?: T[]) {
|
|
this.clear();
|
|
|
|
if (iterable === undefined) {
|
|
return;
|
|
}
|
|
|
|
if (!Array.isArray(iterable)) {
|
|
throw new Error("Non-array iterables are not supported by the SimpleSet constructor.");
|
|
}
|
|
|
|
for (const value of iterable) {
|
|
this.add(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {T} value
|
|
* @return {libjass.Set.<T>} This set
|
|
*/
|
|
add(value: T): this {
|
|
const property = toProperty(value);
|
|
|
|
if (property === null) {
|
|
throw new Error("This Set implementation only supports Number and String values.");
|
|
}
|
|
|
|
if (!(property in this._elements)) {
|
|
this._size++;
|
|
}
|
|
|
|
this._elements[property] = value;
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
*/
|
|
clear(): void {
|
|
this._elements = Object.create(null);
|
|
this._size = 0;
|
|
}
|
|
|
|
/**
|
|
* @param {T} value
|
|
* @return {boolean}
|
|
*/
|
|
has(value: T): boolean {
|
|
const property = toProperty(value);
|
|
|
|
if (property === null) {
|
|
return false;
|
|
}
|
|
|
|
return property in this._elements;
|
|
}
|
|
|
|
/**
|
|
* @param {function(T, T, libjass.Set.<T>)} callbackfn A function that is called with each value in the set.
|
|
* @param {*} thisArg
|
|
*/
|
|
forEach(callbackfn: (value: T, index: T, set: this) => void, thisArg?: any): void {
|
|
for (const property of Object.keys(this._elements)) {
|
|
const element = this._elements[property];
|
|
callbackfn.call(thisArg, element, element, this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
get size(): number {
|
|
return this._size;
|
|
}
|
|
}
|
|
|
|
/* tslint:disable:variable-name */
|
|
|
|
/**
|
|
* Set to the global implementation of Set if the environment has one, else set to {@link ./utility/set.SimpleSet}
|
|
*
|
|
* Can be set to a value using {@link libjass.configure}
|
|
*
|
|
* Set it to null to force {@link ./utility/set.SimpleSet} to be used even if a global Set is present.
|
|
*
|
|
* @type {function(new:Set, !Array.<T>=)}
|
|
*/
|
|
export let Set: {
|
|
new <T>(iterable?: T[]): Set<T>;
|
|
/* tslint:disable-next-line:member-ordering */
|
|
prototype: Set<any>;
|
|
} = (() => {
|
|
const globalSet = global.Set;
|
|
|
|
if (globalSet === undefined) {
|
|
return SimpleSet;
|
|
}
|
|
|
|
if (typeof globalSet.prototype.forEach !== "function") {
|
|
return SimpleSet;
|
|
}
|
|
|
|
try {
|
|
if ((new globalSet([1, 2])).size !== 2) {
|
|
return SimpleSet;
|
|
}
|
|
}
|
|
catch (ex) {
|
|
return SimpleSet;
|
|
}
|
|
|
|
return globalSet as any;
|
|
})();
|
|
|
|
/* tslint:enable:variable-name */
|
|
|
|
/**
|
|
* Sets the Set implementation used by libjass to the provided one. If null, {@link ./utility/set.SimpleSet} is used.
|
|
*
|
|
* @param {?function(new:Set, !Array.<T>=)} value
|
|
*/
|
|
export function setImplementation(value: typeof Set | null): void {
|
|
if (value !== null) {
|
|
Set = value;
|
|
}
|
|
else {
|
|
Set = SimpleSet;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts the given value into a property name for the internal map.
|
|
*
|
|
* @param {*} value
|
|
* @return {?string}
|
|
*/
|
|
function toProperty(value: any): string | null {
|
|
if (typeof value === "number") {
|
|
return `#${ value }`;
|
|
}
|
|
|
|
if (typeof value === "string") {
|
|
return `'${ value }`;
|
|
}
|
|
|
|
return null;
|
|
}
|