source: branches/0.15.x/abcl/src/org/armedbear/lisp/ConcatenatedStream.java

Last change on this file was 11754, checked in by vvoutilainen, 16 years ago

Convert using ClassCastException? to checking instanceof.
Performance tests show this approach to be faster.
Patch by Douglas R. Miles. I modified the patch to
remove tabs, so indentation may be slightly off in places.
That's something that we need to handle separately, abcl
doesn't have a clear indentation policy.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.1 KB
Line 
1/*
2 * ConcatenatedStream.java
3 *
4 * Copyright (C) 2004-2005 Peter Graves
5 * $Id: ConcatenatedStream.java 11754 2009-04-12 10:53:39Z vvoutilainen $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36public final class ConcatenatedStream extends Stream
37{
38    private LispObject streams;
39
40    private ConcatenatedStream(LispObject streams) throws ConditionThrowable
41    {
42        this.streams = streams;
43        isInputStream = true;
44    }
45
46    @Override
47    public boolean isCharacterInputStream() throws ConditionThrowable
48    {
49        if (streams == NIL)
50            return true;
51        return ((Stream)streams.car()).isCharacterInputStream();
52    }
53
54    @Override
55    public boolean isBinaryInputStream() throws ConditionThrowable
56    {
57        if (streams == NIL)
58            return true;
59        return ((Stream)streams.car()).isBinaryInputStream();
60    }
61
62    @Override
63    public boolean isCharacterOutputStream() throws ConditionThrowable
64    {
65        return false;
66    }
67
68    @Override
69    public boolean isBinaryOutputStream() throws ConditionThrowable
70    {
71        return false;
72    }
73
74    @Override
75    public LispObject typeOf()
76    {
77        return Symbol.CONCATENATED_STREAM;
78    }
79
80    @Override
81    public LispObject classOf()
82    {
83        return BuiltInClass.CONCATENATED_STREAM;
84    }
85
86    @Override
87    public LispObject typep(LispObject typeSpecifier) throws ConditionThrowable
88    {
89        if (typeSpecifier == Symbol.CONCATENATED_STREAM)
90            return T;
91        if (typeSpecifier == BuiltInClass.CONCATENATED_STREAM)
92            return T;
93        return super.typep(typeSpecifier);
94    }
95
96    @Override
97    public LispObject getElementType() throws ConditionThrowable
98    {
99        if (streams == NIL)
100            return NIL;
101        return ((Stream)streams.car()).getElementType();
102    }
103
104    @Override
105    public LispObject readCharNoHang(boolean eofError, LispObject eofValue)
106        throws ConditionThrowable
107    {
108        if (streams == NIL) {
109            if (eofError)
110                return error(new EndOfFile(this));
111            else
112                return eofValue;
113        }
114        return _charReady() ? readChar(eofError, eofValue) : NIL;
115    }
116
117    @Override
118    public LispObject listen() throws ConditionThrowable
119    {
120        if (unreadChar >= 0)
121            return T;
122        if (streams == NIL)
123            return NIL;
124        LispObject obj = readCharNoHang(false, this);
125        if (obj == this)
126            return NIL;
127        unreadChar = ((LispCharacter)obj).getValue();
128        return T;
129    }
130
131    private int unreadChar = -1;
132
133    // Returns -1 at end of file.
134    @Override
135    protected int _readChar() throws ConditionThrowable
136    {
137        int n;
138        if (unreadChar >= 0) {
139            n = unreadChar;
140            unreadChar = -1;
141            return n;
142        }
143        if (streams == NIL)
144            return -1;
145        Stream stream = (Stream) streams.car();
146        n = stream._readChar();
147        if (n >= 0)
148            return n;
149        streams = streams.cdr();
150        return _readChar();
151    }
152
153    @Override
154    protected void _unreadChar(int n) throws ConditionThrowable
155    {
156        if (unreadChar >= 0)
157            error(new StreamError(this, "UNREAD-CHAR was invoked twice consecutively without an intervening call to READ-CHAR."));
158        unreadChar = n;
159    }
160
161    @Override
162    protected boolean _charReady() throws ConditionThrowable
163    {
164        if (unreadChar >= 0)
165            return true;
166        if (streams == NIL)
167            return false;
168        Stream stream = (Stream) streams.car();
169        if (stream._charReady())
170            return true;
171        LispObject remainingStreams = streams.cdr();
172        while (remainingStreams != NIL) {
173            stream = (Stream) remainingStreams.car();
174            if (stream._charReady())
175                return true;
176            remainingStreams = remainingStreams.cdr();
177        }
178        return false;
179    }
180
181    @Override
182    public void _writeChar(char c) throws ConditionThrowable
183    {
184        outputStreamError();
185    }
186
187    @Override
188    public void _writeChars(char[] chars, int start, int end)
189        throws ConditionThrowable
190    {
191        outputStreamError();
192    }
193
194    @Override
195    public void _writeString(String s) throws ConditionThrowable
196    {
197        outputStreamError();
198    }
199
200    @Override
201    public void _writeLine(String s) throws ConditionThrowable
202    {
203        outputStreamError();
204    }
205
206    // Reads an 8-bit byte.
207    @Override
208    public int _readByte() throws ConditionThrowable
209    {
210        if (streams == NIL)
211            return -1;
212        Stream stream = (Stream) streams.car();
213        int n = stream._readByte();
214        if (n >= 0)
215            return n;
216        streams = streams.cdr();
217        return _readByte();
218    }
219
220    // Writes an 8-bit byte.
221    @Override
222    public void _writeByte(int n) throws ConditionThrowable
223    {
224        outputStreamError();
225    }
226
227    @Override
228    public void _finishOutput() throws ConditionThrowable
229    {
230        outputStreamError();
231    }
232
233    @Override
234    public void _clearInput() throws ConditionThrowable
235    {
236        // FIXME
237    }
238
239    private void outputStreamError() throws ConditionThrowable
240    {
241        error(new StreamError(this,
242                               String.valueOf(this) + " is not an output stream."));
243    }
244
245    // ### make-concatenated-stream &rest streams => concatenated-stream
246    private static final Primitive MAKE_CONCATENATED_STREAM =
247        new Primitive("make-concatenated-stream", "&rest streams")
248    {
249        @Override
250        public LispObject execute(LispObject[] args) throws ConditionThrowable
251        {
252            LispObject streams = NIL;
253            for (int i = 0; i < args.length; i++) {
254                if (args[i] instanceof Stream) {
255                    Stream stream = (Stream) args[i];
256                    if (stream.isInputStream()) {
257                        //                         streams[i] = (Stream) args[i];
258                        streams = new Cons(stream, streams);
259                        continue;
260                    }
261                }
262                error(new TypeError(String.valueOf(args[i]) +
263                                     " is not an input stream."));
264            }
265            return new ConcatenatedStream(streams.nreverse());
266        }
267    };
268
269    // ### concatenated-stream-streams concatenated-stream => streams
270    private static final Primitive CONCATENATED_STREAM_STREAMS =
271        new Primitive("concatenated-stream-streams", "concatenated-stream")
272    {
273        @Override
274        public LispObject execute(LispObject arg) throws ConditionThrowable
275        {
276            if (arg instanceof ConcatenatedStream) 
277                return ((ConcatenatedStream)arg).streams;
278            return error(new TypeError(arg, Symbol.CONCATENATED_STREAM));
279        }
280    };
281}
Note: See TracBrowser for help on using the repository browser.