1 21 22 package org.armedbear.lisp; 23 24 public final class ConcatenatedStream extends Stream 25 { 26 private LispObject streams; 27 28 private ConcatenatedStream(LispObject streams) throws ConditionThrowable 29 { 30 this.streams = streams; 31 isInputStream = true; 32 } 33 34 public boolean isCharacterInputStream() throws ConditionThrowable 35 { 36 if (streams == NIL) 37 return true; 38 return ((Stream)streams.car()).isCharacterInputStream(); 39 } 40 41 public boolean isBinaryInputStream() throws ConditionThrowable 42 { 43 if (streams == NIL) 44 return true; 45 return ((Stream)streams.car()).isBinaryInputStream(); 46 } 47 48 public boolean isCharacterOutputStream() throws ConditionThrowable 49 { 50 return false; 51 } 52 53 public boolean isBinaryOutputStream() throws ConditionThrowable 54 { 55 return false; 56 } 57 58 public LispObject typeOf() 59 { 60 return Symbol.CONCATENATED_STREAM; 61 } 62 63 public LispClass classOf() 64 { 65 return BuiltInClass.CONCATENATED_STREAM; 66 } 67 68 public LispObject typep(LispObject typeSpecifier) throws ConditionThrowable 69 { 70 if (typeSpecifier == Symbol.CONCATENATED_STREAM) 71 return T; 72 if (typeSpecifier == BuiltInClass.CONCATENATED_STREAM) 73 return T; 74 return super.typep(typeSpecifier); 75 } 76 77 public LispObject getElementType() throws ConditionThrowable 78 { 79 if (streams == NIL) 80 return NIL; 81 return ((Stream)streams.car()).getElementType(); 82 } 83 84 public LispObject readCharNoHang(boolean eofError, LispObject eofValue) 85 throws ConditionThrowable 86 { 87 if (streams == NIL) { 88 if (eofError) 89 return signal(new EndOfFile(this)); 90 else 91 return eofValue; 92 } 93 return _charReady() ? readChar(eofError, eofValue) : NIL; 94 } 95 96 public LispObject listen() throws ConditionThrowable 97 { 98 if (unreadChar >= 0) 99 return T; 100 if (streams == NIL) 101 return NIL; 102 Stream stream = (Stream) streams.car(); 103 LispObject obj = readCharNoHang(false, this); 104 if (obj == this) 105 return NIL; 106 unreadChar = ((LispCharacter)obj).getValue(); 107 return T; 108 } 109 110 private int unreadChar = -1; 111 112 protected int _readChar() throws ConditionThrowable 114 { 115 int n; 116 if (unreadChar >= 0) { 117 n = unreadChar; 118 unreadChar = -1; 119 return n; 120 } 121 if (streams == NIL) 122 return -1; 123 Stream stream = (Stream) streams.car(); 124 n = stream._readChar(); 125 if (n >= 0) 126 return n; 127 streams = streams.cdr(); 128 return _readChar(); 129 } 130 131 protected void _unreadChar(int n) throws ConditionThrowable 132 { 133 if (unreadChar >= 0) 134 signal(new StreamError(this, "UNREAD-CHAR was invoked twice consecutively without an intervening call to READ-CHAR.")); 135 unreadChar = n; 136 } 137 138 protected boolean _charReady() throws ConditionThrowable 139 { 140 if (unreadChar >= 0) 141 return true; 142 if (streams == NIL) 143 return false; 144 Stream stream = (Stream) streams.car(); 145 if (stream._charReady()) 146 return true; 147 LispObject remainingStreams = streams.cdr(); 148 while (remainingStreams != NIL) { 149 stream = (Stream) remainingStreams.car(); 150 if (stream._charReady()) 151 return true; 152 remainingStreams = remainingStreams.cdr(); 153 } 154 return false; 155 } 156 157 public void _writeChar(char c) throws ConditionThrowable 158 { 159 outputStreamError(); 160 } 161 162 public void _writeChars(char[] chars, int start, int end) 163 throws ConditionThrowable 164 { 165 outputStreamError(); 166 } 167 168 public void _writeString(String s) throws ConditionThrowable 169 { 170 outputStreamError(); 171 } 172 173 public void _writeLine(String s) throws ConditionThrowable 174 { 175 outputStreamError(); 176 } 177 178 public int _readByte() throws ConditionThrowable 180 { 181 if (streams == NIL) 182 return -1; 183 Stream stream = (Stream) streams.car(); 184 int n = stream._readByte(); 185 if (n >= 0) 186 return n; 187 streams = streams.cdr(); 188 return _readByte(); 189 } 190 191 public void _writeByte(int n) throws ConditionThrowable 193 { 194 outputStreamError(); 195 } 196 197 public void _finishOutput() throws ConditionThrowable 198 { 199 outputStreamError(); 200 } 201 202 public void _clearInput() throws ConditionThrowable 203 { 204 } 206 207 private void outputStreamError() throws ConditionThrowable 208 { 209 signal(new StreamError(this, 210 String.valueOf(this) + " is not an output stream.")); 211 } 212 213 private static final Primitive MAKE_CONCATENATED_STREAM = 215 new Primitive("make-concatenated-stream", "&rest streams") 216 { 217 public LispObject execute(LispObject[] args) throws ConditionThrowable 218 { 219 LispObject streams = NIL; 220 for (int i = 0; i < args.length; i++) { 221 if (args[i] instanceof Stream) { 222 Stream stream = (Stream) args[i]; 223 if (stream.isInputStream()) { 224 streams = new Cons(stream, streams); 226 continue; 227 } 228 } 229 signal(new TypeError(String.valueOf(args[i]) + 230 " is not an input stream.")); 231 } 232 return new ConcatenatedStream(streams.nreverse()); 233 } 234 }; 235 236 private static final Primitive1 CONCATENATED_STREAM_STREAMS = 238 new Primitive1("concatenated-stream-streams", "concatenated-stream") 239 { 240 public LispObject execute(LispObject arg) throws ConditionThrowable 241 { 242 try { 243 return ((ConcatenatedStream)arg).streams; 244 } 245 catch (ClassCastException e) { 246 return signal(new TypeError(arg, Symbol.CONCATENATED_STREAM)); 247 } 248 } 249 }; 250 } 251 | Popular Tags |