Changeset 11434
- Timestamp:
- 12/07/08 23:24:31 (14 years ago)
- Location:
- trunk/j
- Files:
-
- 8 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/j/build.xml
r11386 r11434 101 101 <patternset id="abcl.source.java"> 102 102 <include name="org/armedbear/lisp/*.java"/> 103 <include name="org/armedbear/lisp/util/*.java"/> 103 104 <include name="org/armedbear/Main.java"/> 104 105 </patternset> … … 118 119 <patternset id="abcl.objects"> 119 120 <include name="org/armedbear/lisp/*.class"/> 121 <include name="org/armedbear/lisp/util/*.class"/> 120 122 <include name="org/armedbear/lisp/*.cls"/> 121 123 <include name="org/armedbear/lisp/*.abcl"/> -
trunk/j/src/org/armedbear/lisp/FileStream.java
r11392 r11434 3 3 * 4 4 * Copyright (C) 2004-2006 Peter Graves 5 * Copyright (C) 2008 Hideo at Yokohama 5 6 * $Id$ 6 7 * … … 35 36 36 37 import java.io.File; 38 import java.io.InputStream; 39 import java.io.OutputStream; 40 import java.io.Reader; 41 import java.io.Writer; 37 42 import java.io.FileNotFoundException; 38 43 import java.io.IOException; 39 44 import java.io.RandomAccessFile; 45 import org.armedbear.lisp.util.RandomAccessCharacterFile; 40 46 41 47 public final class FileStream extends Stream 42 48 { 43 private static final int BUFSIZE = 4096; 44 45 private final RandomAccessFile raf; 46 private final RandomAccessFile in; 47 private final RandomAccessFile out; 49 private final RandomAccessCharacterFile racf; 48 50 private final Pathname pathname; 49 51 private final int bytesPerUnit; 50 private final byte[] inputBuffer;51 private final byte[] outputBuffer;52 53 private long inputBufferFilePosition;54 private int inputBufferOffset;55 private int inputBufferCount;56 private int outputBufferOffset;57 52 58 53 public FileStream(Pathname pathname, String namestring, 59 54 LispObject elementType, LispObject direction, 60 LispObject ifExists )55 LispObject ifExists, LispObject format) 61 56 throws IOException 62 57 { 58 /* externalFormat is a LispObject of which the first char is a 59 * name of a character encoding (such as :UTF-8 or :ISO-8859-1), used 60 * by ABCL as a string designator, unless the name is :CODE-PAGE. 61 * A real string is (thus) also allowed. 62 * 63 * Then, a property list follows with 3 possible keys: 64 * :ID (values: code page numbers supported by MS-DOS/IBM-DOS/MS-Windows 65 * :EOL-STYLE (values: :CR / :LF / :CRLF [none means native]) 66 * :LITTLE-ENDIAN (values: NIL / T) 67 * 68 * These definitions have been taken from FLEXI-STREAMS: 69 * http://www.weitz.de/flexi-streams/#make-external-format 70 */ 63 71 final File file = new File(namestring); 64 72 String mode = null; … … 74 82 isOutputStream = true; 75 83 } 84 76 85 Debug.assertTrue(mode != null); 77 raf = new RandomAccessFile(file, mode); 78 in = isInputStream ? raf : null; 79 out = isOutputStream ? raf : null; 86 RandomAccessFile raf = new RandomAccessFile(file, mode); 87 80 88 // ifExists is ignored unless we have an output stream. 81 89 if (isOutputStream) { … … 90 98 } 91 99 } 100 setExternalFormat(format); 101 102 // don't touch raf directly after passing it to racf. 103 // the state will become inconsistent if you do that. 104 racf = new RandomAccessCharacterFile(raf, encoding); 105 92 106 this.pathname = pathname; 93 107 this.elementType = elementType; … … 95 109 isCharacterStream = true; 96 110 bytesPerUnit = 1; 111 if (isInputStream) { 112 initAsCharacterInputStream(racf.getReader()); 113 } 114 if (isOutputStream) { 115 initAsCharacterOutputStream(racf.getWriter()); 116 } 97 117 } else { 98 118 isBinaryStream = true; … … 105 125 } 106 126 bytesPerUnit = width / 8; 107 } 108 if (isBinaryStream && isInputStream && !isOutputStream && bytesPerUnit == 1) 109 inputBuffer = new byte[BUFSIZE]; 110 else if (isCharacterStream && isInputStream && !isOutputStream) 111 inputBuffer = new byte[BUFSIZE]; 112 else 113 inputBuffer = null; 114 if (isBinaryStream && isOutputStream && !isInputStream && bytesPerUnit == 1) 115 outputBuffer = new byte[BUFSIZE]; 116 else if (isCharacterStream && isOutputStream && !isInputStream) 117 outputBuffer = new byte[BUFSIZE]; 118 else 119 outputBuffer = null; 127 if (isInputStream) { 128 initAsBinaryInputStream(racf.getInputStream()); 129 } 130 if (isOutputStream) { 131 initAsBinaryOutputStream(racf.getOutputStream()); 132 } 133 } 120 134 } 121 135 … … 148 162 149 163 @Override 150 public LispObject listen() throws ConditionThrowable151 {152 try {153 return in.getFilePointer() < in.length() ? T : NIL;154 }155 catch (NullPointerException e) {156 streamNotInputStream();157 }158 catch (IOException e) {159 error(new StreamError(this, e));160 }161 // Not reached.162 return NIL;163 }164 165 @Override166 164 public LispObject fileLength() throws ConditionThrowable 167 165 { … … 169 167 if (isOpen()) { 170 168 try { 171 length = ra f.length();169 length = racf.length(); 172 170 } 173 171 catch (IOException e) { … … 192 190 193 191 @Override 194 public LispObject readLine(boolean eofError, LispObject eofValue)195 throws ConditionThrowable196 {197 if (inputBuffer != null) {198 final LispThread thread = LispThread.currentThread();199 final FastStringBuffer sb = new FastStringBuffer();200 while (true) {201 int n = _readChar();202 if (n < 0) {203 // End of file.204 if (sb.length() == 0) {205 if (eofError)206 return error(new EndOfFile(this));207 return thread.setValues(eofValue, T);208 }209 return thread.setValues(new SimpleString(sb), T);210 }211 char c = (char) n;212 if (c == '\n')213 return thread.setValues(new SimpleString(sb), NIL);214 else215 sb.append(c);216 }217 } else218 return super.readLine(eofError, eofValue);219 }220 221 // Returns -1 at end of file.222 @Override223 protected int _readChar() throws ConditionThrowable224 {225 try {226 int c = _readByte();227 if (Utilities.isPlatformWindows) {228 if (c == '\r') {229 int c2 = _readByte();230 if (c2 == '\n') {231 ++lineNumber;232 return c2;233 }234 // '\r' was not followed by '\n'235 if (inputBuffer != null && inputBufferOffset > 0) {236 --inputBufferOffset;237 } else {238 clearInputBuffer();239 long pos = in.getFilePointer();240 if (pos > 0)241 in.seek(pos - 1);242 }243 }244 return c;245 }246 if (c == '\n') {247 ++lineNumber;248 return c;249 }250 return c;251 }252 catch (NullPointerException e) {253 streamNotInputStream();254 }255 catch (IOException e) {256 error(new StreamError(this, e));257 }258 // Not reached.259 return -1;260 }261 262 @Override263 192 protected void _unreadChar(int n) throws ConditionThrowable 264 193 { 265 if (inputBuffer != null && inputBufferOffset > 0) { 266 --inputBufferOffset; 267 if (n != '\n') 268 return; 269 --lineNumber; 270 if (!Utilities.isPlatformWindows) 271 return; 272 // Check for preceding '\r'. 273 if (inputBufferOffset > 0) { 274 if (inputBuffer[--inputBufferOffset] != '\r') 275 ++inputBufferOffset; 276 return; 277 } 278 // We can't go back far enough in the buffered input. Reset and 279 // fall through... 280 ++inputBufferOffset; 281 } 282 try { 283 long pos; 284 if (inputBuffer != null && inputBufferFilePosition >= 0) 285 pos = inputBufferFilePosition + inputBufferOffset; 286 else 287 pos = in.getFilePointer(); 288 clearInputBuffer(); 289 if (pos > 0) 290 in.seek(pos - 1); 291 if (Utilities.isPlatformWindows && n == '\n') { 292 // Check for preceding '\r'. 293 pos = in.getFilePointer(); 294 if (pos > 0) { 295 in.seek(pos - 1); 296 n = in.read(); 297 if (n == '\r') 298 in.seek(pos - 1); 299 } 300 } 301 } 302 catch (NullPointerException e) { 303 streamNotInputStream(); 194 try { 195 racf.unreadChar((char)n); 304 196 } 305 197 catch (IOException e) { … … 315 207 316 208 @Override 317 public void _writeChar(char c) throws ConditionThrowable318 {319 if (c == '\n') {320 if (Utilities.isPlatformWindows)321 _writeByte((byte)'\r');322 _writeByte((byte)c);323 charPos = 0;324 } else {325 _writeByte((byte)c);326 ++charPos;327 }328 }329 330 @Override331 public void _writeChars(char[] chars, int start, int end)332 throws ConditionThrowable333 {334 if (Utilities.isPlatformWindows) {335 for (int i = start; i < end; i++) {336 char c = chars[i];337 if (c == '\n') {338 _writeByte((byte)'\r');339 _writeByte((byte)c);340 charPos = 0;341 } else {342 _writeByte((byte)c);343 ++charPos;344 }345 }346 } else {347 // We're not on Windows, so no newline conversion is necessary.348 for (int i = start; i < end; i++) {349 char c = chars[i];350 _writeByte((byte)c);351 if (c == '\n')352 charPos = 0;353 else354 ++charPos;355 }356 }357 }358 359 @Override360 public void _writeString(String s) throws ConditionThrowable361 {362 final int length = s.length();363 if (Utilities.isPlatformWindows) {364 for (int i = 0; i < length; i++) {365 char c = s.charAt(i);366 if (c == '\n') {367 _writeByte((byte)'\r');368 _writeByte((byte)c);369 charPos = 0;370 } else {371 _writeByte((byte)c);372 ++charPos;373 }374 }375 } else {376 // We're not on Windows, so no newline conversion is necessary.377 for (int i = 0; i < length; i++) {378 char c = s.charAt(i);379 _writeByte((byte)c);380 if (c == '\n')381 charPos = 0;382 else383 ++charPos;384 }385 }386 }387 388 @Override389 public void _writeLine(String s) throws ConditionThrowable390 {391 _writeString(s);392 if (Utilities.isPlatformWindows)393 _writeByte((byte)'\r');394 _writeByte((byte)'\n');395 charPos = 0;396 }397 398 // Reads an 8-bit byte.399 @Override400 public int _readByte() throws ConditionThrowable401 {402 if (inputBuffer != null)403 return readByteFromBuffer();404 try {405 return in.read(); // Reads an 8-bit byte.406 }407 catch (NullPointerException e) {408 streamNotInputStream();409 }410 catch (IOException e) {411 error(new StreamError(this, e));412 }413 // Not reached.414 return -1;415 }416 417 // Writes an 8-bit byte.418 @Override419 public void _writeByte(int n) throws ConditionThrowable420 {421 if (outputBuffer != null) {422 writeByteToBuffer((byte)n);423 } else {424 try {425 out.write((byte)n); // Writes an 8-bit byte.426 }427 catch (NullPointerException e) {428 streamNotOutputStream();429 }430 catch (IOException e) {431 error(new StreamError(this, e));432 }433 }434 }435 436 @Override437 public void _finishOutput() throws ConditionThrowable438 {439 if (outputBuffer != null)440 flushOutputBuffer();441 }442 443 @Override444 209 public void _clearInput() throws ConditionThrowable 445 210 { 446 211 try { 447 in.seek(in.length()); 448 clearInputBuffer();449 } 450 catch (NullPointerException e) { 451 streamNotInputStream(); 212 if (isInputStream) { 213 racf.position(racf.length()); 214 } else { 215 streamNotInputStream(); 216 } 452 217 } 453 218 catch (IOException e) { … … 459 224 protected long _getFilePosition() throws ConditionThrowable 460 225 { 461 if (inputBuffer != null) { 462 if (inputBufferFilePosition >= 0) 463 return inputBufferFilePosition + inputBufferOffset; 464 } 465 if (outputBuffer != null) 466 flushOutputBuffer(); 467 try { 468 long pos = raf.getFilePointer(); 226 try { 227 long pos = racf.position(); 469 228 return pos / bytesPerUnit; 470 229 } … … 479 238 protected boolean _setFilePosition(LispObject arg) throws ConditionThrowable 480 239 { 481 if (outputBuffer != null)482 flushOutputBuffer();483 if (inputBuffer != null)484 clearInputBuffer();485 240 try { 486 241 long pos; … … 488 243 pos = 0; 489 244 else if (arg == Keyword.END) 490 pos = ra f.length();245 pos = racf.length(); 491 246 else { 492 247 long n = Fixnum.getValue(arg); // FIXME arg might be a bignum 493 248 pos = n * bytesPerUnit; 494 249 } 495 ra f.seek(pos);250 racf.position(pos); 496 251 } 497 252 catch (IOException e) { … … 504 259 public void _close() throws ConditionThrowable 505 260 { 506 if (outputBuffer != null) 507 flushOutputBuffer(); 508 try { 509 raf.close(); 261 try { 262 racf.close(); 510 263 setOpen(false); 511 264 } … … 515 268 } 516 269 517 private int readByteFromBuffer() throws ConditionThrowable518 {519 if (inputBufferOffset >= inputBufferCount) {520 fillInputBuffer();521 if (inputBufferCount < 0)522 return -1;523 }524 return inputBuffer[inputBufferOffset++] & 0xff;525 }526 527 private void fillInputBuffer() throws ConditionThrowable528 {529 try {530 inputBufferFilePosition = in.getFilePointer();531 inputBufferOffset = 0;532 inputBufferCount = in.read(inputBuffer, 0, BUFSIZE);533 }534 catch (NullPointerException e) {535 streamNotInputStream();536 }537 catch (IOException e) {538 error(new StreamError(this, e));539 }540 }541 542 private void clearInputBuffer()543 {544 inputBufferFilePosition = -1;545 inputBufferOffset = 0;546 inputBufferCount = 0;547 }548 549 private void writeByteToBuffer(byte b) throws ConditionThrowable550 {551 if (outputBufferOffset == BUFSIZE)552 flushOutputBuffer();553 outputBuffer[outputBufferOffset++] = b;554 }555 556 private void flushOutputBuffer() throws ConditionThrowable557 {558 if (outputBufferOffset > 0) {559 try {560 out.write(outputBuffer, 0, outputBufferOffset);561 outputBufferOffset = 0;562 }563 catch (NullPointerException e) {564 streamNotOutputStream();565 }566 catch (IOException e) {567 error(new StreamError(this, e));568 }569 }570 }571 572 270 @Override 573 271 public String writeToString() throws ConditionThrowable … … 576 274 } 577 275 578 // ### make-file-stream pathname namestring element-type direction if-exists => stream276 // ### make-file-stream pathname namestring element-type direction if-exists external-format => stream 579 277 private static final Primitive MAKE_FILE_STREAM = 580 278 new Primitive("make-file-stream", PACKAGE_SYS, true, 581 "pathname namestring element-type direction if-exists ")279 "pathname namestring element-type direction if-exists external-format") 582 280 { 583 281 @Override 584 282 public LispObject execute(LispObject first, LispObject second, 585 283 LispObject third, LispObject fourth, 586 LispObject fifth )284 LispObject fifth, LispObject sixth) 587 285 throws ConditionThrowable 588 286 { … … 604 302 LispObject direction = fourth; 605 303 LispObject ifExists = fifth; 304 LispObject externalFormat = sixth; 305 606 306 if (direction != Keyword.INPUT && direction != Keyword.OUTPUT && 607 307 direction != Keyword.IO) … … 609 309 try { 610 310 return new FileStream(pathname, namestring.getStringValue(), 611 elementType, direction, ifExists); 311 elementType, direction, ifExists, 312 externalFormat); 612 313 } 613 314 catch (FileNotFoundException e) { -
trunk/j/src/org/armedbear/lisp/Stream.java
r11391 r11434 44 44 import java.io.PrintWriter; 45 45 import java.io.PushbackReader; 46 import java.io.Reader; 46 47 import java.io.StringWriter; 47 48 import java.io.Writer; … … 63 64 protected boolean isBinaryStream; 64 65 66 private boolean pastEnd = false; 65 67 private boolean interactive; 66 68 private boolean open = true; 67 69 68 70 // Character input. 69 pr ivatePushbackReader reader;71 protected PushbackReader reader; 70 72 protected int offset; 71 73 protected int lineNumber; … … 80 82 */ 81 83 protected int charPos; 82 84 85 public enum EolStyle { 86 RAW, 87 CR, 88 CRLF, 89 LF 90 } 91 92 static final protected Symbol keywordDefault = Packages.internKeyword("DEFAULT"); 93 94 static final private Symbol keywordCodePage = Packages.internKeyword("CODE-PAGE"); 95 static final private Symbol keywordID = Packages.internKeyword("ID"); 96 97 static final private Symbol keywordEolStyle = Packages.internKeyword("EOL-STYLE"); 98 static final private Symbol keywordCR = Packages.internKeyword("CR"); 99 static final private Symbol keywordLF = Packages.internKeyword("LF"); 100 static final private Symbol keywordCRLF = Packages.internKeyword("CRLF"); 101 static final private Symbol keywordRAW = Packages.internKeyword("RAW"); 102 103 public final static EolStyle platformEolStyle = Utilities.isPlatformWindows ? EolStyle.CRLF : EolStyle.LF; 104 105 protected EolStyle eolStyle = platformEolStyle; 106 protected char eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; 107 protected LispObject externalFormat = LispObject.NIL; 108 protected String encoding = null; 109 protected char lastChar = 0; 110 83 111 // Binary input. 84 private BufferedInputStream in;112 private InputStream in; 85 113 86 114 // Binary output. 87 private BufferedOutputStream out;115 private OutputStream out; 88 116 89 117 protected Stream() … … 91 119 } 92 120 121 public Stream(InputStream inputStream, LispObject elementType) 122 { 123 this(inputStream, elementType, keywordDefault); 124 } 125 126 93 127 // Input stream constructors. 94 public Stream(InputStream inputStream, LispObject elementType)128 public Stream(InputStream inputStream, LispObject elementType, LispObject format) 95 129 { 96 130 this.elementType = elementType; 131 setExternalFormat(format); 97 132 if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) 98 133 { 99 isCharacterStream = true;100 134 InputStreamReader inputStreamReader; 101 135 try 102 136 { 103 137 inputStreamReader = 104 new InputStreamReader(inputStream, "ISO-8859-1"); 138 (encoding == null) ? 139 new InputStreamReader(inputStream) 140 : new InputStreamReader(inputStream, encoding); 105 141 } 106 142 catch (java.io.UnsupportedEncodingException e) … … 110 146 new InputStreamReader(inputStream); 111 147 } 112 reader = new PushbackReader(new BufferedReader(inputStreamReader), 113 2); 148 initAsCharacterInputStream(new BufferedReader(inputStreamReader)); 114 149 } 115 150 else 116 151 { 117 152 isBinaryStream = true; 118 in = new BufferedInputStream(inputStream); 119 } 120 isInputStream = true; 121 isOutputStream = false; 153 InputStream stream = new BufferedInputStream(inputStream); 154 initAsBinaryInputStream(stream); 155 } 122 156 } 123 157 … … 128 162 } 129 163 164 public Stream(OutputStream outputStream, LispObject elementType) 165 { 166 this(outputStream, elementType, keywordDefault); 167 } 168 130 169 // Output stream constructors. 131 public Stream(OutputStream outputStream, LispObject elementType )170 public Stream(OutputStream outputStream, LispObject elementType, LispObject format) 132 171 { 133 172 this.elementType = elementType; 173 setExternalFormat(format); 134 174 if (elementType == Symbol.CHARACTER || elementType == Symbol.BASE_CHAR) 135 175 { 136 isCharacterStream = true;176 Writer w; 137 177 try 138 178 { 139 writer = new OutputStreamWriter(outputStream, "ISO-8859-1"); 179 w = (encoding == null) ? 180 new OutputStreamWriter(outputStream) 181 : new OutputStreamWriter(outputStream, encoding); 140 182 } 141 183 catch (java.io.UnsupportedEncodingException e) 142 184 { 143 185 Debug.trace(e); 144 writer = new OutputStreamWriter(outputStream); 145 } 186 w = new OutputStreamWriter(outputStream); 187 } 188 initAsCharacterOutputStream(w); 146 189 } 147 190 else 148 191 { 149 isBinaryStream = true; 150 out = new BufferedOutputStream(outputStream); 151 } 152 isInputStream = false; 153 isOutputStream = true; 192 OutputStream stream = new BufferedOutputStream(outputStream); 193 initAsBinaryOutputStream(stream); 194 } 154 195 } 155 196 … … 161 202 } 162 203 204 protected void initAsCharacterInputStream(Reader reader) 205 { 206 if (! (reader instanceof PushbackReader)) 207 this.reader = new PushbackReader(reader, 5); 208 else 209 this.reader = (PushbackReader)reader; 210 211 isInputStream = true; 212 isCharacterStream = true; 213 } 214 215 protected void initAsBinaryInputStream(InputStream in) { 216 this.in = in; 217 isInputStream = true; 218 isBinaryStream = true; 219 } 220 221 protected void initAsCharacterOutputStream(Writer writer) { 222 this.writer = writer; 223 isOutputStream = true; 224 isCharacterStream = true; 225 } 226 227 protected void initAsBinaryOutputStream(OutputStream out) { 228 this.out = out; 229 isOutputStream = true; 230 isBinaryStream = true; 231 } 232 163 233 public boolean isInputStream() throws ConditionThrowable 164 234 { … … 201 271 } 202 272 273 public LispObject getExternalFormat() { 274 return externalFormat; 275 } 276 277 public String getEncoding() { 278 return encoding; 279 } 280 281 public void setExternalFormat(LispObject format) { 282 if (format == keywordDefault) { 283 encoding = null; 284 eolStyle = platformEolStyle; 285 eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; 286 externalFormat = format; 287 return; 288 } 289 290 try { 291 LispObject enc; 292 boolean encIsCp = false; 293 294 if (format instanceof Cons) { 295 // meaning a non-empty list 296 enc = format.car(); 297 298 if (enc == keywordCodePage) { 299 encIsCp = true; 300 301 enc = LispObject.getf(format.cdr(), keywordID, null); 302 } 303 304 LispObject eol = LispObject.getf(format.cdr(), keywordEolStyle, keywordRAW); 305 if (eol == keywordCR) 306 eolStyle = EolStyle.CR; 307 else if (eol == keywordLF) 308 eolStyle = EolStyle.LF; 309 else if (eol == keywordCRLF) 310 eolStyle = EolStyle.CRLF; 311 else if (eol != keywordRAW) 312 //###FIXME: raise an error 313 ; 314 315 } else 316 enc = format; 317 318 if (enc.numberp()) 319 encoding = enc.toString(); 320 else if (enc instanceof AbstractString) 321 encoding = enc.getStringValue(); 322 else if (enc == keywordDefault) 323 // This allows the user to use the encoding determined by 324 // Java to be the default for the current environment 325 // while still being able to set other stream options 326 // (e.g. :EOL-STYLE) 327 encoding = null; 328 else if (enc instanceof Symbol) 329 encoding = ((Symbol)enc).getName(); 330 else 331 //###FIXME: raise an error! 332 ; 333 334 if (encIsCp) 335 encoding = "Cp" + encoding; 336 } 337 catch (ConditionThrowable ct) { } 338 339 eolChar = (eolStyle == EolStyle.CR) ? '\r' : '\n'; 340 externalFormat = format; 341 } 342 203 343 public boolean isOpen() 204 344 { … … 1604 1744 public LispObject listen() throws ConditionThrowable 1605 1745 { 1606 return _charReady() ? T : NIL; 1746 if (pastEnd) 1747 return NIL; 1748 1749 if (! _charReady()) 1750 return NIL; 1751 1752 int n = _readChar(); 1753 if (n < 0) 1754 return NIL; 1755 1756 _unreadChar(n); 1757 1758 return T; 1607 1759 } 1608 1760 … … 1652 1804 protected int _readChar() throws ConditionThrowable 1653 1805 { 1806 if (pastEnd) 1807 return -1; 1808 1654 1809 try 1655 1810 { 1656 1811 int n = reader.read(); 1812 1813 if (n < 0) { 1814 pastEnd = true; 1815 return -1; 1816 } 1817 1657 1818 ++offset; 1658 if (n == '\r') 1659 { 1660 if (interactive && Utilities.isPlatformWindows) 1661 return _readChar(); 1662 } 1663 if (n == '\n') 1819 if (eolStyle == EolStyle.CRLF && n == '\r') { 1820 n = _readChar(); 1821 if (n != '\n') { 1822 _unreadChar(n); 1823 return '\r'; 1824 } 1825 } 1826 1827 if (n == eolChar) { 1664 1828 ++lineNumber; 1829 return '\n'; 1830 } 1831 1665 1832 return n; 1666 1833 } … … 1689 1856 reader.unread(n); 1690 1857 --offset; 1691 if (n == '\n') 1858 pastEnd = false; 1859 if (n == eolChar) 1692 1860 --lineNumber; 1693 1861 } … … 1737 1905 try 1738 1906 { 1739 writer.write(c); 1740 if (c == '\n') 1741 { 1742 writer.flush(); 1743 charPos = 0; 1744 } 1745 else 1907 if (c == '\n') { 1908 if (eolStyle == EolStyle.CRLF && lastChar != '\r') 1909 writer.write('\r'); 1910 1911 writer.write(eolChar); 1912 lastChar = eolChar; 1913 writer.flush(); 1914 charPos = 0; 1915 } else { 1916 writer.write(c); 1917 lastChar = c; 1746 1918 ++charPos; 1919 } 1747 1920 } 1748 1921 catch (NullPointerException e) … … 1770 1943 try 1771 1944 { 1945 if (eolStyle != EolStyle.RAW) { 1946 for (int i = start; i < end; i++) 1947 //###FIXME: the number of writes can be greatly reduced by 1948 // writing the space between newlines as chunks. 1949 _writeChar(chars[i]); 1950 return; 1951 } 1952 1772 1953 writer.write(chars, start, end - start); 1954 if (start < end) 1955 lastChar = chars[end-1]; 1956 1773 1957 int index = -1; 1774 1958 for (int i = end; i-- > start;) … … 1778 1962 index = i; 1779 1963 break; 1780 1781 1964 } 1965 } 1782 1966 if (index < 0) 1783 1967 { 1784 1968 // No newline. 1785 1969 charPos += (end - start); 1786 1970 } 1787 1971 else 1788 1972 { 1789 1973 charPos = end - (index + 1); 1790 writer.flush();1791 1792 1974 writer.flush(); 1975 } 1976 } 1793 1977 catch (NullPointerException e) 1794 1978 { … … 1814 1998 try 1815 1999 { 1816 writer.write(s); 1817 int index = s.lastIndexOf('\n'); 1818 if (index < 0) 1819 charPos += s.length(); 1820 else 1821 { 1822 charPos = s.length() - (index + 1); 1823 writer.flush(); 1824 } 2000 _writeChars(s.toCharArray(), 0, s.length()); 1825 2001 } 1826 2002 catch (NullPointerException e) … … 1830 2006 else 1831 2007 throw e; 1832 }1833 catch (IOException e)1834 {1835 error(new StreamError(this, e));1836 2008 } 1837 2009 } … … 1847 2019 try 1848 2020 { 1849 writer.write(s); 1850 writer.write('\n'); 1851 writer.flush(); 1852 charPos = 0; 2021 _writeString(s); 2022 _writeChar('\n'); 1853 2023 } 1854 2024 catch (NullPointerException e) … … 1856 2026 // writer is null 1857 2027 streamNotCharacterOutputStream(); 1858 }1859 catch (IOException e)1860 {1861 error(new StreamError(this, e));1862 2028 } 1863 2029 } … … 1873 2039 try 1874 2040 { 1875 return in.read(); // Reads an 8-bit byte. 2041 int n = in.read(); 2042 if (n < 0) 2043 pastEnd = true; 2044 2045 return n; // Reads an 8-bit byte. 1876 2046 } 1877 2047 catch (IOException e) … … 1934 2104 if (reader != null) 1935 2105 { 1936 while (_charReady()) 1937 _readChar(); 2106 int c = 0; 2107 while (_charReady() && (c >= 0)) 2108 c = _readChar(); 1938 2109 } 1939 2110 else if (in != null) … … 1941 2112 try 1942 2113 { 2114 int n = 0; 1943 2115 while (in.available() > 0) 1944 in.read(); 2116 n = in.read(); 2117 2118 if (n < 0) 2119 pastEnd = true; 1945 2120 } 1946 2121 catch (IOException e) … … 2007 2182 writer.write(sw.toString()); 2008 2183 writer.write('\n'); 2184 lastChar = '\n'; 2009 2185 writer.flush(); 2010 2186 charPos = 0; -
trunk/j/src/org/armedbear/lisp/StringInputStream.java
r11391 r11434 34 34 package org.armedbear.lisp; 35 35 36 import java.io.StringReader; 37 36 38 public final class StringInputStream extends Stream 37 39 { 38 final String s; 39 final int start; 40 final int end; 41 40 private final StringReader stringReader; 41 private final int start; 42 42 43 public StringInputStream(String s) 43 44 { … … 53 54 { 54 55 elementType = Symbol.CHARACTER; 55 isInputStream = true; 56 isOutputStream = false; 57 isCharacterStream = true; 58 isBinaryStream = false; 59 this.s = s; 56 setExternalFormat(keywordDefault); 57 eolStyle = EolStyle.RAW; 58 60 59 this.start = start; 61 this.end = end; 62 offset = start; 60 61 stringReader = new StringReader(s.substring(start, end)); 62 initAsCharacterInputStream(stringReader); 63 63 } 64 64 65 @Override 65 66 public LispObject typeOf() 66 67 { … … 68 69 } 69 70 71 @Override 70 72 public LispObject classOf() 71 73 { … … 73 75 } 74 76 77 @Override 75 78 public LispObject typep(LispObject type) throws ConditionThrowable 76 79 { … … 86 89 } 87 90 88 public LispObject close(LispObject abort) throws ConditionThrowable 89 { 90 setOpen(false); 91 return T; 92 } 93 94 public LispObject listen() 95 { 96 return offset < end ? T : NIL; 97 } 98 99 protected int _readChar() 100 { 101 if (offset >= end) 102 return -1; 103 int n = s.charAt(offset); 104 ++offset; 105 if (n == '\n') 106 ++lineNumber; 107 return n; 108 } 109 110 protected void _unreadChar(int n) 111 { 112 if (offset > start) { 113 --offset; 114 if (n == '\n') 115 --lineNumber; 116 } 117 } 118 119 protected boolean _charReady() 120 { 121 return true; 122 } 123 91 @Override 124 92 public String toString() 125 93 { … … 127 95 } 128 96 97 @Override 98 public int getOffset() { 99 return start + super.getOffset(); 100 } 101 129 102 // ### make-string-input-stream 130 103 // make-string-input-stream string &optional start end => string-stream … … 132 105 new Primitive("make-string-input-stream", "string &optional start end") 133 106 { 107 @Override 134 108 public LispObject execute(LispObject arg) throws ConditionThrowable 135 109 { … … 137 111 } 138 112 113 @Override 139 114 public LispObject execute(LispObject first, LispObject second) 140 115 throws ConditionThrowable … … 145 120 } 146 121 122 @Override 147 123 public LispObject execute(LispObject first, LispObject second, 148 124 LispObject third) … … 162 138 new Primitive("string-input-stream-current", PACKAGE_EXT, true, "stream") 163 139 { 140 @Override 164 141 public LispObject execute(LispObject arg) throws ConditionThrowable 165 142 { -
trunk/j/src/org/armedbear/lisp/StringOutputStream.java
r11391 r11434 48 48 { 49 49 this.elementType = elementType; 50 isInputStream = false; 51 isOutputStream = true; 52 isCharacterStream = true; 53 isBinaryStream = false; 54 setWriter(stringWriter = new StringWriter()); 50 this.eolStyle = EolStyle.RAW; 51 initAsCharacterOutputStream(stringWriter = new StringWriter()); 55 52 } 56 53 54 @Override 57 55 public LispObject typeOf() 58 56 { … … 60 58 } 61 59 60 @Override 62 61 public LispObject classOf() 63 62 { … … 65 64 } 66 65 66 @Override 67 67 public LispObject typep(LispObject type) throws ConditionThrowable 68 68 { … … 78 78 } 79 79 80 public void _writeChar(char c) throws ConditionThrowable 81 { 82 if (elementType == NIL) 83 writeError(); 84 super._writeChar(c); 85 } 86 87 public void _writeChars(char[] chars, int start, int end) 88 throws ConditionThrowable 89 { 90 if (elementType == NIL) 91 writeError(); 92 super._writeChars(chars, start, end); 93 } 94 95 public void _writeString(String s) throws ConditionThrowable 96 { 97 if (elementType == NIL) 98 writeError(); 99 super._writeString(s); 100 } 101 102 public void _writeLine(String s) throws ConditionThrowable 103 { 104 if (elementType == NIL) 105 writeError(); 106 super._writeLine(s); 107 } 108 109 private void writeError() throws ConditionThrowable 110 { 111 error(new TypeError("Attempt to write to a string output stream of element type NIL.")); 112 } 113 80 @Override 114 81 protected long _getFilePosition() throws ConditionThrowable 115 82 { 116 83 if (elementType == NIL) 117 84 return 0; 118 return stringWriter. toString().length();85 return stringWriter.getBuffer().length(); 119 86 } 120 87 … … 129 96 } 130 97 98 @Override 131 99 public String toString() 132 100 { … … 140 108 "element-type") 141 109 { 110 @Override 142 111 public LispObject execute(LispObject arg) throws ConditionThrowable 143 112 { … … 151 120 new Primitive("get-output-stream-string", "string-output-stream") 152 121 { 122 @Override 153 123 public LispObject execute(LispObject arg) throws ConditionThrowable 154 124 { -
trunk/j/src/org/armedbear/lisp/open.lisp
r11391 r11434 107 107 (if-does-not-exist nil if-does-not-exist-given) 108 108 (external-format :default)) 109 (declare (ignore external-format)) ; FIXME109 ; (declare (ignore external-format)) ; FIXME 110 110 (setf element-type (case element-type 111 111 ((character base-char) … … 144 144 :format-control "The file ~S does not exist." 145 145 :format-arguments (list namestring))))) 146 (make-file-stream pathname namestring element-type :input nil ))146 (make-file-stream pathname namestring element-type :input nil external-format)) 147 147 (:probe 148 148 (case if-does-not-exist … … 158 158 ;; not yet exist." See java.io.File.createNewFile(). 159 159 (create-new-file namestring))) 160 (let ((stream (make-file-stream pathname namestring element-type :input nil))) 160 (let ((stream (make-file-stream pathname namestring element-type 161 :input nil external-format))) 161 162 (when stream 162 163 (close stream)) … … 205 206 :format-control "Option not supported: ~S." 206 207 :format-arguments (list if-exists)))) 207 (let ((stream (make-file-stream pathname namestring element-type direction if-exists))) 208 (let ((stream (make-file-stream pathname namestring element-type 209 direction if-exists external-format))) 208 210 (unless stream 209 211 (error 'file-error -
trunk/j/src/org/armedbear/lisp/socket.lisp
r11391 r11434 32 32 (in-package "SYSTEM") 33 33 34 (defun get-socket-stream (socket &key (element-type 'character)) 35 ":ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8); the default is CHARACTER." 34 (defun get-socket-stream (socket &key (element-type 'character) (external-format :default)) 35 ":ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8); the default is CHARACTER. 36 EXTERNAL-FORMAT must be of the same format as specified for OPEN." 36 37 (cond ((eq element-type 'character)) 37 38 ((equal element-type '(unsigned-byte 8))) … … 40 41 :format-control 41 42 ":ELEMENT-TYPE must be CHARACTER or (UNSIGNED-BYTE 8)."))) 42 (%socket-stream socket element-type ))43 (%socket-stream socket element-type external-format)) 43 44 44 45 (defun make-socket (host port) -
trunk/j/src/org/armedbear/lisp/socket_stream.java
r11391 r11434 41 41 private socket_stream() 42 42 { 43 super("%socket-stream", PACKAGE_SYS, false, "socket element-type ");43 super("%socket-stream", PACKAGE_SYS, false, "socket element-type external-format"); 44 44 } 45 45 46 public LispObject execute(LispObject first, LispObject second )46 public LispObject execute(LispObject first, LispObject second, LispObject third) 47 47 throws ConditionThrowable 48 48 { … … 51 51 try { 52 52 Stream in = 53 new Stream(socket.getInputStream(), elementType );53 new Stream(socket.getInputStream(), elementType, third); 54 54 Stream out = 55 new Stream(socket.getOutputStream(), elementType );55 new Stream(socket.getOutputStream(), elementType, third); 56 56 return new SocketStream(socket, in, out); 57 57 }
Note: See TracChangeset
for help on using the changeset viewer.