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

cgta.oscala.util.IISeqProxy.scala Maven / Gradle / Ivy

The newest version!
package cgta.oscala
package util

import scala.collection.IndexedSeqLike


//////////////////////////////////////////////////////////////
// Copyright (c) 2014 Ben Jackman, Jeff Gomberg
// All Rights Reserved
// please contact [email protected] or [email protected]
// for licensing inquiries
// Created by bjackman @ 8/14/14 6:44 PM
//////////////////////////////////////////////////////////////

//TODO UNIT TEST THESE CLASSES
object IISeqProxy {
  def apply[A](size: => Int)(f: Int => A) : IISeq[A] = new IISeqProxy(() => size, f)
}

class IISeqProxy[A](val sz: () => Int, val get: Int => A) extends IISeq[A] with IndexedSeqLike[A, IndexedSeq[A]] {
  override def length: Int = sz()
  override def apply(i: Int): A = get(i)
}


object IISeqMerge {
  def apply[Elem, S](xss: IISeq[S], sizeF: S => Int, getF: (S, Int) => Elem): IISeqMerge[Elem, S] = {
    val totalSize = xss.iterator.map(xs => sizeF(xs)).sum
    new IISeqMerge[Elem, S] {
      val startIdxSeq: Array[Int] = {
        var startOffset = 0
        xss.map {xs =>
          val oldStartOffset = startOffset
          startOffset += sizeF(xs)
          oldStartOffset
        }.toArray
      }

      override def underlying: IISeq[S] = xss
      override def length: Int = totalSize
      override def deref[B](i: Int)(f: (S, Int) => B): B = {
        OBinarySearch.floorIndexLast(startIdxSeq, i) match {
          case Some(ssi) => {
            val subIdx = i - startIdxSeq(ssi)
            f(xss(ssi), subIdx)
          }
          case None =>
            throw new IndexOutOfBoundsException("Tried to offset: " + i + " in seq of size: " + totalSize)
        }
      }
      override def apply(i: Int): Elem = {
        deref(i)(getF)
      }

    }
  }
}

trait IISeqMerge[Elem, S] extends IISeq[Elem] with IndexedSeqLike[Elem, IISeq[Elem]] {
  def underlying: IISeq[S]
  def deref[B](i: Int)(f: (S, Int) => B): B
}

/**
 * Used various vector operations
 *
 */
object IISeqOps {
  /**
   * CIISeqOps OWNS the array it is wrapped!
   *
   * DOES NOT COPY THE ARRAY SO BE CAREFUL, CHANGES TO THE UNDERLYING ARRAY
   * WILL DO BAD BAD THINGS.
   *
   */
  def wrapArray[A](xs: Array[A]): IISeq[A] = IISeqProxy[A](xs.size)(i => xs(i))

  /**
   * Merges together multiple indexed seqs
   *
   */
  def merge[A](xss: IISeq[IISeq[A]]): IISeqMerge[A, IISeq[A]] = IISeqMerge(xss, xs => xs.size, (xs, i) => xs(i))


  /**
   *
   * Used for inserting items into sorted vectors, using the index provided by NavigableArrayOps.bs
   *
   */
  def sortedInsert[A](xs: IISeq[A], idx: Int, replaceFn: A => A, defaultValue: => A): (IISeq[A], A) = {
    //Adding a new value
    if (idx < 0) {
      val beforeIdx = -idx - 1
      val x = defaultValue
      if (beforeIdx >= xs.size) {
        (xs :+ x, x)
      } else if (beforeIdx == 0) {
        (xs.+:(x), x)
      } else {
        (xs.patch(beforeIdx, IISeq(x), 0), x)
      }
    } else {
      val x = replaceFn(xs(idx))
      (xs.updated(idx, x), x)
    }
  }

  /**
   * If there is an element at idx (where again it's a NavigableArray.bs style idx)
   * this method will either replace if with replaceFn(xs(idx)) is defined, with that defined value
   * or remove it if replaceFn is not defined there.
   */
  def sortedReplace[A](xs: IISeq[A], idx: Int, replaceFn: A => Option[A]): IISeq[A] = {
    //Adding a new value
    if (idx < 0) {
      //Do nothing
      xs
    } else {
      val x = replaceFn(xs(idx))
      if (x.isDefined) {
        xs.updated(idx, x.get)
      } else {
        xs.patch(idx, IISeq.empty, 1)
      }
    }
  }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy