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

zio.morphir.sexpr.internal.StringEscape.scala Maven / Gradle / Ivy

There is a newer version: 0.2.0-M01
Show newest version
package zio.morphir.sexpr.internal

import scala.annotation._

// Fix escaping in a string
final class StringEscape(in: String) {
  private[this] var escaped = false
  private[this] var pos     = 0

  def run: Either[String, String] = {
    val len = in.length
    pos = 0
    val result = new StringBuilder
    try {
      while (pos < len) {
        result += readChar()
      }
      Right(result.toString)
    } catch {
      case e: Exception => Left(s"[$in] -- has an error in string encoding: ${e.getMessage()}")
    }
  }

  def nextChar: Char = {
    pos += 1
    in.charAt(pos - 1)
  }

  def read(): Int = {
    val c = nextChar
    if (escaped) {
      escaped = false
      (c: @switch) match {
        case '"' | '\\' | '/' => c.toInt
        case 'b'              => '\b'.toInt
        case 'f'              => '\f'.toInt
        case 'n'              => '\n'.toInt
        case 'r'              => '\r'.toInt
        case 't'              => '\t'.toInt
        case 'u'              => nextHex4()
        case _ =>
          throw new Exception(s"invalid '\\${c.toChar}' in string")
      }
    } else if (c == '\\') {
      escaped = true
      read()
    }
    // else if (c == '"') -1 // this is the EOS for the caller
    else if (c < ' ')
      throw new Exception("invalid control in string")
    else c.toInt
  }

  // callers expect to get an EOB so this is rare
  def readChar(): Char = {
    read().toChar
  }

  // consumes 4 hex characters after current
  def nextHex4(): Int = {
    var i: Int     = 0
    var accum: Int = 0
    while (i < 4) {
      var c: Int = nextChar.toInt
      // if (c == -1)
      //   throw new Exception("unexpected EOB in string")
      c =
        if ('0' <= c && c <= '9') c - '0'
        else if ('A' <= c && c <= 'F') c - 'A' + 10
        else if ('a' <= c && c <= 'f') c - 'a' + 10
        else
          throw new Exception("invalid charcode in string")
      accum = accum * 16 + c
      i += 1
    }
    accum
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy