<commit_before>/**
 * Copyright (c) 2016 The xterm.js authors. All rights reserved.
 * @license MIT
 */

import { EventEmitter } from './EventEmitter';
import { ICircularList } from './Types';

/**
 * Represents a circular list; a list with a maximum size that wraps around when push is called,
 * overriding values at the start of the list.
 */
export class CircularList<T> extends EventEmitter implements ICircularList<T> {
  protected _array: (T | undefined)[];
  private _startIndex: number;
  private _length: number;

  constructor(
    private _maxLength: number
  ) {
    super();
    this._array = new Array<T>(this._maxLength);
    this._startIndex = 0;
    this._length = 0;
  }

  public get maxLength(): number {
    return this._maxLength;
  }

  public set maxLength(newMaxLength: number) {
    // There was no change in maxLength, return early.
    if (this._maxLength === newMaxLength) {
      return;
    }

    // Reconstruct array, starting at index 0. Only transfer values from the
    // indexes 0 to length.
    const newArray = new Array<T | undefined>(newMaxLength);
    for (let i = 0; i < Math.min(newMaxLength, this.length); i++) {
      newArray[i] = this._array[this._getCyclicIndex(i)];
    }
    this._array = newArray;
    this._maxLength = newMaxLength;
    this._startIndex = 0;
  }

  public get length(): number {
    return this._length;
  }

  public set length(newLength: number) {
    if (newLength > this._length) {
      for (let i = this._length; i < newLength; i++) {
        this._array[i] = undefined;
      }
    }
    this._length = newLength;
  }

  /**
   * Gets the value at an index.
   *
   * Note that for performance reasons there is no bounds checking here, the index reference is
   * circular so this should always return a value and never throw.
   * @param index The index of the value to get.
   * @return The value corresponding to the index.
   */
  public get(index: number): T | undefined {
    return this._array[this._getCyclicIndex(index)];
  }

  /**
   * Sets the value at an index.
   *
   * Note that for performance reasons there is no bounds checking here, the index reference is
   * circular so this should always return a value and never throw.
   * @param index The index to set.
   * @param value The value to set.
   */
  public set(index: number, value: T | undefined): void {
    this._array[this._getCyclicIndex(index)] = value;
  }

  /**
   * Pushes a new value onto the list, wrapping around to the start of the array, overriding index 0
   * if the maximum length is reached.
   * @param value The value to push onto the list.
   */
  public push(value: T): void {
    this._array[this._getCyclicIndex(this._length)] = value;
    if (this._length === this._maxLength) {
      this._startIndex = ++this._startIndex % this._maxLength;
      this.emit('trim', 1);
    } else {
      this._length++;
    }
  }

  /**
   * Advance ringbuffer index and return current element for recycling.
   * Note: If the ringbuffer is not full this method will return undefined,
   * Either precheck with isFull() or handle the undefined return value accordingly.
   */
  public recycle(): T | undefined {
    if (this._length === this._maxLength) {
      this._startIndex = ++this._startIndex % this._maxLength;
      this.emit('trim', 1);
    } else {
      this._length++;
    }
    return this._array[this._getCyclicIndex(this._length - 1)];
  }

  /**
   * Ringbuffer is at max length.
   */
  public isFull(): boolean {
    return this._length === this._maxLength;
  }

  /**
   * Removes and returns the last value on the list.
   * @return The popped value.
   */
  public pop(): T | undefined {
    return this._array[this._getCyclicIndex(this._length-- - 1)];
  }

  /**<commit_msg>throw error in recycle with buffer not full<commit_after>/**
 * Copyright (c) 2016 The xterm.js authors. All rights reserved.
 * @license MIT
 */

import { EventEmitter } from './EventEmitter';
import { ICircularList } from './Types';

/**
 * Represents a circular list; a list with a maximum size that wraps around when push is called,
 * overriding values at the start of the list.
 */
export class CircularList<T> extends EventEmitter implements ICircularList<T> {
  protected _array: (T | undefined)[];
  private _startIndex: number;
  private _length: number;

  constructor(
    private _maxLength: number
  ) {
    super();
    this._array = new Array<T>(this._maxLength);
    this._startIndex = 0;
    this._length = 0;
  }

  public get maxLength(): number {
    return this._maxLength;
  }

  public set maxLength(newMaxLength: number) {
    // There was no change in maxLength, return early.
    if (this._maxLength === newMaxLength) {
      return;
    }

    // Reconstruct array, starting at index 0. Only transfer values from the
    // indexes 0 to length.
    const newArray = new Array<T | undefined>(newMaxLength);
    for (let i = 0; i < Math.min(newMaxLength, this.length); i++) {
      newArray[i] = this._array[this._getCyclicIndex(i)];
    }
    this._array = newArray;
    this._maxLength = newMaxLength;
    this._startIndex = 0;
  }

  public get length(): number {
    return this._length;
  }

  public set length(newLength: number) {
    if (newLength > this._length) {
      for (let i = this._length; i < newLength; i++) {
        this._array[i] = undefined;
      }
    }
    this._length = newLength;
  }

  /**
   * Gets the value at an index.
   *
   * Note that for performance reasons there is no bounds checking here, the index reference is
   * circular so this should always return a value and never throw.
   * @param index The index of the value to get.
   * @return The value corresponding to the index.
   */
  public get(index: number): T | undefined {
    return this._array[this._getCyclicIndex(index)];
  }

  /**
   * Sets the value at an index.
   *
   * Note that for performance reasons there is no bounds checking here, the index reference is
   * circular so this should always return a value and never throw.
   * @param index The index to set.
   * @param value The value to set.
   */
  public set(index: number, value: T | undefined): void {
    this._array[this._getCyclicIndex(index)] = value;
  }

  /**
   * Pushes a new value onto the list, wrapping around to the start of the array, overriding index 0
   * if the maximum length is reached.
   * @param value The value to push onto the list.
   */
  public push(value: T): void {
    this._array[this._getCyclicIndex(this._length)] = value;
    if (this._length === this._maxLength) {
      this._startIndex = ++this._startIndex % this._maxLength;
      this.emit('trim', 1);
    } else {
      this._length++;
    }
  }

  /**
   * Advance ringbuffer index and return current element for recycling.
   * Note: The buffer must be full for this method to work.
   * @throws When the buffer is not full.
   */
  public recycle(): T {
    if (this._length !== this._maxLength) {
      throw new Error('Can only recycle when the buffer is full');
    }
    this._startIndex = ++this._startIndex % this._maxLength;
    this.emit('trim', 1);
    return this._array[this._getCyclicIndex(this._length - 1)]!;
  }

  /**
   * Ringbuffer is at max length.
   */
  public isFull(): boolean {
    return this._length === this._maxLength;
  }

  /**
   * Removes and returns the last value on the list.
   * @return The popped value.
   */
  public pop(): T | undefined {
    return this._array[this._getCyclicIndex(this._length-- - 1)];
  }

  /**
{'fraction_non_alphanumeric': 0.11155484558040468, 'fraction_numerical': 0.003993610223642172, 'mean_word_length': 2.8312085670576237, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2730616', 'n_tokens_mistral': 2291, 'n_tokens_neox': 2215, 'n_words': 795}