/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.lex; import java.io.Reader; import java.io.FilterReader; import java.io.IOException; /** A reader that translates escaped unicode into unicode characters. */ public class EscapedUnicodeReader extends FilterReader { int pushback=-1; boolean isEvenSlash = true; public EscapedUnicodeReader(Reader in) { super(in); } public Reader getSource() { return in; } public int read() throws IOException { int r = (pushback==-1)?in.read():pushback; pushback=-1; if (r!='\\') { isEvenSlash=true; return r; } else { // found a backslash; if (!isEvenSlash) { // Only even slashes are eligible unicode escapes. isEvenSlash=true; return r; } // Check for the trailing u. pushback=in.read(); if (pushback!='u') { isEvenSlash=false; return '\\'; } // OK, we've found backslash-u. // Reset pushback and snarf up all trailing u's. pushback=-1; while((r=in.read())=='u') ; // Now we should find 4 hex digits. // If we don't, we can raise bloody hell. int val=0; for (int i=0; i<4; i++, r=in.read()) { int d=Character.digit((char)r, 16); if (r<0 || d<0) { // invalid unicode character. Spend some time getting a // meaningful error message String code = ""; for (int j = 0; j < i; j++) { code = Character.forDigit(val % 16, 16) + code; val = val/16; } for (; i<4; i++, r=in.read()) { code += ((char)r); } throw new IOException("Invalid unicode escape character: \\u" + code); } val = (val*16) + d; } // yeah, we made it. pushback = r; isEvenSlash=true; return val; } } // synthesize array read from single-character read. public int read(char cbuf[], int off, int len) throws IOException { for (int i=0; i<len; i++) { int c = read(); if (c==-1) return (i==0)?-1:i; // end of stream reached. else cbuf[i+off] = (char) c; } return len; } public boolean markSupported() { return false; } public boolean ready() throws IOException { if (pushback!=-1) return true; else return in.ready(); } }