All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jsonRpc.CircularArrayBuffer.scala Maven / Gradle / Ivy

package jsonRpc

import scala.collection.mutable
import scala.collection.mutable.Seq
import scala.reflect.ClassTag

/**
 * A data structure that provides O(1) get, update, length, append, prepend, clear, trimStart and trimRight
 */
class CircularArrayBuffer[A: ClassTag](initialSize: Int = 1<<4) extends mutable.Seq[A] {
  private var array = Array.ofDim[A](initialSize)
  private var start, end = 0

  def popLeft(): A = {
    val result = head
    remove(0)
    result
  }

  override def apply(idx: Int) = {
    checkIndex(idx)
    array(mod(start + idx))
  }

  override def update(idx: Int, elem: A): Unit = {
    checkIndex(idx)
    array(mod(start + idx)) = elem
  }

  override def length = mod(mod(end) - mod(start))

  def append(elem: A) = {
    ensureCapacity()
    array(mod(end)) = elem
    end += 1
    this
  }

  def clear(): Unit = start = end

  def prepend(elem: A) = {
    ensureCapacity()
    start -= 1
    array(mod(start)) = elem
    this
  }

  def appendAll(xs: IterableOnce[A]): Unit = {
    xs.iterator.foreach(x => this.append(x))
  }

  def prependAll(xs: IterableOnce[A]): Unit =
    xs.iterator.toSeq.reverse.foreach(x => this.prepend(x))

  def insertAll(idx: Int, elems: IterableOnce[A]): Unit = {
    checkIndex(idx)
    if (idx == 0) {
      prependAll(elems)
    } else {
      val shift = (idx until size).map(this)
      end = start + idx
      this.appendAll(elems)
      this.appendAll(shift)
    }
  }

  def remove(idx: Int): A = {
    val elem = this(idx)
    remove(idx, 1)
    elem
  }

  def remove(idx: Int, count: Int): Unit = {
    checkIndex(idx)
    if (idx + count >= size) {
      end = start + idx
    } else if (count > 0) {
      if (idx == 0) {
        start += count
      } else {
        ((idx + count) until size).foreach(i => this(i - count) = this(i))
        end -= count
      }
    }
  }

  /**
   * Trims the capacity of this CircularBuffer's instance to be the current size
   */
  def trimToSize(): Unit = resizeTo(size)

  override def iterator = indices.iterator.map(apply)

  def trimStart(n: Int): Unit = if (n >= size) clear() else if (n >= 0) start += n

  def trimEnd(n: Int): Unit = if (n >= size) clear() else if (n >= 0) end -= n

  override def head = this(0)

  override def last = this(size - 1)

  private def mod(x: Int) = Math.floorMod(x, array.length)

  private def resizeTo(len: Int): Unit = {
    require(len >= size)
    val array2 = Array.ofDim[A](len)
    val (l, r) = (mod(start), mod(end))
    if (l <= r) {
      Array.copy(src = array, srcPos = l, dest = array2, destPos = 0, length = size)
    } else {
      val s = array.length - l
      Array.copy(src = array, srcPos = l, dest = array2, destPos = 0, length = s)
      Array.copy(src = array, srcPos = 0, dest = array2, destPos = s, length = r)
    }
    end = size
    start = 0
    array = array2
  }

  private def checkIndex(idx: Int): Unit = if(!isDefinedAt(idx)) throw new IndexOutOfBoundsException(idx.toString)

  private def ensureCapacity(): Unit = if (size == array.length - 1) resizeTo(2 * array.length)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy