package scala.tools.nsc
package util
import Chars._
abstract class CharArrayReader { self =>
val buf: Array[Char]
def decodeUni: Boolean = true
protected def error(offset: Int, msg: String): Unit
var ch: Char = _
var charOffset: Int = 0
var lineStartOffset: Int = 0
var lastLineStartOffset: Int = 0
private var lastUnicodeOffset = -1
def isUnicodeEscape = charOffset == lastUnicodeOffset
final def nextChar() {
if (charOffset >= buf.length) {
ch = SU
} else {
val c = buf(charOffset)
ch = c
charOffset += 1
if (c == '\\') potentialUnicode()
else if (c < ' ') { skipCR(); potentialLineEnd() }
}
}
final def nextRawChar() {
if (charOffset >= buf.length) {
ch = SU
} else {
val c = buf(charOffset)
ch = c
charOffset += 1
if (c == '\\') potentialUnicode()
else if (c < ' ') potentialLineEnd()
}
}
private def potentialUnicode() {
def evenSlashPrefix: Boolean = {
var p = charOffset - 2
while (p >= 0 && buf(p) == '\\') p -= 1
(charOffset - p) % 2 == 0
}
def udigit: Int = {
if (charOffset >= buf.length) {
error(charOffset - 1, "incomplete unicode escape")
SU
}
else {
val d = digit2int(buf(charOffset), 16)
if (d >= 0) charOffset += 1
else error(charOffset, "error in unicode escape")
d
}
}
if (charOffset < buf.length && buf(charOffset) == 'u' && decodeUni && evenSlashPrefix) {
do charOffset += 1
while (charOffset < buf.length && buf(charOffset) == 'u')
val code = udigit << 12 | udigit << 8 | udigit << 4 | udigit
lastUnicodeOffset = charOffset
ch = code.toChar
}
}
private def skipCR() {
if (ch == CR)
if (charOffset < buf.length && buf(charOffset) == LF) {
charOffset += 1
ch = LF
}
}
private def potentialLineEnd() {
if (ch == LF || ch == FF) {
lastLineStartOffset = lineStartOffset
lineStartOffset = charOffset
}
}
def lookaheadReader = new CharArrayLookaheadReader
class CharArrayLookaheadReader extends CharArrayReader {
val buf = self.buf
charOffset = self.charOffset
ch = self.ch
override def decodeUni = self.decodeUni
def error(offset: Int, msg: String) = self.error(offset, msg)
def getc() = { nextChar() ; ch }
}
}