UNPKG

typescript-logging

Version:

Library for logging, written in typescript, can be used by normal es5+ javascript as well.

322 lines (268 loc) 6.47 kB
class LinkedNode<T> { private _value: T; private _previous: LinkedNode<T> | null = null; private _next: LinkedNode<T> | null = null; constructor(value: T) { this._value = value; } get previous(): LinkedNode<T> | null { return this._previous; } set previous(value: LinkedNode<T> | null) { this._previous = value; } get next(): LinkedNode<T> | null { return this._next; } set next(value: LinkedNode<T> | null) { this._next = value; } get value(): T { return this._value; } } /** * Double linkedlist implementation. */ export class LinkedList<T> { private head: LinkedNode<T> | null = null; private size: number = 0; public addHead(value: T): void { if (!this.createHeadIfNeeded(value)) { if (this.head != null) { const nextNode = this.head.next; const newHeadNode = new LinkedNode<T>(value); if (nextNode != null) { nextNode.previous = newHeadNode; newHeadNode.next = nextNode; } this.head = newHeadNode; } else { throw new Error("This should never happen, list implementation broken"); } } this.size++; } public addTail(value: T): void { if (!this.createHeadIfNeeded(value)) { const oldTailNode = this.getTailNode(); if (oldTailNode != null) { const newTailNode = new LinkedNode<T>(value); oldTailNode.next = newTailNode; newTailNode.previous = oldTailNode; } else { throw new Error("List implementation broken"); } } this.size++; } public clear() { this.head = null; this.size = 0; } public getHead(): T | null { if (this.head != null) { return this.head.value; } return null; } public removeHead(): T | null { if (this.head != null) { const oldHead = this.head; const value = oldHead.value; this.head = oldHead.next; this.size--; return value; } return null; } public getTail(): T | null { const node = this.getTailNode(); if (node != null) { return node.value; } return null; } public removeTail(): T | null { const node = this.getTailNode(); if (node != null) { if (node === this.head) { this.head = null; } else { const previousNode = node.previous; if (previousNode != null) { previousNode.next = null; } else { throw new Error("List implementation is broken"); } } this.size--; return node.value; } return null; } public getSize(): number { return this.size; } public filter(f: (value: T) => boolean): T[] { const recurse = (fn: (value: T) => boolean, node: LinkedNode<T>, values: T[]) => { if (fn(node.value)) { values.push(node.value); } const nextNode = node.next; if (nextNode != null) { recurse(fn, nextNode, values); } }; const result: T[] = []; const currentNode = this.head; if (currentNode != null) { recurse(f, currentNode, result); } return result; } private createHeadIfNeeded(value: T): boolean { if (this.head == null) { this.head = new LinkedNode(value); return true; } return false; } private getTailNode(): LinkedNode<T> | null { if (this.head == null) { return null; } let node = this.head; while (node.next != null) { node = node.next; } return node; } } /** * Map implementation keyed by string (always). */ export class SimpleMap<V> { private array: {[key: string]: V} = {}; public put(key: string, value: V): void { this.array[key] = value; } public get(key: string): V | undefined { return this.array[key]; } public exists(key: string): boolean { const value = this.array[key]; return (typeof value !== "undefined"); } public remove(key: string): V | undefined { const value = this.array[key]; if (typeof value !== "undefined") { delete this.array[key]; } return value; } public keys(): string[] { const keys: string[] = []; for (const key in this.array) { // To prevent random stuff to appear if (this.array.hasOwnProperty(key)) { keys.push(key); } } return keys; } public values(): V[] { const values: V[] = []; for (const key in this.array) { // To prevent random stuff to appear if (this.array.hasOwnProperty(key)) { values.push(this.get(key) as V); } } return values; } public size(): number { return this.keys().length; } public isEmpty(): boolean { return this.size() === 0; } public clear(): void { this.array = {}; } public forEach(cbFunction: (key: string, value: V, index: number) => void): void { let count = 0; for (const key in this.array) { // To prevent random stuff to appear if (this.array.hasOwnProperty(key)) { const value = this.array[key]; cbFunction(key, value, count); count++; } } } public forEachValue(cbFunction: (value: V, index: number) => void): void { let count = 0; for (const key in this.array) { // To prevent random stuff to appear if (this.array.hasOwnProperty(key)) { const value = this.array[key]; cbFunction(value, count); count++; } } } } /** * Tuple to hold two values. */ export class TuplePair<X, Y> { private _x: X; private _y: Y; constructor(x: X, y: Y) { this._x = x; this._y = y; } get x(): X { return this._x; } set x(value: X) { this._x = value; } get y(): Y { return this._y; } set y(value: Y) { this._y = value; } } /** * Utility class to build up a string. */ export class StringBuilder { private data: string[] = []; public append(line: string): StringBuilder { if (line === undefined || line == null) { throw new Error("String must be set, cannot append null or undefined"); } this.data.push(line); return this; } public appendLine(line: string): StringBuilder { this.data.push(line + "\n"); return this; } public isEmpty(): boolean { return this.data.length === 0; } public clear(): void { this.data = []; } public toString(separator: string = ""): string { return this.data.join(separator); } }