1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-18 20:09:08 +02:00
unleash.unleash/lib/client-metrics/list.js
2020-02-20 08:30:37 +01:00

133 lines
3.0 KiB
JavaScript

'use strict';
const { EventEmitter } = require('events');
class Node {
constructor (value) {
this.value = value;
this.next = null;
}
link (next) {
this.next = next;
next.prev = this;
return this;
}
}
/*
* linked list
* ranged list, assumes start to end(tail) is a known order
* remove() is only implemented in reverse order for the usecase
* emits events on eviction
*/
module.exports = class List extends EventEmitter {
constructor () {
super();
this.start = null;
this.tail = null;
}
add (obj) {
const node = new Node(obj);
if (this.start) {
this.start = node.link(this.start);
} else {
this.start = node;
this.tail = node;
}
return node;
}
iterate (fn) {
if (!this.start) {
return;
}
let cursor = this.start;
while (cursor) {
const result = fn(cursor);
if (result === false) {
cursor = null;
} else {
cursor = cursor.next;
}
}
}
iterateReverse (fn) {
if (!this.tail) {
return;
}
let cursor = this.tail;
while (cursor) {
const result = fn(cursor);
if (result === false) {
cursor = null;
} else {
cursor = cursor.prev;
}
}
}
reverseRemoveUntilTrue (fn) {
if (!this.tail) {
return;
}
let cursor = this.tail;
while (cursor) {
const result = fn(cursor);
if (result === false && cursor === this.start) {
// whole list is removed
this.emit('evicted', cursor.value);
this.start = null;
this.tail = null;
// stop iteration
cursor = null;
} else if (result === true) {
// when TRUE, set match as new tail
if (cursor !== this.tail) {
this.tail = cursor;
cursor.next = null;
}
// stop iteration
cursor = null;
} else {
// evicted
this.emit('evicted', cursor.value);
// iterate to next
cursor = cursor.prev;
}
}
}
toArray () {
const result = [];
if (this.start) {
let cursor = this.start;
while (cursor) {
result.push(cursor.value);
cursor = cursor.next;
}
}
return result;
}
toArrayReverse () {
const result = [];
if (this.tail) {
let cursor = this.tail;
while (cursor) {
result.push(cursor.value);
cursor = cursor.prev;
}
}
return result;
}
};