001: /*
002: * EchoStream.java
003: *
004: * Copyright (C) 2004 Peter Graves
005: * $Id: EchoStream.java,v 1.10 2004/06/22 23:07:46 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.lisp;
023:
024: public final class EchoStream extends Stream {
025: private final Stream in;
026: private final Stream out;
027:
028: private int unreadChar = -1;
029:
030: public EchoStream(Stream in, Stream out) {
031: this .in = in;
032: this .out = out;
033: }
034:
035: public EchoStream(Stream in, Stream out, boolean interactive) {
036: this .in = in;
037: this .out = out;
038: setInteractive(interactive);
039: }
040:
041: public LispObject getElementType() throws ConditionThrowable {
042: LispObject itype = in.getElementType();
043: LispObject otype = out.getElementType();
044: if (itype.equal(otype))
045: return itype;
046: return Symbol.NULL; // FIXME
047: }
048:
049: public Stream getInputStream() {
050: return in;
051: }
052:
053: public Stream getOutputStream() {
054: return out;
055: }
056:
057: public LispObject typeOf() {
058: return Symbol.ECHO_STREAM;
059: }
060:
061: public LispClass classOf() {
062: return BuiltInClass.ECHO_STREAM;
063: }
064:
065: public LispObject typep(LispObject type) throws ConditionThrowable {
066: if (type == Symbol.ECHO_STREAM)
067: return T;
068: if (type == BuiltInClass.ECHO_STREAM)
069: return T;
070: return super .typep(type);
071: }
072:
073: public boolean isInputStream() {
074: return true;
075: }
076:
077: public boolean isOutputStream() {
078: return true;
079: }
080:
081: public boolean isCharacterInputStream() throws ConditionThrowable {
082: return in.isCharacterInputStream();
083: }
084:
085: public boolean isBinaryInputStream() throws ConditionThrowable {
086: return in.isBinaryInputStream();
087: }
088:
089: public boolean isCharacterOutputStream() throws ConditionThrowable {
090: return out.isCharacterOutputStream();
091: }
092:
093: public boolean isBinaryOutputStream() throws ConditionThrowable {
094: return out.isBinaryOutputStream();
095: }
096:
097: // Returns -1 at end of file.
098: protected int _readChar() throws ConditionThrowable {
099: int n = in._readChar();
100: if (n >= 0) {
101: // Not at end of file.
102: if (unreadChar < 0)
103: out._writeChar((char) n);
104: else
105: unreadChar = -1;
106: }
107: return n;
108: }
109:
110: protected void _unreadChar(int n) throws ConditionThrowable {
111: in._unreadChar(n);
112: unreadChar = n;
113: }
114:
115: protected boolean _charReady() throws ConditionThrowable {
116: return in._charReady();
117: }
118:
119: public void _writeChar(char c) throws ConditionThrowable {
120: out._writeChar(c);
121: }
122:
123: public void _writeChars(char[] chars, int start, int end)
124: throws ConditionThrowable {
125: out._writeChars(chars, start, end);
126: }
127:
128: public void _writeString(String s) throws ConditionThrowable {
129: out._writeString(s);
130: }
131:
132: public void _writeLine(String s) throws ConditionThrowable {
133: out._writeLine(s);
134: }
135:
136: // Reads an 8-bit byte.
137: public int _readByte() throws ConditionThrowable {
138: int n = in._readByte();
139: if (n >= 0)
140: out._writeByte(n);
141: return n;
142: }
143:
144: // Writes an 8-bit byte.
145: public void _writeByte(int n) throws ConditionThrowable {
146: out._writeByte(n);
147: }
148:
149: public void _finishOutput() throws ConditionThrowable {
150: out._finishOutput();
151: }
152:
153: public void _clearInput() throws ConditionThrowable {
154: in._clearInput();
155: }
156:
157: public LispObject close(LispObject abort) throws ConditionThrowable {
158: // "The effect of CLOSE on a constructed stream is to close the
159: // argument stream only. There is no effect on the constituents of
160: // composite streams."
161: setOpen(false);
162: return T;
163: }
164:
165: public LispObject listen() throws ConditionThrowable {
166: return in.listen();
167: }
168:
169: public LispObject freshLine() throws ConditionThrowable {
170: return out.freshLine();
171: }
172:
173: public String toString() {
174: return unreadableString("ECHO-STREAM");
175: }
176:
177: // ### make-echo-stream
178: // input-stream output-stream => echo-stream
179: private static final Primitive2 MAKE_ECHO_STREAM = new Primitive2(
180: "make-echo-stream", "input-stream output-stream") {
181: public LispObject execute(LispObject first, LispObject second)
182: throws ConditionThrowable {
183: if (!(first instanceof Stream))
184: return signal(new TypeError(first, Symbol.STREAM));
185: if (!(second instanceof Stream))
186: return signal(new TypeError(second, Symbol.STREAM));
187: return new EchoStream((Stream) first, (Stream) second);
188: }
189: };
190:
191: // ### echo-stream-input-stream
192: // echo-stream => input-stream
193: private static final Primitive1 ECHO_STREAM_INPUT_STREAM = new Primitive1(
194: "echo-stream-input-stream", "echo-stream") {
195: public LispObject execute(LispObject arg)
196: throws ConditionThrowable {
197: if (arg instanceof EchoStream)
198: return ((EchoStream) arg).getInputStream();
199: return signal(new TypeError(arg, Symbol.ECHO_STREAM));
200: }
201: };
202:
203: // ### echo-stream-output-stream
204: // echo-stream => output-stream
205: private static final Primitive1 ECHO_STREAM_OUTPUT_STREAM = new Primitive1(
206: "echo-stream-output-stream", "echo-stream") {
207: public LispObject execute(LispObject arg)
208: throws ConditionThrowable {
209: if (arg instanceof EchoStream)
210: return ((EchoStream) arg).getOutputStream();
211: return signal(new TypeError(arg, Symbol.ECHO_STREAM));
212: }
213: };
214: }
|