KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > antlr > UnicodeEscapingReader


1 /**
2  * Copyright 2005 Alan Green
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17
18
19 package org.codehaus.groovy.antlr;
20
21 import java.io.IOException JavaDoc;
22 import java.io.Reader JavaDoc;
23
24 import antlr.CharScanner;
25
26 /**
27  * Translates GLS-defined unicode escapes into characters. Throws an exception
28  * in the event of an invalid unicode escape being detected.
29  *
30  * <p>No attempt has been made to optimise this class for speed or
31  * space.</p>
32  *
33  * @version $Revision: 1.3 $
34  */

35 public class UnicodeEscapingReader extends Reader JavaDoc {
36
37     private Reader JavaDoc reader;
38     private CharScanner lexer;
39     private boolean hasNextChar = false;
40     private int nextChar;
41     private SourceBuffer sourceBuffer;
42
43     /**
44      * Constructor.
45      * @param reader The reader that this reader will filter over.
46      */

47     public UnicodeEscapingReader(Reader JavaDoc reader,SourceBuffer sourceBuffer) {
48         this.reader = reader;
49         this.sourceBuffer = sourceBuffer;
50     }
51
52     /**
53      * Sets the lexer that is using this reader. Must be called before the
54      * lexer is used.
55      */

56     public void setLexer(CharScanner lexer) {
57         this.lexer = lexer;
58     }
59
60     /**
61      * Reads characters from the underlying reader.
62      * @see java.io.Reader#read(char[],int,int)
63      */

64     public int read(char cbuf[], int off, int len) throws IOException JavaDoc {
65         int c = 0;
66         int count = 0;
67         while (count < len && (c = read())!= -1) {
68             cbuf[off + count] = (char) c;
69             count++;
70         }
71         return (count == 0 && c == -1) ? -1 : count;
72     }
73
74     /**
75      * Gets the next character from the underlying reader,
76      * translating escapes as required.
77      * @see java.io.Reader#close()
78      */

79     public int read() throws IOException JavaDoc {
80         if (hasNextChar) {
81             hasNextChar = false;
82             write(nextChar);
83             return nextChar;
84         }
85
86         int c = reader.read();
87         if (c != '\\') {
88             write(c);
89             return c;
90         }
91
92         // Have one backslash, continue if next char is 'u'
93
c = reader.read();
94         if (c != 'u') {
95             hasNextChar = true;
96             nextChar = c;
97             write('\\');
98             return '\\';
99         }
100
101         // Swallow multiple 'u's
102
do {
103             c = reader.read();
104         } while (c == 'u');
105
106         // Get first hex digit
107
checkHexDigit(c);
108         StringBuffer JavaDoc charNum = new StringBuffer JavaDoc();
109         charNum.append((char) c);
110
111         // Must now be three more hex digits
112
for (int i = 0; i < 3; i++) {
113             c = reader.read();
114             checkHexDigit(c);
115             charNum.append((char) c);
116         }
117         int rv = Integer.parseInt(charNum.toString(), 16);
118         write(rv);
119         return rv;
120     }
121     private void write(int c) {
122         if (sourceBuffer != null) {sourceBuffer.write(c);}
123     }
124     /**
125      * Checks that the given character is indeed a hex digit.
126      */

127     private void checkHexDigit(int c) throws IOException JavaDoc {
128         if (c >= '0' && c <= '9') {
129             return;
130         }
131         if (c >= 'a' && c <= 'f') {
132             return;
133         }
134         if (c >= 'A' && c <= 'F') {
135             return;
136         }
137         // Causes the invalid escape to be skipped
138
hasNextChar = true;
139         nextChar = c;
140         throw new IOException JavaDoc("Did not find four digit hex character code."
141                 + " line: " + lexer.getLine() + " col:" + lexer.getColumn());
142     }
143
144     /**
145      * Closes this reader by calling close on the underlying reader.
146      * @see java.io.Reader#close()
147      */

148     public void close() throws IOException JavaDoc {
149         reader.close();
150     }
151 }
152
Popular Tags