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

basis.text.String4.scala Maven / Gradle / Ivy

/*      ____              ___                                           *\
**     / __ | ___  ____  /__/___      A library of building blocks      **
**    / __  / __ |/ ___|/  / ___|                                       **
**   / /_/ / /_/ /\__ \/  /\__ \      (c) 2012 Chris Sachs              **
**  |_____/\_____\____/__/\____/      http://basis.reify.it             **
\*                                                                      */

package basis.text

import basis.collections._
import basis.util._

/** A UTF-32 string.
  * 
  * @define collection  string
  */
final class String4(codeUnits: Array[Int]) extends UTF32 {
  override def length: Int = codeUnits.length
  
  override def get(index: Int): Int = codeUnits(index)
}

/** A factory for [[String4 UTF-32 strings]]. */
object String4 {
  val empty: String4 = new String4(new Array[Int](0))
  
  def apply(chars: CharSequence): String4 = {
    val s = new String4Builder
    s.append(chars)
    s.state
  }
  
  implicit def Builder: StringBuilder[Any] { type State = String4 } = new String4Builder
}

/** A builder for 32-bit Unicode strings in the UTF-32 encoding form.
  * Produces only well-formed code unit sequences. */
private[text] final class String4Iterator
    (string: String4, private[this] var index: Int)
  extends Iterator[Int] {
  
  override def isEmpty: Boolean = index >= string.length
  
  override def head: Int = {
    if (index >= string.length) throw new NoSuchElementException("Head of empty iterator.")
    string(index)
  }
  
  override def step() {
    if (index >= string.length) throw new UnsupportedOperationException("Empty iterator step.")
    index += 1
  }
  
  override def dup: Iterator[Int] = new String4Iterator(string, index)
}

/** A builder for 32-bit Unicode strings in the UTF-32 encoding form.
  * Produces only well-formed code unit sequences. */
private[text] final class String4Builder extends StringBuilder[Any] {
  override type State = String4
  
  private[this] var codeUnits: Array[Int] = _
  
  private[this] var aliased: Boolean = true
  
  private[this] var size: Int = 0
  
  private[this] def expand(base: Int, size: Int): Int = {
    var n = (base max size) - 1
    n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16
    n + 1
  }
  
  private[this] def resize(size: Int) {
    val newCodeUnits = new Array[Int](size)
    if (codeUnits != null) java.lang.System.arraycopy(codeUnits, 0, newCodeUnits, 0, codeUnits.length min size)
    codeUnits = newCodeUnits
  }
  
  private[this] def prepare(size: Int) {
    if (aliased || size > codeUnits.length) {
      resize(expand(16, size))
      aliased = false
    }
  }
  
  override def append(c: Int) {
    val n = size
    if ((c >= 0x0000 && c <= 0xD7FF) ||
        (c >= 0xE000 && c <= 0x10FFFF)) { // U+0000..U+D7FF | U+E000..U+FFFF
      prepare(n + 1)
      codeUnits(n) = c
      size = n + 1
    }
    else { // invalid code point
      prepare(n + 1)
      codeUnits(n) = 0xFFFD
      size = n + 1
    }
  }
  
  override def expect(count: Int): this.type = {
    if (codeUnits == null || size + count > codeUnits.length) {
      resize(size + count)
      aliased = false
    }
    this
  }
  
  override def state: String4 = {
    if (codeUnits == null || size != codeUnits.length) resize(size)
    aliased = true
    new String4(codeUnits)
  }
  
  override def clear() {
    codeUnits = null
    aliased = true
    size = 0
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy