You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			77 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
/**
 | 
						|
 * This ringbuffer class can be used to keep a list of at most a size and removing old items first when the size is exceeded.
 | 
						|
 * Internally, it uses an array to keep track of the order, so two times the same item can exist in it.
 | 
						|
 *
 | 
						|
 */
 | 
						|
export class RingBuffer<T> {
 | 
						|
  private newest = -1;
 | 
						|
  private oldest = 0;
 | 
						|
  private buffer: Array<T> = [];
 | 
						|
  private readonly capacity: number;
 | 
						|
 | 
						|
  constructor(capacity: number) {
 | 
						|
    this.capacity = capacity;
 | 
						|
  }
 | 
						|
 | 
						|
  public getCapacity(): number {
 | 
						|
    return this.capacity;
 | 
						|
  }
 | 
						|
 | 
						|
  public getLength(): number {
 | 
						|
    if (this.isEmpty()) {
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    // When only one item was added, newest = 0 and oldest = 0.
 | 
						|
    // When more than one item was added, but less than capacity, newest = nbItemsAdded & oldest = 0.
 | 
						|
    // As soon as we overflow, oldest is incremented to oldest+1 and newest rolls back to 0,
 | 
						|
    // so this test fails here and we have to extract the length based on the two parts instead.
 | 
						|
    if (this.newest >= this.oldest) {
 | 
						|
      return this.newest + 1;
 | 
						|
    }
 | 
						|
    const firstPart = this.capacity - this.oldest;
 | 
						|
    const secondPart = this.newest + 1;
 | 
						|
    return firstPart + secondPart;
 | 
						|
  }
 | 
						|
 | 
						|
  public insert(item: T) {
 | 
						|
    // see comments in `getLength()`
 | 
						|
    this.newest = (this.newest + 1) % this.capacity;
 | 
						|
    if (this.buffer.length >= this.capacity) {
 | 
						|
      this.oldest = (this.oldest + 1) % this.capacity;
 | 
						|
    }
 | 
						|
    this.buffer[this.newest] = item;
 | 
						|
  }
 | 
						|
 | 
						|
  public has(item: T) {
 | 
						|
    // no items at all
 | 
						|
    if (this.isEmpty()) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    return this.toArray().includes(item);
 | 
						|
  }
 | 
						|
 | 
						|
  public isEmpty() {
 | 
						|
    return this.newest === -1;
 | 
						|
  }
 | 
						|
 | 
						|
  public clear() {
 | 
						|
    this.buffer = [];
 | 
						|
    this.newest = -1;
 | 
						|
    this.oldest = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  public toArray(): Array<T> {
 | 
						|
    if (this.isEmpty()) {
 | 
						|
      return [];
 | 
						|
    }
 | 
						|
 | 
						|
    if (this.newest >= this.oldest) {
 | 
						|
      return this.buffer.slice(0, this.newest + 1);
 | 
						|
    }
 | 
						|
    const firstPart = this.buffer.slice(this.oldest, this.capacity);
 | 
						|
    const secondPart = this.buffer.slice(0, this.newest + 1);
 | 
						|
    return [...firstPart, ...secondPart];
 | 
						|
  }
 | 
						|
}
 |