astl
Version:
AssemblyScript-STL (Standard Template Library, migrated from the C++)
415 lines (357 loc) • 11 kB
text/typescript
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();
}
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
--------------------------------------------------------- */
public size(): usize
{
return this.buckets_.size();
}
public empty(): boolean
{
return this.size() === 0;
}
public begin(): LightSet.Iterator<Key>
{
return LightSet._Nth(this, 0);
}
public end(): LightSet.Iterator<Key>
{
return new LightSet.Iterator(this, this.data_.size());
}
public rbegin(): LightSet.ReverseIterator<Key>
{
return this.end().reverse();
}
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();
}
public static _At<Key>(source: LightSet<Key>, index: usize): Key
{
return source.data_.at(index).key;
}
/* ---------------------------------------------------------
BUCKETS
--------------------------------------------------------- */
public hash_function(): Hasher<Key>
{
return this.buckets_.hash_function();
}
public key_eq(): BinaryPredicator<Key>
{
return this.buckets_.key_eq();
}
public bucket(key: Key): usize
{
return this.hash_function()(key) % this.bucket_count();
}
public bucket_count(): usize
{
return this.buckets_.row_size();
}
public bucket_size(index: usize): usize
{
return this.buckets_.at(index).size();
}
public load_factor(): usize
{
return this.buckets_.load_factor();
}
public max_load_factor(): f64
{
return this.buckets_.max_load_factor();
}
public set_max_load_factor(z: f64): void
{
this.buckets_.set_max_load_factor(z);
}
public reserve(n: usize): void
{
this.buckets_.reserve(n);
this.data_.reserve(n);
}
public rehash(n: usize): void
{
this.buckets_.rehash(n);
}
/* ---------------------------------------------------------
ELEMENTS
--------------------------------------------------------- */
public has(key: Key): boolean
{
return this.buckets_.find(key) !== null;
}
public count(key: Key): usize
{
return this.has(key) ? 1 : 0;
}
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;
}
public reverse(): ReverseIterator<Key>
{
return new ReverseIterator(this);
}
public prev(): Iterator<Key>
{
return LightSet._Prev(this.source_, this.index_);
}
public next(): Iterator<Key>
{
return LightSet._Nth(this.source_, this.index_ + 1);
}
/* ---------------------------------------------------------
ACCESSORS
--------------------------------------------------------- */
public source(): LightSet<Key>
{
return this.source_;
}
public index(): usize
{
return this.index_;
}
public get value(): Key
{
return LightSet._At(this.source_, this.index_);
}
/* ---------------------------------------------------------
OPERATORS
--------------------------------------------------------- */
public equals(obj: Iterator<Key>): boolean
{
return this.source_ === obj.source_ && this.index_ === obj.index_;
}
public less(obj: Iterator<Key>): boolean
{
return this.index_ < obj.index_;
}
protected __not_equals(obj: Iterator<Key>): boolean
{
return !this.equals(obj);
}
protected __less_equals(obj: Iterator<Key>): boolean
{
return this.source_ === obj.source_ && this.index_ <= obj.index_;
}
protected __greater(obj: Iterator<Key>): boolean
{
return this.index_ > obj.index_;
}
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
--------------------------------------------------------- */
public index(): usize
{
return this.base().index();
}
public get value(): Key
{
return this.base_.value;
}
/* ---------------------------------------------------------
OPERATORS
--------------------------------------------------------- */
public less(obj: ReverseIterator<Key>): boolean
{
return this.index() > obj.index();
}
protected __less_equals(obj: ReverseIterator<Key>): boolean
{
return this.source() === obj.source() && this.index() >= obj.index();
}
protected __greater(obj: ReverseIterator<Key>): boolean
{
return this.index() < obj.index();
}
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;
}
public delete(): void
{
this.key_ = changetype<Key>(0);
this.erased_ = true;
}
public get key(): Key { return this.key_ ; }
public get erased(): boolean { return this.erased_; }
}