001: /*
002: * translate.java
003: *
004: * Copyright (c) 2005,2006 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.io;
010:
011: import java.io.FilterInputStream;
012: import java.io.FilterOutputStream;
013: import java.io.FilterReader;
014: import java.io.FilterWriter;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.io.OutputStream;
018: import java.io.Reader;
019: import java.io.Writer;
020: import java.util.Arrays;
021: import pnuts.lang.Context;
022: import pnuts.lang.PnutsFunction;
023:
024: public class translate extends PnutsFunction {
025:
026: public translate() {
027: super ("translate");
028: }
029:
030: public boolean defined(int narg) {
031: return (narg == 3);
032: }
033:
034: static char[] toCharArray(Object obj) {
035: if (obj instanceof String) {
036: return ((String) obj).toCharArray();
037: } else if (obj instanceof char[]) {
038: return (char[]) obj;
039: } else {
040: throw new IllegalArgumentException(String.valueOf(obj));
041: }
042: }
043:
044: static byte[] toByteArray(Object obj) {
045: if (obj instanceof String) {
046: return ((String) obj).getBytes();
047: } else if (obj instanceof byte[]) {
048: return (byte[]) obj;
049: } else {
050: throw new IllegalArgumentException(String.valueOf(obj));
051: }
052: }
053:
054: protected Object exec(Object[] args, Context context) {
055: if (args.length != 3) {
056: undefined(args, context);
057: return null;
058: }
059: Object arg0 = args[0];
060: Object arg1 = args[1];
061: Object arg2 = args[2];
062: if (arg0 instanceof InputStream) {
063: byte[] b1 = toByteArray(arg1);
064: byte[] b2 = toByteArray(arg2);
065: return new TranslateInputStream((InputStream) arg0, b1, b2);
066: } else if (arg0 instanceof OutputStream) {
067: byte[] b1 = toByteArray(arg1);
068: byte[] b2 = toByteArray(arg2);
069: return new TranslateOutputStream((OutputStream) arg0, b1,
070: b2);
071: } else if (arg0 instanceof Reader) {
072: char[] c1 = toCharArray(arg1);
073: char[] c2 = toCharArray(arg2);
074: return new TranslateReader((Reader) arg0, c1, c2);
075: } else if (arg0 instanceof Writer) {
076: char[] c1 = toCharArray(arg1);
077: char[] c2 = toCharArray(arg2);
078: return new TranslateWriter((Writer) arg0, c1, c2);
079: } else if (arg0 instanceof byte[]) {
080: byte[] from = toByteArray(arg1);
081: byte[] to = toByteArray(arg2);
082: byte[] b = (byte[]) arg0;
083: byte[] table = new byte[256];
084: for (int i = 0; i < 0xff; i++) {
085: table[i] = (byte) i;
086: }
087: for (int i = 0, len = from.length; i < len; i++) {
088: table[from[i] & 0xff] = to[i];
089: }
090: for (int i = 0, len = b.length; i < len; i++) {
091: b[i] = table[b[i]];
092: }
093: return b;
094: } else if (arg0 instanceof char[]) {
095: char[] c = (char[]) arg0;
096: char[] from = toCharArray(arg1);
097: char[] to = toCharArray(arg2);
098: int l1 = from.length;
099: int l2 = to.length;
100: int l = l1 < l2 ? l1 : l2;
101: Translation[] t = new Translation[l];
102: for (int i = 0; i < l; i++) {
103: t[i] = new Translation(from[i], to[i]);
104: }
105: Arrays.sort(t);
106: char min = t[0].from;
107: char max = t[t.length - 1].from;
108: char[] table = new char[max - min + 1];
109: for (int i = 0; i < table.length; i++) {
110: table[i] = (char) (min + i);
111: }
112: for (int i = 0; i < t.length; i++) {
113: table[t[i].from - min] = t[i].to;
114: }
115: for (int i = 0; i < c.length; i++) {
116: char ch = c[i];
117: if (ch >= min && ch <= max) {
118: c[i] = table[ch - min];
119: } else {
120: c[i] = ch;
121: }
122: }
123: return c;
124: } else if (arg0 instanceof String) {
125: StringBuffer sbuf = new StringBuffer();
126: String str = (String) arg0;
127: char[] from = toCharArray(arg1);
128: char[] to = toCharArray(arg2);
129: int l1 = from.length;
130: int l2 = to.length;
131: int l = l1 < l2 ? l1 : l2;
132: Translation[] t = new Translation[l];
133: for (int i = 0; i < l; i++) {
134: t[i] = new Translation(from[i], to[i]);
135: }
136: Arrays.sort(t);
137: char min = t[0].from;
138: char max = t[t.length - 1].from;
139: char[] table = new char[max - min + 1];
140: for (int i = 0; i < table.length; i++) {
141: table[i] = (char) (min + i);
142: }
143: for (int i = 0; i < t.length; i++) {
144: table[t[i].from - min] = t[i].to;
145: }
146: for (int i = 0; i < str.length(); i++) {
147: char ch = str.charAt(i);
148: if (ch >= min && ch <= max) {
149: sbuf.append(table[ch - min]);
150: } else {
151: sbuf.append(ch);
152: }
153: }
154: return sbuf.toString();
155: } else {
156: throw new IllegalArgumentException(String.valueOf(arg0));
157: }
158: }
159:
160: static class TranslateInputStream extends FilterInputStream {
161: byte[] table = new byte[256];
162:
163: TranslateInputStream(InputStream in, byte[] from, byte[] to) {
164: super (in);
165: for (int i = 0; i < 0xff; i++) {
166: table[i] = (byte) i;
167: }
168: for (int i = 0, len = from.length; i < len; i++) {
169: table[from[i] & 0xff] = to[i];
170: }
171: }
172:
173: public int read() throws IOException {
174: int ch = super .read();
175: if (ch == -1) {
176: return -1;
177: } else {
178: return table[ch & 0xff];
179: }
180: }
181:
182: public int read(byte[] buf, int offset, int len)
183: throws IOException {
184: int r = super .read(buf, offset, len);
185: if (r != -1) {
186: for (int i = 0; i < len; i++) {
187: buf[i + offset] = table[buf[i + offset] & 0xff];
188: }
189: }
190: return r;
191: }
192: }
193:
194: static class TranslateOutputStream extends FilterOutputStream {
195: byte[] table = new byte[256];
196:
197: TranslateOutputStream(OutputStream out, byte[] from, byte[] to) {
198: super (out);
199: for (int i = 0; i < 0xff; i++) {
200: table[i] = (byte) i;
201: }
202: for (int i = 0, len = from.length; i < len; i++) {
203: table[from[i] & 0xff] = to[i];
204: }
205: }
206:
207: public void write(int ch) throws IOException {
208: super .write((int) table[ch & 0xff]);
209: }
210:
211: public void write(byte[] b, int offset, int len)
212: throws IOException {
213: for (int i = 0; i < len; i++) {
214: write(b[offset + i]);
215: }
216: }
217:
218: }
219:
220: static class TranslateReader extends FilterReader {
221: char[] table;
222: int min;
223: int max;
224:
225: TranslateReader(Reader in, char[] from, char[] to) {
226: super (in);
227: if (from.length > 0) {
228: char[] tmp = (char[]) from.clone();
229: Arrays.sort(tmp);
230: int min = tmp[0];
231: int max = tmp[tmp.length - 1];
232: this .table = new char[max - min + 1];
233: for (int i = min; i <= max; i++) {
234: table[i] = (char) i;
235: }
236: for (int i = 0; i < from.length; i++) {
237: table[from[i] - min] = to[i];
238: }
239: }
240: }
241:
242: public int read() throws IOException {
243: int ch = super .read();
244: if (table == null || ch < min || ch > max) {
245: return ch;
246: } else {
247: return table[ch - min];
248: }
249: }
250:
251: public int read(char[] buf, int offset, int len)
252: throws IOException {
253: int r = super .read(buf, offset, len);
254: if (table != null && r != -1) {
255: for (int i = 0; i < len; i++) {
256: char ch = buf[i + offset];
257: if (ch != -1 && ch >= min && ch <= max) {
258: buf[i + offset] = table[ch - min];
259: }
260: }
261: }
262: return r;
263: }
264: }
265:
266: static class TranslateWriter extends FilterWriter {
267: char[] table;
268: int min;
269: int max;
270:
271: TranslateWriter(Writer out, char[] from, char[] to) {
272: super (out);
273: if (from.length > 0) {
274: int min = from[0];
275: int max = from[0];
276: char[] tmp = (char[]) from.clone();
277: Arrays.sort(tmp);
278: min = tmp[0];
279: max = tmp[tmp.length - 1];
280: this .table = new char[max - min + 1];
281: for (int i = min; i <= max; i++) {
282: table[i] = (char) i;
283: }
284: for (int i = 0; i < from.length; i++) {
285: table[from[i] - min] = to[i];
286: }
287: }
288: }
289:
290: public void write(int ch) throws IOException {
291: if (table != null) {
292: super .write((int) table[ch - min]);
293: } else {
294: super .write(ch);
295: }
296: }
297:
298: public void write(char[] b, int offset, int len)
299: throws IOException {
300: for (int i = 0; i < len; i++) {
301: write(b[offset + i]);
302: }
303: }
304:
305: }
306:
307: static class Translation implements Comparable {
308: char from;
309: char to;
310:
311: Translation(char from, char to) {
312: this .from = from;
313: this .to = to;
314: }
315:
316: public int compareTo(Object obj) {
317: Translation t = (Translation) obj;
318: if (from < t.from) {
319: return -1;
320: } else if (from > t.from) {
321: return 1;
322: } else {
323: return 0;
324: }
325: }
326:
327: }
328:
329: public String toString() {
330: return "function translate((InputStream|OutputStream|Reader|Writer|String|char[]|byte[]), from[], to[])";
331: }
332: }
|