UNPKG

astl

Version:

AssemblyScript-STL (Standard Template Library, migrated from the C++)

415 lines (357 loc) 11 kB
import { HashBuckets } from "../../internal/hash/HashBuckets"; import { Vector } from "../../container/Vector"; import { ReverseIteratorBase } from "../../internal/iterator/ReverseIteratorBase"; import { BinaryPredicator } from "../../internal/functional/BinaryPredicator"; import { Hasher } from "../../internal/functional/Hasher"; import { equal_to } from "../../functional/comparators"; import { hash } from "../../functional/hash"; import { ErrorGenerator } from "../../internal/exception/ErrorGenerator"; import { CMath } from "../../internal/numeric/CMath"; import { Entry } from "../../utility/Entry"; import { IPair } from "../../utility/IPair"; export class LightSet<Key> { private buckets_: HashBuckets<Key, Element<Key>>; private data_: Vector<Element<Key>>; /* --------------------------------------------------------- CONSTRUCTORS --------------------------------------------------------- */ public constructor ( hasher: Hasher<Key> = key => hash(key), predicator: BinaryPredicator<Key> = (x, y) => equal_to(x, y) ) { this.buckets_ = new HashBuckets(hasher, predicator, elem => elem.key); this.data_ = new Vector(); } @inline public clear(): void { this.buckets_.clear(); this.data_.clear(); } public swap(obj: LightSet<Key>): void { const buckets: HashBuckets<Key, Element<Key>> = this.buckets_; this.buckets_ = obj.buckets_; obj.buckets_ = buckets; const data: Vector<Element<Key>> = this.data_; this.data_ = obj.data_; obj.data_ = data; } /* ========================================================= ACCESSORS - CAPACITIES - BUCKETS - ELEMENTS ============================================================ CAPACITIES --------------------------------------------------------- */ @inline public size(): usize { return this.buckets_.size(); } @inline public empty(): boolean { return this.size() === 0; } @inline public begin(): LightSet.Iterator<Key> { return LightSet._Nth(this, 0); } @inline public end(): LightSet.Iterator<Key> { return new LightSet.Iterator(this, this.data_.size()); } @inline public rbegin(): LightSet.ReverseIterator<Key> { return this.end().reverse(); } @inline public rend(): LightSet.ReverseIterator<Key> { return this.begin().reverse(); } public static _Nth<Key>(source: LightSet<Key>, index: usize): LightSet.Iterator<Key> { for (; index < source.data_.size(); ++index) if (source.data_.at(index).erased === false) return new LightSet.Iterator(source, index); return source.end(); } public static _Prev<Key>(source: LightSet<Key>, index: usize): LightSet.Iterator<Key> { index = CMath.min(index, source.size()); while (index !== 0) { const elem: Element<Key> = source.data_.at(--index); if (elem.erased === false) return new LightSet.Iterator(source, index); } return source.end(); } @inline public static _At<Key>(source: LightSet<Key>, index: usize): Key { return source.data_.at(index).key; } /* --------------------------------------------------------- BUCKETS --------------------------------------------------------- */ @inline public hash_function(): Hasher<Key> { return this.buckets_.hash_function(); } @inline public key_eq(): BinaryPredicator<Key> { return this.buckets_.key_eq(); } @inline public bucket(key: Key): usize { return this.hash_function()(key) % this.bucket_count(); } @inline public bucket_count(): usize { return this.buckets_.row_size(); } @inline public bucket_size(index: usize): usize { return this.buckets_.at(index).size(); } @inline public load_factor(): usize { return this.buckets_.load_factor(); } @inline public max_load_factor(): f64 { return this.buckets_.max_load_factor(); } @inline public set_max_load_factor(z: f64): void { this.buckets_.set_max_load_factor(z); } @inline public reserve(n: usize): void { this.buckets_.reserve(n); this.data_.reserve(n); } @inline public rehash(n: usize): void { this.buckets_.rehash(n); } /* --------------------------------------------------------- ELEMENTS --------------------------------------------------------- */ @inline public has(key: Key): boolean { return this.buckets_.find(key) !== null; } @inline public count(key: Key): usize { return this.has(key) ? 1 : 0; } @inline @operator("[]=") public insert(key: Key): void { let elem: Element<Key> | null = this.buckets_.find(key); if (elem !== null) return; elem = new Element(key); this.buckets_.insert(elem); this.data_.push_back(elem); } public erase(first: LightSet.Iterator<Key>, last: LightSet.Iterator<Key> = first.next()): LightSet.Iterator<Key> { for (let i: usize = first.index(); i < last.index(); ++i) { const elem: Element<Key> = this.data_.at(i); if (elem.erased === true) continue; this.buckets_.erase(elem); elem.delete(); } return LightSet._Nth(this, last.index()); } public erase_by_key(key: Key): usize { const elem: Element<Key> | null = this.buckets_.find(key); if (elem === null) return 0; this.buckets_.erase(elem); elem.delete(); return 1; } } export namespace LightSet { export class Iterator<Key> { private readonly source_: LightSet<Key>; private readonly index_: usize; /* --------------------------------------------------------- CONSTRUCTORS --------------------------------------------------------- */ public constructor(source: LightSet<Key>, index: usize) { this.source_ = source; this.index_ = index; } @inline public reverse(): ReverseIterator<Key> { return new ReverseIterator(this); } @inline public prev(): Iterator<Key> { return LightSet._Prev(this.source_, this.index_); } @inline public next(): Iterator<Key> { return LightSet._Nth(this.source_, this.index_ + 1); } /* --------------------------------------------------------- ACCESSORS --------------------------------------------------------- */ @inline public source(): LightSet<Key> { return this.source_; } @inline public index(): usize { return this.index_; } @inline public get value(): Key { return LightSet._At(this.source_, this.index_); } /* --------------------------------------------------------- OPERATORS --------------------------------------------------------- */ @inline @operator("==") public equals(obj: Iterator<Key>): boolean { return this.source_ === obj.source_ && this.index_ === obj.index_; } @inline @operator("<") public less(obj: Iterator<Key>): boolean { return this.index_ < obj.index_; } @inline @operator("!=") protected __not_equals(obj: Iterator<Key>): boolean { return !this.equals(obj); } @inline @operator("<=") protected __less_equals(obj: Iterator<Key>): boolean { return this.source_ === obj.source_ && this.index_ <= obj.index_; } @inline @operator(">") protected __greater(obj: Iterator<Key>): boolean { return this.index_ > obj.index_; } @inline @operator(">=") protected __greater_equals(obj: Iterator<Key>): boolean { return this.source_ === obj.source_ && this.index_ >= obj.index_; } } export class ReverseIterator<Key> extends ReverseIteratorBase<Key, LightSet<Key>, Iterator<Key>, ReverseIterator<Key>, Key> { /* --------------------------------------------------------- ACCESSORS --------------------------------------------------------- */ @inline public index(): usize { return this.base().index(); } @inline public get value(): Key { return this.base_.value; } /* --------------------------------------------------------- OPERATORS --------------------------------------------------------- */ @inline @operator("<") public less(obj: ReverseIterator<Key>): boolean { return this.index() > obj.index(); } @inline @operator("<=") protected __less_equals(obj: ReverseIterator<Key>): boolean { return this.source() === obj.source() && this.index() >= obj.index(); } @inline @operator(">") protected __greater(obj: ReverseIterator<Key>): boolean { return this.index() < obj.index(); } @inline @operator(">=") protected __greater_equals(obj: ReverseIterator<Key>): boolean { return this.source() === obj.source() && this.index() <= obj.index(); } } } class Element<Key> { private key_: Key; private erased_: boolean; public constructor(key: Key) { this.key_ = key; this.erased_ = false; } @inline public delete(): void { this.key_ = changetype<Key>(0); this.erased_ = true; } @inline public get key(): Key { return this.key_ ; } @inline public get erased(): boolean { return this.erased_; } }