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

pickling.binary.Util.scala Maven / Gradle / Ivy

The newest version!
package scala.pickling

package binary {
  import collection.mutable.Buffer
  import UnsafeMemory._

  object Util {

    val SizeOfByte = 1
    val SizeOfShort = 2
    val SizeOfInt = 4
    val SizeOfLong = 8
    val SizeOfFloat  = 4
    val SizeOfDouble = 8
    val SizeOfChar = 2
    val SizeOfBoolean = 1

    // Decoding functions

    def decodeShortFrom(arr: Array[Byte], i: Int): Short = {
      val fst = ((arr(i) << 8) & 0xFFFF).toShort
      val snd = (arr(i+1)      & 0x00FF).toShort
      (fst | snd).toShort
    }

    def decodeIntFrom(arr: Array[Byte], i: Int): Int = {
      val fst = (arr(i) << 24).toInt
      val snd = ((arr(i+1) << 16) & 0x00FFFFFF).toInt
      val thrd = ((arr(i+2) << 8) & 0x0000FFFF).toInt
      val frth = (arr(i+3) & 0x000000FF).toInt
      fst | snd | thrd | frth
    }

    def decodeLongFrom(arr: Array[Byte], i: Int): Long = {
      val elem1 = ((arr(i).toLong   << 56) & 0xFFFFFFFFFFFFFFFFL).toLong
      val elem2 = ((arr(i+1).toLong << 48) & 0x00FFFFFFFFFFFFFFL).toLong
      val elem3 = ((arr(i+2).toLong << 40) & 0x0000FFFFFFFFFFFFL).toLong
      val elem4 = ((arr(i+3).toLong << 32) & 0x000000FFFFFFFFFFL).toLong
      val elem5 = ((arr(i+4).toLong << 24) & 0x00000000FFFFFFFFL).toLong
      val elem6 = ((arr(i+5).toLong << 16) & 0x0000000000FFFFFFL).toLong
      val elem7 = ((arr(i+6).toLong << 8)  & 0x000000000000FFFFL).toLong
      val elem8 = (arr(i+7).toLong         & 0x00000000000000FFL).toLong
      elem1 | elem2 | elem3 | elem4 | elem5 | elem6 | elem7 | elem8
    }

    def decodeCharFrom(arr: Array[Byte], i: Int): Char = {
      val fst = ((arr(i) << 8) & 0xFFFF).toChar
      val snd = (arr(i+1)      & 0x00FF).toChar
      (fst | snd).toChar
    }

    def decodeStringFrom(arr: Array[Byte], i: Int): (String, Int) = {
      val len = decodeIntFrom(arr, i)
      val bytes = Array.ofDim[Byte](len)
      Array.copy(arr, i + SizeOfInt, bytes, 0, len)
      (new String(bytes, "UTF-8"), i + SizeOfInt + len)
    }

    def decodeBooleanFrom(arr: Array[Byte], i: Int): Boolean = {
      arr(i) != 0
    }

    def decodeByteArray(arr: Array[Byte], offset: Int, len: Int): Array[Byte] = {
      val newArr = Array.ofDim[Byte](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfByte)
      newArr
    }

    def decodeByteArrayFrom(arr: Array[Byte], i: Int): (Array[Byte], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeByteArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfByte)
    }

    def decodeShortArray(arr: Array[Byte], offset: Int, len: Int): Array[Short] = {
      val newArr = Array.ofDim[Short](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.shortArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfShort)
      newArr
    }

    def decodeShortArrayFrom(arr: Array[Byte], i: Int): (Array[Short], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeShortArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfShort)
    }

    def decodeCharArray(arr: Array[Byte], offset: Int, len: Int): Array[Char] = {
      val newArr = Array.ofDim[Char](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.charArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfChar)
      newArr
    }

    def decodeCharArrayFrom(arr: Array[Byte], i: Int): (Array[Char], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeCharArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfChar)
    }

    def decodeIntArray(arr: Array[Byte], offset: Int, len: Int): Array[Int] = {
      val newArr = Array.ofDim[Int](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.intArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfInt)
      newArr
    }

    def decodeIntArrayFrom(arr: Array[Byte], i: Int): (Array[Int], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeIntArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfInt)
    }

    def decodeLongArray(arr: Array[Byte], offset: Int, len: Int): Array[Long] = {
      val newArr = Array.ofDim[Long](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.longArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfLong)
      newArr
    }

    def decodeLongArrayFrom(arr: Array[Byte], i: Int): (Array[Long], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeLongArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfLong)
    }

    def decodeFloatArray(arr: Array[Byte], offset: Int, len: Int): Array[Float] = {
      val newArr = Array.ofDim[Float](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.floatArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfFloat)
      newArr
    }

    def decodeFloatArrayFrom(arr: Array[Byte], i: Int): (Array[Float], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeFloatArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfFloat)
    }

    def decodeDoubleArray(arr: Array[Byte], offset: Int, len: Int): Array[Double] = {
      val newArr = Array.ofDim[Double](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.doubleArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfDouble)
      newArr
    }

    def decodeDoubleArrayFrom(arr: Array[Byte], i: Int): (Array[Double], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeDoubleArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfDouble)
    }

    def decodeBooleanArray(arr: Array[Byte], offset: Int, len: Int): Array[Boolean] = {
      val newArr = Array.ofDim[Boolean](len)
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.booleanArrayOffset
      UnsafeMemory.unsafe.copyMemory(arr, srcOffset + offset, newArr, destOffset, len * SizeOfBoolean)
      newArr
    }

    def decodeBooleanArrayFrom(arr: Array[Byte], i: Int): (Array[Boolean], Int) = {
      val len = decodeIntFrom(arr, i)
      val nextPos = i + SizeOfInt
      val ia = decodeBooleanArray(arr, nextPos, len)
      (ia, nextPos + len * SizeOfBoolean)
    }

    // Encoding functions

    def encodeByte(arr: ArrayOutput[Byte], value: Byte): Unit = {
      arr += value
    }

    def encodeShort(arr: ArrayOutput[Byte], value: Short): Unit = {
      val fst = (value >>> 8 & 0xff).asInstanceOf[Byte]
      val snd = (value & 0xff).asInstanceOf[Byte]
      arr += fst
      arr += snd
    }

    def encodeInt(arr: ArrayOutput[Byte], value: Int): Unit = {
      val fst = (value >>> 24).asInstanceOf[Byte]
      val snd = (value >>> 16 & 0xff).asInstanceOf[Byte]
      val thrd = (value >>> 8 & 0xff).asInstanceOf[Byte]
      val frth = (value & 0xff).asInstanceOf[Byte]
      arr += fst
      arr += snd
      arr += thrd
      arr += frth
    }


    def encodeLong(arr: ArrayOutput[Byte], value: Long): Unit = {
      val elem1 = (value >>> 56 & 0xff).asInstanceOf[Byte]
      val elem2 = (value >>> 48 & 0xff).asInstanceOf[Byte]
      val elem3 = (value >>> 40 & 0xff).asInstanceOf[Byte]
      val elem4 = (value >>> 32 & 0xff).asInstanceOf[Byte]
      val elem5 = (value >>> 24 & 0xff).asInstanceOf[Byte]
      val elem6 = (value >>> 16 & 0xff).asInstanceOf[Byte]
      val elem7 = (value >>> 8 & 0xff).asInstanceOf[Byte]
      val elem8 = (value & 0xff).asInstanceOf[Byte]
      arr += elem1
      arr += elem2
      arr += elem3
      arr += elem4
      arr += elem5
      arr += elem6
      arr += elem7
      arr += elem8
    }

    def encodeChar(arr: ArrayOutput[Byte], value: Char): Unit = {
      val fst = (value >>> 8 & 0xff).asInstanceOf[Byte]
      val snd = (value & 0xff).asInstanceOf[Byte]
      arr += fst
      arr += snd
    }

    def encodeString(arr: ArrayOutput[Byte], value: String): Unit = {
      val bytes = value.getBytes("UTF-8")
      encodeInt(arr, bytes.length)
      val (buf, pos) = arr.target(bytes.length * SizeOfByte)
      encodeByteArrayTo(buf, pos, bytes)
      arr.flush(buf)
    }

    def encodeBoolean(arr: ArrayOutput[Byte], value: Boolean): Unit = {
      arr += (if (value) 1 else 0)
    }

    def encodeByteArray(arr: ArrayOutput[Byte], value: Array[Byte]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfByte)
      encodeByteArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeShortArray(arr: ArrayOutput[Byte], value: Array[Short]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfShort)
      encodeShortArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeIntArray(arr: ArrayOutput[Byte], value: Array[Int]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfInt)
      encodeIntArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeLongArray(arr: ArrayOutput[Byte], value: Array[Long]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfLong)
      encodeLongArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeFloatArray(arr: ArrayOutput[Byte], value: Array[Float]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfFloat)
      encodeFloatArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeDoubleArray(arr: ArrayOutput[Byte], value: Array[Double]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfDouble)
      encodeDoubleArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeCharArray(arr: ArrayOutput[Byte], value: Array[Char]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfChar)
      encodeCharArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeBooleanArray(arr: ArrayOutput[Byte], value: Array[Boolean]): Unit = {
      encodeInt(arr, value.length)
      val (buf, pos) = arr.target(value.length * SizeOfBoolean)
      encodeBooleanArrayTo(buf, pos, value)
      arr.flush(buf)
    }

    def encodeByteArrayTo(arr: Array[Byte], i: Int, value: Array[Byte]): Int = {
      val srcOffset = UnsafeMemory.byteArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfByte)
      i + value.length * SizeOfByte
    }

    def encodeShortArrayTo(arr: Array[Byte], i: Int, value: Array[Short]): Int = {
      val srcOffset = UnsafeMemory.shortArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfShort)
      i + value.length * SizeOfShort
    }

    def encodeIntArrayTo(arr: Array[Byte], i: Int, value: Array[Int]): Int = {
      val srcOffset = UnsafeMemory.intArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfInt)
      i + value.length * SizeOfInt
    }

    def encodeLongArrayTo(arr: Array[Byte], i: Int, value: Array[Long]): Int = {
      val srcOffset = UnsafeMemory.longArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfLong)
      i + value.length * SizeOfLong
    }

    def encodeFloatArrayTo(arr: Array[Byte], i: Int, value: Array[Float]): Int = {
      val srcOffset = UnsafeMemory.floatArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfFloat)
      i + value.length * SizeOfFloat
    }

    def encodeDoubleArrayTo(arr: Array[Byte], i: Int, value: Array[Double]): Int = {
      val srcOffset = UnsafeMemory.doubleArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfDouble)
      i + value.length * SizeOfDouble
    }

    def encodeCharArrayTo(arr: Array[Byte], i: Int, value: Array[Char]): Int = {
      val srcOffset = UnsafeMemory.charArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfChar)
      i + value.length * SizeOfChar
    }

    def encodeBooleanArrayTo(arr: Array[Byte], i: Int, value: Array[Boolean]): Int = {
      val srcOffset = UnsafeMemory.booleanArrayOffset
      val destOffset = UnsafeMemory.byteArrayOffset
      UnsafeMemory.unsafe.copyMemory(value, srcOffset, arr, destOffset + i, value.length * SizeOfBoolean)
      i + value.length * SizeOfBoolean
    }
  }

  object UnsafeMemory {
    import sun.misc.Unsafe

    private[pickling] val unsafe: Unsafe =
      scala.concurrent.util.Unsafe.instance

    private[pickling] val byteArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Byte]])
    private[pickling] val shortArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Short]])
    private[pickling] val intArrayOffset: Long  = unsafe.arrayBaseOffset(classOf[Array[Int]])
    private[pickling] val longArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Long]])
    private[pickling] val floatArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Float]])
    private[pickling] val doubleArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Double]])
    private[pickling] val charArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Char]])
    private[pickling] val booleanArrayOffset: Long = unsafe.arrayBaseOffset(classOf[Array[Boolean]])

    def putInt(arr: Array[Byte], i: Int, value: Int): Unit = {
      unsafe.putInt(arr, byteArrayOffset + i, value)
    }

    def getInt(arr: Array[Byte], i: Int): Int = {
      unsafe.getInt(arr, byteArrayOffset + i)
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy