source: other-projects/rsyntax-textarea/devel-packages/jflex-1.4.3/src/JFlex/PackEmitter.java@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 6.0 KB
Line 
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * jflex 1.4 *
3 * Copyright (C) 1998-2009 Gerwin Klein <[email protected]> *
4 * All rights reserved. *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License. See the file *
8 * COPYRIGHT for more information. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License along *
16 * with this program; if not, write to the Free Software Foundation, Inc., *
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
18 * *
19 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20
21package JFlex;
22
23
24/**
25 * Encodes <code>int</code> arrays as strings.
26 *
27 * Also splits up strings when longer than 64K in UTF8 encoding.
28 * Subclasses emit unpacking code.
29 *
30 * Usage protocol:
31 * <code>p.emitInit();</code><br>
32 * <code>for each data: p.emitData(data);</code><br>
33 * <code>p.emitUnpack();</code>
34 *
35 * @author Gerwin Klein
36 * @version $Revision: 433 $, $Date: 2009-01-31 19:52:34 +1100 (Sat, 31 Jan 2009) $
37 */
38public abstract class PackEmitter {
39
40 /** name of the generated array (mixed case, no yy prefix) */
41 protected String name;
42
43 /** current UTF8 length of generated string in current chunk */
44 private int UTF8Length;
45
46 /** position in the current line */
47 private int linepos;
48
49 /** max number of entries per line */
50 private static final int maxEntries = 16;
51
52 /** output buffer */
53 protected StringBuffer out = new StringBuffer();
54
55 /** number of existing string chunks */
56 protected int chunks;
57
58 /** maximum size of chunks */
59 // String constants are stored as UTF8 with 2 bytes length
60 // field in class files. One Unicode char can be up to 3
61 // UTF8 bytes. 64K max and two chars safety.
62 private static final int maxSize = 0xFFFF-6;
63
64 /** indent for string lines */
65 private static final String indent = " ";
66
67 /**
68 * Create new emitter for an array.
69 *
70 * @param name the name of the generated array
71 */
72 public PackEmitter(String name) {
73 this.name = name;
74 }
75
76 /**
77 * Convert array name into all uppercase internal scanner
78 * constant name.
79 *
80 * @return <code>name</code> as a internal constant name.
81 * @see PackEmitter#name
82 */
83 protected String constName() {
84 return "ZZ_" + name.toUpperCase();
85 }
86
87 /**
88 * Return current output buffer.
89 */
90 public String toString() {
91 return out.toString();
92 }
93
94 /**
95 * Emit declaration of decoded member and open first chunk.
96 */
97 public void emitInit() {
98 out.append(" private static final int [] ");
99 out.append(constName());
100 out.append(" = zzUnpack");
101 out.append(name);
102 out.append("();");
103 nl();
104 nextChunk();
105 }
106
107 /**
108 * Emit single unicode character.
109 *
110 * Updates length, position, etc.
111 *
112 * @param i the character to emit.
113 * @prec 0 <= i <= 0xFFFF
114 */
115 public void emitUC(int i) {
116 if (i < 0 || i > 0xFFFF)
117 throw new IllegalArgumentException("character value expected");
118
119 // cast ok because of prec
120 char c = (char) i;
121
122 printUC(c);
123 UTF8Length += UTF8Length(c);
124 linepos++;
125 }
126
127 /**
128 * Execute line/chunk break if necessary.
129 * Leave space for at least two chars.
130 */
131 public void breaks() {
132 if (UTF8Length >= maxSize) {
133 // close current chunk
134 out.append("\";");
135 nl();
136
137 nextChunk();
138 }
139 else {
140 if (linepos >= maxEntries) {
141 // line break
142 out.append("\"+");
143 nl();
144 out.append(indent);
145 out.append("\"");
146 linepos = 0;
147 }
148 }
149 }
150
151 /**
152 * Emit the unpacking code.
153 */
154 public abstract void emitUnpack();
155
156 /**
157 * emit next chunk
158 */
159 private void nextChunk() {
160 nl();
161 out.append(" private static final String ");
162 out.append(constName());
163 out.append("_PACKED_");
164 out.append(chunks);
165 out.append(" =");
166 nl();
167 out.append(indent);
168 out.append("\"");
169
170 UTF8Length = 0;
171 linepos = 0;
172 chunks++;
173 }
174
175 /**
176 * emit newline
177 */
178 protected void nl() {
179 out.append(Out.NL);
180 }
181
182 /**
183 * Append a unicode/octal escaped character
184 * to <code>out</code> buffer.
185 *
186 * @param c the character to append
187 */
188 private void printUC(char c) {
189 if (c > 255) {
190 out.append("\\u");
191 if (c < 0x1000) out.append("0");
192 out.append(Integer.toHexString(c));
193 }
194 else {
195 out.append("\\");
196 out.append(Integer.toOctalString(c));
197 }
198 }
199
200 /**
201 * Calculates the number of bytes a Unicode character
202 * would have in UTF8 representation in a class file.
203 *
204 * @param value the char code of the Unicode character
205 * @prec 0 <= value <= 0xFFFF
206 *
207 * @return length of UTF8 representation.
208 */
209 private int UTF8Length(char value) {
210 // if (value < 0 || value > 0xFFFF) throw new Error("not a char value ("+value+")");
211
212 // see JVM spec section 4.4.7, p 111
213 if (value == 0) return 2;
214 if (value <= 0x7F) return 1;
215
216 // workaround for javac bug (up to jdk 1.3):
217 if (value < 0x0400) return 2;
218 if (value <= 0x07FF) return 3;
219
220 // correct would be:
221 // if (value <= 0x7FF) return 2;
222 return 3;
223 }
224
225 // convenience
226 protected void println(String s) {
227 out.append(s);
228 nl();
229 }
230}
Note: See TracBrowser for help on using the repository browser.