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

com.mchange.sc.v2.collection.immutable.ImmutableArraySeq.scala Maven / Gradle / Ivy

The newest version!
/*
 * Distributed as part of mchange-commons-scala v0.4.0
 *
 * Copyright (C) 2015 Machinery For Change, Inc.
 *
 * Author: Steve Waldman 
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of EITHER:
 *
 *     1) The GNU Lesser General Public License (LGPL), version 2.1, as 
 *        published by the Free Software Foundation
 *
 * OR
 *
 *     2) The Eclipse Public License (EPL), version 1.0
 *
 * You may choose which license to accept if you wish to redistribute
 * or modify this work. You may offer derivatives of this work
 * under the license you have chosen, or you may provide the same
 * choice of license which you have been offered here.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received copies of both LGPL v2.1 and EPL v1.0
 * along with this software; see the files LICENSE-EPL and LICENSE-LGPL.
 * If not, the text of these licenses are currently available at
 *
 * LGPL v2.1: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
 *  EPL v1.0: http://www.eclipse.org/org/documents/epl-v10.php 
 * 
 */

package com.mchange.sc.v2.collection.immutable;

import scala.collection._;

import java.util.{Arrays,Random};

// TODO: Abstract away commonalities in factories...
object ImmutableArraySeq {
  def apply[A]( source : Array[A] )( implicit atag : scala.reflect.ClassTag[A] ) = new ImmutableArraySeq[A]( source.clone() )( atag );

  /**
   * Be sure you know WTF you are doing, that nothing else mutates this array.
   */  
  def createNoCopy[A]( source : Array[A] )( implicit atag : scala.reflect.ClassTag[A] ) = new ImmutableArraySeq( source )( atag );

  abstract class Abstract[A] protected ( private val inner : Array[A] )( implicit atag : scala.reflect.ClassTag[A] ) extends immutable.IndexedSeq[A] {
    override def apply( i : scala.Int ) : A = inner.apply(i);

    override def iterator : Iterator[A] = inner.iterator;

    override def length : scala.Int = inner.length;

    override def toArray[B >: A](implicit btag : scala.reflect.ClassTag[B]) : Array[B] = {
      try {
        if (atag.runtimeClass == btag.runtimeClass) {
          inner.clone().asInstanceOf[Array[B]]
        } else {
          val src = inner
          val len = src.length;
          val out = btag.newArray( len );
          Array.copy( src, 0, out, 0, len );
          out
        }
      } catch {
        case e : ArrayStoreException => { // if we ask for a primitive array as an Any (rare)
          Array[B]( inner : _* )          // this formulation boxes
        }
      }
    }

    override def copyToArray[B >: A](xs: Array[B], start: scala.Int, len: scala.Int): Unit = {
      val lenToCopy = math.min( xs.length - start, len )
      Array.copy( inner, 0, xs, start, lenToCopy )
    }
  }

  object Byte {
    def apply( source : Array[scala.Byte] )( implicit atag : scala.reflect.ClassTag[scala.Byte] ) = new ImmutableArraySeq.Byte( source.clone() )( atag );

    /**
     * Be sure you know WTF you are doing, that nothing else can possibly mutate this array.
     */  
    def createNoCopy( source : Array[scala.Byte] )( implicit atag : scala.reflect.ClassTag[scala.Byte] ) = new ImmutableArraySeq.Byte( source )( atag );

    def random( len : scala.Int )( random : Random ) = {
      val tmp = Array.ofDim[scala.Byte]( len )
      random.nextBytes( tmp )
      apply( tmp )
    }
  }
  final class Byte private ( private val byteInner : Array[scala.Byte] )( implicit atag : scala.reflect.ClassTag[scala.Byte] ) extends Abstract[scala.Byte]( byteInner ) {
    override def equals( o : Any ) : Boolean = {
      o match {
        case other : ImmutableArraySeq.Byte => Arrays.equals( this.byteInner, other.byteInner );
        case whatever                       => super.equals( whatever );
      }
    }

    lazy val asSignedBigInteger : java.math.BigInteger = new java.math.BigInteger( byteInner );
    lazy val asSignedBigInt     : BigInt               = BigInt( asSignedBigInteger );

    lazy val asUnsignedBigInteger : java.math.BigInteger = new java.math.BigInteger( 1, byteInner );
    lazy val asUnsignedBigInt     : BigInt               = BigInt( asUnsignedBigInteger );
  }

  object Double {
    def apply( source : Array[scala.Double] )( implicit atag : scala.reflect.ClassTag[scala.Double] ) = new ImmutableArraySeq.Double( source.clone() )( atag );

    /**
     * Be sure you know WTF you are doing, that nothing else can possibly mutate this array.
     */  
    def createNoCopy( source : Array[scala.Double] )( implicit atag : scala.reflect.ClassTag[scala.Double] ) = new ImmutableArraySeq.Double( source )( atag );
  }
  final class Double private ( private val doubleInner : Array[scala.Double] )( implicit atag : scala.reflect.ClassTag[scala.Double] ) extends Abstract[scala.Double]( doubleInner ) {
    override def equals( o : Any ) : Boolean = {
      o match {
        case other : ImmutableArraySeq.Double => Arrays.equals( this.doubleInner, other.doubleInner );
        case whatever                         => super.equals( whatever );
      }
    }
  }

  object Int {
    def apply( source : Array[scala.Int] )( implicit atag : scala.reflect.ClassTag[scala.Int] ) = new ImmutableArraySeq.Int( source.clone() )( atag );

    /**
     * Be sure you know WTF you are doing, that nothing else mutates this array.
     */  
    def createNoCopy( source : Array[scala.Int] )( implicit atag : scala.reflect.ClassTag[scala.Int] ) = new ImmutableArraySeq.Int( source )( atag );
  }
  final class Int private ( private val intInner : Array[scala.Int] )( implicit atag : scala.reflect.ClassTag[scala.Int] ) extends Abstract[scala.Int]( intInner ) {
    override def equals( o : Any ) : Boolean = {
      o match {
        case other : ImmutableArraySeq.Int => Arrays.equals( this.intInner, other.intInner );
        case whatever                      => super.equals( whatever );
      }
    }
  }

  object Long {
    def apply( source : Array[scala.Long] )( implicit atag : scala.reflect.ClassTag[scala.Long] ) = new ImmutableArraySeq.Long( source.clone() )( atag );

    /**
     * Be sure you know WTF you are doing, that nothing else mutates this array.
     */  
    def createNoCopy( source : Array[scala.Long] )( implicit atag : scala.reflect.ClassTag[scala.Long] ) = new ImmutableArraySeq.Long( source )( atag );
  }
  final class Long private ( private val longInner : Array[scala.Long] )( implicit atag : scala.reflect.ClassTag[scala.Long] ) extends Abstract[scala.Long]( longInner ) {
    override def equals( o : Any ) : Boolean = {
      o match {
        case other : ImmutableArraySeq.Long => Arrays.equals( this.longInner, other.longInner );
        case whatever                       => super.equals( whatever );
      }
    }
  }
}
final class ImmutableArraySeq[A] private ( inner : Array[A] )( implicit atag : scala.reflect.ClassTag[A] ) extends ImmutableArraySeq.Abstract[A]( inner ) {
  require( !atag.runtimeClass.isPrimitive, s"Please use an implementation of ImmutableArraySeq.Abstract specialized for ${atag.runtimeClass.getName}." );
}







© 2015 - 2025 Weber Informatics LLC | Privacy Policy