//================================================================ /** * @packageDocumentation * @module std.base */ //================================================================ import { IAssociativeContainer } from "../../internal/container/associative/IAssociativeContainer"; import { IContainer } from "./IContainer"; import { Container } from "./Container"; import { IForwardIterator } from "../../iterator/IForwardIterator"; import { ILinearContainerBase } from "../../internal/container/linear/ILinearContainerBase"; import { NativeArrayIterator } from "../../internal/iterator/disposable/NativeArrayIterator"; import { Pair } from "../../utility/Pair"; import { Temporary } from "../../internal/functional/Temporary"; /** * Basic set container. * * @template Key Key type * @template Unique Whether duplicated key is blocked or not * @template Source Derived type extending this {@link SetContainer} * @template IteratorT Iterator type * @template ReverseT Reverse iterator type * * @author Jeongho Nam - https://github.com/samchon */ export abstract class SetContainer< Key, Unique extends boolean, SourceT extends SetContainer, IteratorT extends SetContainer.Iterator< Key, Unique, SourceT, IteratorT, ReverseT >, ReverseT extends SetContainer.ReverseIterator< Key, Unique, SourceT, IteratorT, ReverseT >, > extends Container implements IAssociativeContainer { protected data_: ILinearContainerBase; /* --------------------------------------------------------- CONSTURCTORS --------------------------------------------------------- */ /** * Default Constructor. */ protected constructor( factory: ( thisArg: SourceT, ) => ILinearContainerBase, ) { super(); this.data_ = factory(this); } /** * @inheritDoc */ public assign< InputIterator extends Readonly>, >(first: InputIterator, last: InputIterator): void { // INSERT this.clear(); this.insert(first, last); } /** * @inheritDoc */ public clear(): void { // TO BE ABSTRACT this.data_.clear(); } /* ========================================================= ACCESSORS - ITERATORS - ELEMENTS ============================================================ ITERATOR --------------------------------------------------------- */ /** * @inheritDoc */ public abstract find(key: Key): IteratorT; /** * @inheritDoc */ public begin(): IteratorT { return this.data_.begin(); } /** * @inheritDoc */ public end(): IteratorT { return this.data_.end(); } /* --------------------------------------------------------- ELEMENTS --------------------------------------------------------- */ /** * @inheritDoc */ public has(key: Key): boolean { return !this.find(key).equals(this.end()); } /** * @inheritDoc */ public abstract count(key: Key): number; /** * @inheritDoc */ public size(): number { return this.data_.size(); } /* ========================================================= ELEMENTS I/O - INSERT - ERASE - UTILITY - POST-PROCESS ============================================================ INSERT --------------------------------------------------------- */ /** * @inheritDoc */ public push(...items: Key[]): number { if (items.length === 0) return this.size(); // INSERT BY RANGE const first: NativeArrayIterator = new NativeArrayIterator( items, 0, ); const last: NativeArrayIterator = new NativeArrayIterator( items, items.length, ); this._Insert_by_range(first, last); // RETURN SIZE return this.size(); } public insert( key: Key, ): SetContainer.InsertRet; public insert(hint: IteratorT, key: Key): IteratorT; public insert< InputIterator extends Readonly>, >(first: InputIterator, last: InputIterator): void; public insert(...args: any[]): any { if (args.length === 1) return this._Insert_by_key(args[0]); else if ( args[0].next instanceof Function && args[1].next instanceof Function ) return this._Insert_by_range(args[0], args[1]); else return this._Insert_by_hint(args[0], args[1]); } protected abstract _Insert_by_key( key: Key, ): SetContainer.InsertRet; protected abstract _Insert_by_hint(hint: IteratorT, key: Key): IteratorT; protected abstract _Insert_by_range< InputIterator extends Readonly>, >(begin: InputIterator, end: InputIterator): void; /* --------------------------------------------------------- ERASE --------------------------------------------------------- */ /** * @inheritDoc */ public erase(key: Key): number; /** * @inheritDoc */ public erase(pos: IteratorT): IteratorT; /** * @inheritDoc */ public erase(first: IteratorT, last: IteratorT): IteratorT; public erase(...args: any[]): any { if ( args.length === 1 && !( args[0] instanceof this.end().constructor && (args[0] as IteratorT).source() === this ) ) return this._Erase_by_val(args[0]); else if (args.length === 1) return this._Erase_by_range(args[0]); else return this._Erase_by_range(args[0], args[1]); } protected abstract _Erase_by_val(key: Key): number; protected _Erase_by_range( first: IteratorT, last: IteratorT = first.next(), ): IteratorT { // ERASE const it = this.data_.erase(first, last); // POST-PROCESS this._Handle_erase(first, last); return it; } /* --------------------------------------------------------- UTILITY --------------------------------------------------------- */ /** * @inheritDoc */ public abstract swap(obj: SourceT): void; /** * @inheritDoc */ public abstract merge(source: SourceT): void; /* --------------------------------------------------------- POST-PROCESS --------------------------------------------------------- */ protected abstract _Handle_insert(first: IteratorT, last: IteratorT): void; protected abstract _Handle_erase(first: IteratorT, last: IteratorT): void; } /** * */ export namespace SetContainer { /** * Return type of {@link SetContainer.insert} */ export type InsertRet< Key, Unique extends boolean, Source extends SetContainer, IteratorT extends Iterator, ReverseT extends ReverseIterator< Key, Unique, Source, IteratorT, ReverseT >, > = Unique extends true ? Pair : IteratorT; /** * Iterator of {@link SetContainer} * * @author Jenogho Nam */ export type Iterator< Key, Unique extends boolean, SourceT extends SetContainer, IteratorT extends Iterator, ReverseT extends ReverseIterator< Key, Unique, SourceT, IteratorT, ReverseT >, > = Readonly>; /** * Reverse iterator of {@link SetContainer} * * @author Jenogho Nam */ export type ReverseIterator< Key, Unique extends boolean, SourceT extends SetContainer, IteratorT extends Iterator, ReverseT extends ReverseIterator< Key, Unique, SourceT, IteratorT, ReverseT >, > = Readonly< IContainer.ReverseIterator >; }