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

pickle-core_sjs1_3.3.1.0.source-code.CharUtils.scala Maven / Gradle / Ivy

package upickle.core
import scala.annotation.switch
object CharUtils{

  def appendEscapedChar(charBuilder: CharBuilder, c: Char, i: Int): Boolean = {
    (c: @switch) match {
      case '"' => escapeSingleChar(charBuilder, i, '"'); true
      case '\\' => escapeSingleChar(charBuilder, i, '\\'); true
      case '\b' => escapeSingleChar(charBuilder, i, 'b'); true
      case '\f' => escapeSingleChar(charBuilder, i, 'f'); true
      case '\n' => escapeSingleChar(charBuilder, i, 'n'); true
      case '\r' => escapeSingleChar(charBuilder, i, 'r'); true
      case '\t' => escapeSingleChar(charBuilder, i, 't'); true
      case _ => false
    }
  }


  def escapeSingleChar(charBuilder: CharBuilder, i: Int, c: Char) = {
    charBuilder.ensureLength(2);
    val length = charBuilder.length
    val arr = charBuilder.arr
    arr(length) = '\\'.toChar
    arr(length + 1) = c.toChar
    charBuilder.length += 2
  }


  def escapeSingleCharUnicodeEscape(charBuilder: CharBuilder, i: Int, c: Char) = {
    charBuilder.ensureLength(6)
    val arr = charBuilder.arr
    val length = charBuilder.length
    arr(length) = '\\'.toChar
    arr(length + 1) = 'u'.toChar
    arr(length + 2) = RenderUtils.toHex((c >> 12) & 15).toChar
    arr(length + 3) = RenderUtils.toHex((c >> 8) & 15).toChar
    arr(length + 4) = RenderUtils.toHex((c >> 4) & 15).toChar
    arr(length + 5) = RenderUtils.toHex(c & 15).toChar
    charBuilder.length += 6
  }

  def appendSimpleStringSection(charBuilder: CharBuilder,
                               i0: Int,
                               len: Int,
                               s: CharSequence) = {
    charBuilder.ensureLength(len - i0)
    val i = appendSimpleStringSection0(charBuilder.arr, charBuilder.length, i0, len, s)
    charBuilder.length = charBuilder.length + (i - i0) + 1
    i
  }

  def appendSimpleStringSectionNoUnicode(charBuilder: CharBuilder,
                                        i0: Int,
                                        len: Int,
                                        s: CharSequence) = {
    charBuilder.ensureLength(len - i0)
    val i = appendSimpleStringSectionNoUnicode0(charBuilder.arr, charBuilder.length, i0, len, s)
    charBuilder.length = charBuilder.length + (i - i0) + 1
    i
  }

  private def appendSimpleStringSection0(arr: Array[Char],
                                        arrOffset: Int,
                                        i0: Int,
                                        len: Int,
                                        s: CharSequence) = {
    var i = i0
    while (
      if (i >= len) false
      else {
        val c2 = s.charAt(i)
        if (c2 < ' ' | c2 == '"' | c2 == '\\') false
        else {
          arr(arrOffset + i - i0) = c2.toChar
          i += 1
          true
        }
      }
    ) ()

    i - 1
  }

  private def appendSimpleStringSectionNoUnicode0(arr: Array[Char],
                                                 arrOffset: Int,
                                                 i0: Int,
                                                 len: Int,
                                                 s: CharSequence) = {
    var i = i0
    while (
      if (i >= len) false
      else {
        val c2 = s.charAt(i)
        if (c2 < ' ' || c2 > 127 || c2 == '"' || c2 == '\\') false
        else {
          arr(arrOffset + i - i0) = c2.toChar
          i += 1
          true
        }
      }
    ) ()

    i - 1
  }


  def parseIntegralNum(arr: Array[Char], arrOffset: Int, arrLength: Int, decIndex: Int, expIndex: Int) = {
    val expMul =
      if (expIndex == -1) 1
      else {
        var mult = 1
        val e = parseLong(arr, arrOffset + expIndex + 1, arrOffset + arrLength)
        var i = 0
        while (i < e) {
          if (mult >= Long.MaxValue / 10) throw new Abort("expected integer")
          mult = mult * 10
          i += 1
        }
        mult
      }

    val intPortion = {
      val end =
        if (decIndex != -1) decIndex
        else if (expIndex != -1) expIndex
        else arrLength

      parseLong(arr, arrOffset, arrOffset + end) * expMul
    }

    val decPortion =
      if (decIndex == -1) 0
      else {
        val end = if (expIndex != -1) expIndex else arrLength
        var value = parseLong(arr, arrOffset + decIndex + 1, arrOffset + end) * expMul
        var i = end - (decIndex + 1)
        while (i > 0) {
          value = value / 10
          i -= 1
        }
        if (arr(arrOffset) == '-') -value else value
      }

    intPortion + decPortion
  }

  def parseLong(cs0: Array[Char], start0: Int, end0: Int): Long = {
    if ((start0 | end0 | end0 - start0 | (cs0.length - end0)) < 0) throw new IndexOutOfBoundsException

    // If we do not copy the data from `cs0` into our own local array before
    // parsing it, we take a significant performance penalty in the
    // `integers Read` benchmarks, but *only* when run together with the rest
    // of the benchmarks! When `integers Read` isrun alone, this does not
    // happen, and is presumably something to do with the JIT compiler.

    // Since any real world use case would exercise all sorts of code paths,
    // it would more closely resemble the "all benchmarks together" case
    // rather, and so we leave this copy in-place to optimize performance
    // for that scenario.
    val cs = new Array[Char](end0 - start0)
    System.arraycopy(cs0, start0, cs, 0, end0 - start0)

    // we store the inverse of the positive sum, to ensure we don't
    // incorrectly overflow on Long.MinValue. for positive numbers
    // this inverse sum will be inverted before being returned.
    var inverseSum: Long = 0L
    var inverseSign: Long = -1L
    var i: Int = 0
    val end = end0 - start0

    if (cs(0) == '-') {
      inverseSign = 1L
      i += 1
    }

    val size = end - i
    if (size <= 0 || size > 19) throw new NumberFormatException(new String(cs))

    while (i < end) {
      val digit = cs(i).toInt - 48
      if (digit < 0 || 9 < digit) throw new NumberFormatException(new String(cs))
      inverseSum = inverseSum * 10L - digit
      i += 1
    }

    // detect and throw on overflow
    if (size == 19 && (inverseSum >= 0 || (inverseSum == Long.MinValue && inverseSign < 0))) {
      throw new NumberFormatException(new String(cs))
    }

    inverseSum * inverseSign
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy