UNPKG

metaapi.cloud-sdk

Version:

SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)

235 lines (214 loc) 5.13 kB
'use strict'; /** * Implements a queue structure * @template T Queue values type */ export default class Queue<T> { private _length: number; private _start: any; private _end: any; /** * Creates a queue from array * @param {Array<V>} array Array to create the queue from * @return {Queue<V>} Queue created from the array * @deprecated Use constructor instead */ static fromArray<V>(array: V[]) { let queue = new Queue<V>(); array.forEach(item => queue.push(item)); return queue; } /** * Constructs instance * @param {Iterable<T>} [items] Initial items to add to the queue */ constructor(items?: Iterable<T>) { for (let item of items || []) { this.push(item); } this._length = 0; } /** * Returns the queue size * @return {Number} Queue size */ get length() { return this._length; } /** * Iterates by queue items */ *[Symbol.iterator](): Iterator<T> { let current = this._start; while (current) { yield current.value; current = current.next; } } /** * Returns the first element or undefined if the queue is empty * @return {T} The first value */ front(): T | undefined { return this._start?.value; } /** * Returns the last element or undefined if the queue is empty * @return {T} The last value */ back(): T | undefined { return this._end?.value; } /** * Pushes new elements to the end of the queue * @param {T[]} values Values to push */ push(...values: T[]) { for (let value of values) { if (this._end) { this._end.next = {value, prev: this._end}; this._end = this._end.next; } else { this._start = this._end = {value}; } this._length++; } } /** * Removes the last element from the queue * @return {T} The value removed or undefined */ pop(): T | undefined { if (this._end) { let result = this._end; this._remove(this._end); return result.value; } } /** * Inserts new elements to the front of the queue * @param {T} value Values to unshift */ unshift(value: T) { if (this._start) { this._start = {value, next: this._start}; this._start.next.prev = this._start; } else { this._start = this._end = {value}; } this._length++; } /** * Removes the first element from the queue * @return {T} The value removed or undefined */ shift(): T | undefined { if (this._start) { let result = this._start; this._remove(this._start); return result.value; } } /** * Finds an element in the queue by the predicate * @param {(value: T) => boolean} predicate Predicate to use * @return {T} Element value found or undefined */ find(predicate: (value: T) => boolean): T | undefined { let current = this._start; while (current) { if (predicate(current.value)) { return current.value; } current = current.next; } } /** * Iterates over the queue * @param {(value: T, index: Number) => any} callable Iterator callable */ forEach(callable: (value: T, index: number) => any) { let current = this._start; let index = 0; while (current) { callable(current.value, index++); current = current.next; } } /** * Removes elements iterating them and matching by predicate * @param {(value: T) => boolean|null} predicate Returns true for values to remove. If returns null, iteration stops */ remove(predicate: (value: T) => boolean | null) { let current = this._start; while (current) { let remove = predicate(current.value); if (remove === null) { break; } if (remove === true) { this._remove(current); } current = current.next; } } /** * Removes the first occurence of element matched by predicate * @param predicate returns true for value to removed */ removeOne(predicate: (value: T) => boolean) { let removed = false; this.remove(item => { if (removed) { return null; } if (predicate(item)) { removed = true; return true; } }); } /** * Creates a new queue from this one in reversed order * @return {Queue<T>} Reversed queue */ reversed(): Queue<T> { let result = new Queue<T>(); let current = this._end; while (current) { result.push(current.value); current = current.prev; } return result; } /** * Creates an array from the queue * @return {Array<T>} Array created */ toArray(): T[] { let result = []; this.forEach(value => result.push(value)); return result; } /** * Clears the queue */ clear() { delete this._start; delete this._end; this._length = 0; } private _remove(node) { if (node.prev) { node.prev.next = node.next; } else { this._start = node.next; } if (node.next) { node.next.prev = node.prev; } else { this._end = node.prev; } this._length--; } }