-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Restore minimal part of old IO for jossl 0.9.5 to work.
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
- 9.1.2.0
- 9.1.1.0
- 9.1.0.0
- 9.0.5.0
- 9.0.4.0
- 9.0.3.0
- 9.0.1.0
- 9.0.0.0
- 9.0.0.0.rc2
- 9.0.0.0.rc1
- 9.0.0.0.pre2
- 9.0.0.0.pre1
Showing
5 changed files
with
3,105 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
356 changes: 356 additions & 0 deletions
356
core/src/main/java/org/jruby/util/io/CRLFStreamWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,356 @@ | ||
package org.jruby.util.io; | ||
|
||
import java.io.EOFException; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.Channel; | ||
import org.jcodings.Encoding; | ||
import org.jcodings.specific.UTF16BEEncoding; | ||
import org.jcodings.specific.UTF16LEEncoding; | ||
import org.jruby.Ruby; | ||
import org.jruby.platform.Platform; | ||
import org.jruby.util.ByteList; | ||
|
||
/** | ||
* Wrapper around Stream that packs and unpacks LF <=> CRLF. | ||
* @author nicksieger | ||
*/ | ||
public class CRLFStreamWrapper implements Stream { | ||
private final Stream stream; | ||
private final boolean isWindows; | ||
private boolean binmode = false; | ||
private static final int CR = 13; | ||
private static final int LF = 10; | ||
|
||
public CRLFStreamWrapper(Stream stream) { | ||
this.stream = stream; | ||
// To differentiate between textmode and windows in how we handle crlf. | ||
this.isWindows = Platform.IS_WINDOWS; | ||
} | ||
|
||
public ChannelDescriptor getDescriptor() { | ||
return stream.getDescriptor(); | ||
} | ||
|
||
public void clearerr() { | ||
stream.clearerr(); | ||
} | ||
|
||
@Override | ||
public ByteBuffer getBuffer() { | ||
return stream.getBuffer(); | ||
} | ||
|
||
public ModeFlags getModes() { | ||
return stream.getModes(); | ||
} | ||
|
||
public void setModes(ModeFlags modes) { | ||
stream.setModes(modes); | ||
} | ||
|
||
public boolean isSync() { | ||
return stream.isSync(); | ||
} | ||
|
||
public void setSync(boolean sync) { | ||
stream.setSync(sync); | ||
} | ||
|
||
@Override | ||
public int bufferedAvailable() { | ||
return stream.bufferedAvailable(); | ||
} | ||
|
||
public void setBinmode() { | ||
binmode = true; | ||
stream.setBinmode(); | ||
} | ||
|
||
public boolean isBinmode() { | ||
return binmode; | ||
} | ||
|
||
public boolean isAutoclose() { | ||
return stream.isAutoclose(); | ||
} | ||
|
||
public void setAutoclose(boolean autoclose) { | ||
stream.setAutoclose(autoclose); | ||
} | ||
|
||
public ByteList fgets(ByteList separatorString) throws IOException, BadDescriptorException, EOFException { | ||
return convertCRLFToLF(stream.fgets(separatorString)); | ||
} | ||
|
||
public ByteList readall() throws IOException, BadDescriptorException, EOFException { | ||
return convertCRLFToLF(stream.readall()); | ||
} | ||
|
||
public int getline(ByteList dst, byte terminator) throws IOException, BadDescriptorException { | ||
if (binmode) { | ||
return stream.getline(dst, terminator); | ||
} | ||
|
||
ByteList intermediate = new ByteList(); | ||
int result = stream.getline(intermediate, terminator); | ||
convertCRLFToLF(intermediate, dst); | ||
return result; | ||
} | ||
|
||
public int getline(ByteList dst, byte terminator, long limit) throws IOException, BadDescriptorException { | ||
if (binmode) { | ||
return stream.getline(dst, terminator, limit); | ||
} | ||
|
||
ByteList intermediate = new ByteList(); | ||
int result = stream.getline(intermediate, terminator, limit); | ||
convertCRLFToLF(intermediate, dst); | ||
return result; | ||
} | ||
|
||
public ByteList fread(int number) throws IOException, BadDescriptorException, EOFException { | ||
if (number == 0) { | ||
if (stream.feof()) { | ||
return null; | ||
} else { | ||
return new ByteList(0); | ||
} | ||
} | ||
boolean eof = false; | ||
ByteList bl = new ByteList(number > ChannelStream.BUFSIZE ? ChannelStream.BUFSIZE : number); | ||
for (int i = 0; i < number; i++) { | ||
int c = fgetc(); | ||
if (c == -1) { | ||
eof = true; | ||
break; | ||
} | ||
bl.append(c); | ||
} | ||
if (eof && bl.length() == 0) { | ||
return null; | ||
} | ||
return bl; | ||
} | ||
|
||
public int fwrite(ByteList string) throws IOException, BadDescriptorException { | ||
if (isWindows) return stream.fwrite(convertLFToCRLF(string)); | ||
|
||
return stream.fwrite(convertCRLFToLF(string)); | ||
} | ||
|
||
public int fgetc() throws IOException, BadDescriptorException, EOFException { | ||
int c = stream.fgetc(); | ||
if (!binmode && c == CR) { | ||
c = stream.fgetc(); | ||
if (c != LF) { | ||
stream.ungetc(c); | ||
return CR; | ||
} | ||
} | ||
return c; | ||
} | ||
|
||
public int ungetc(int c) { | ||
return stream.ungetc(c); | ||
} | ||
|
||
public void fputc(int c) throws IOException, BadDescriptorException { | ||
if (!binmode && c == LF) { | ||
stream.fputc(CR); | ||
} | ||
stream.fputc(c); | ||
} | ||
|
||
public ByteList read(int number) throws IOException, BadDescriptorException, EOFException { | ||
return convertCRLFToLF(stream.read(number)); | ||
} | ||
|
||
public void fclose() throws IOException, BadDescriptorException { | ||
stream.fclose(); | ||
} | ||
|
||
public int fflush() throws IOException, BadDescriptorException { | ||
return stream.fflush(); | ||
} | ||
|
||
public void sync() throws IOException, BadDescriptorException { | ||
stream.sync(); | ||
} | ||
|
||
public boolean feof() throws IOException, BadDescriptorException { | ||
return stream.feof(); | ||
} | ||
|
||
public long fgetpos() throws IOException, PipeException, BadDescriptorException, InvalidValueException { | ||
return stream.fgetpos(); | ||
} | ||
|
||
public void lseek(long offset, int type) throws IOException, InvalidValueException, PipeException, BadDescriptorException { | ||
stream.lseek(offset, type); | ||
} | ||
|
||
public void ftruncate(long newLength) throws IOException, PipeException, InvalidValueException, BadDescriptorException { | ||
stream.ftruncate(newLength); | ||
} | ||
|
||
public int ready() throws IOException { | ||
return stream.ready(); | ||
} | ||
|
||
public void waitUntilReady() throws IOException, InterruptedException { | ||
stream.waitUntilReady(); | ||
} | ||
|
||
public boolean readDataBuffered() { | ||
return stream.readDataBuffered(); | ||
} | ||
|
||
public boolean writeDataBuffered() { | ||
return stream.writeDataBuffered(); | ||
} | ||
|
||
public InputStream newInputStream() { | ||
return stream.newInputStream(); | ||
} | ||
|
||
public OutputStream newOutputStream() { | ||
return stream.newOutputStream(); | ||
} | ||
|
||
public boolean isBlocking() { | ||
return stream.isBlocking(); | ||
} | ||
|
||
public void setBlocking(boolean blocking) throws IOException { | ||
stream.setBlocking(blocking); | ||
} | ||
|
||
public void freopen(Ruby runtime, String path, ModeFlags modes) throws DirectoryAsFileException, IOException, InvalidValueException, PipeException, BadDescriptorException { | ||
stream.freopen(runtime, path, modes); | ||
} | ||
|
||
private ByteList convertCRLFToLF(ByteList input) { | ||
if (input == null || binmode) return input; | ||
|
||
ByteList result = new ByteList(); | ||
convertCRLFToLF(input, result); | ||
return result; | ||
} | ||
|
||
// FIXME: Horrific hack until we properly setup transcoding support of cr/lf logic in 1.9 proper. This class | ||
// is going away in 9k and the LE/BE logic is never used by 1.8 support. | ||
|
||
// I could not find any way in MRI to exercise this logic....endless needs | ||
// binmode set (which obviously would not work here). Leaving it for now | ||
// since I will likely be either doubling down on new knowledge for 1.7.2 | ||
// or ripping all this out when we have real transcoding logic ported | ||
// properly | ||
// private int skipCROfLF(ByteList src, int i, int c) { | ||
// Encoding encoding = src.getEncoding(); | ||
// int length = src.length(); | ||
// | ||
// if (encoding == UTF16BEEncoding.INSTANCE) { | ||
// if (i + 3 < length && c == 0 && src.get(i + 1) == CR && | ||
// src.get(i + 2) == 0 && src.get(i + 3) == LF) { | ||
// return i + 1; | ||
// } | ||
// } else if (encoding == UTF16LEEncoding.INSTANCE) { | ||
// if (i + 3 < length && c == CR && src.get(i + 1) == 0 && | ||
// src.get(i + 2) == LF && src.get(i + 3) == 0) { | ||
// return i + 1; | ||
// } | ||
// } else if (c == CR && i + 1 < length && src.get(i + 1) == LF) { | ||
// return i; | ||
// } | ||
// | ||
// return -1; | ||
// } | ||
// | ||
// private void convertCRLFToLF(ByteList src, ByteList dst) { | ||
// for (int i = 0; i < src.length(); i++) { | ||
// int b = src.get(i); | ||
// int j = skipCROfLF(src, i, b); | ||
// if (j != -1) i = j; | ||
// | ||
// dst.append(b); | ||
// } | ||
// } | ||
|
||
|
||
private void convertCRLFToLF(ByteList src, ByteList dst) { | ||
for (int i = 0; i < src.length(); i++) { | ||
int b = src.get(i); | ||
if (b == CR && i + 1 < src.length() && src.get(i + 1) == LF) { | ||
continue; | ||
} | ||
dst.append(b); | ||
} | ||
} | ||
|
||
final byte[] CRBYTES = new byte[] { CR }; | ||
final byte[] CRLEBYTES = new byte[] { CR, 0}; | ||
final byte[] CRBEBYTES = new byte[] { 0, CR }; | ||
|
||
private byte[] crBytes(Encoding encoding) { | ||
if (encoding == UTF16BEEncoding.INSTANCE) return CRBEBYTES; | ||
if (encoding == UTF16LEEncoding.INSTANCE) return CRLEBYTES; | ||
|
||
return CRBYTES; | ||
} | ||
|
||
final byte[] LFBYTES = new byte[] { LF }; | ||
final byte[] LFLEBYTES = new byte[] { LF, 0 }; | ||
final byte[] LFBEBYTES = new byte[] { 0, LF }; | ||
|
||
private byte[] lfBytes(Encoding encoding) { | ||
if (encoding == UTF16BEEncoding.INSTANCE) return LFBEBYTES; | ||
if (encoding == UTF16LEEncoding.INSTANCE) return LFLEBYTES; | ||
|
||
return LFBYTES; | ||
} | ||
|
||
private ByteList convertLFToCRLF(ByteList bs) { | ||
if (bs == null || binmode) return bs; | ||
|
||
byte[] crBytes = crBytes(bs.getEncoding()); | ||
byte[] lfBytes = lfBytes(bs.getEncoding()); | ||
|
||
int p = bs.getBegin(); | ||
int end = p + bs.getRealSize(); | ||
byte[]bytes = bs.getUnsafeBytes(); | ||
Encoding enc = bs.getEncoding(); | ||
|
||
ByteList result = new ByteList(); | ||
int lastWrittenIndex = p; | ||
while (p < end) { | ||
int c = enc.mbcToCode(bytes, p, end); | ||
int cLength = enc.codeToMbcLength(c); | ||
|
||
if (c == LF) { | ||
result.append(bytes, lastWrittenIndex, p - lastWrittenIndex); | ||
result.append(crBytes); | ||
result.append(lfBytes); | ||
lastWrittenIndex = p + cLength; | ||
} | ||
|
||
p += cLength; | ||
} | ||
|
||
if (lastWrittenIndex < end) { | ||
result.append(bytes, lastWrittenIndex, end - lastWrittenIndex); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
public Channel getChannel() { | ||
return stream.getChannel(); | ||
} | ||
|
||
public final int refillBuffer() throws IOException { | ||
return stream.refillBuffer(); | ||
} | ||
} |
861 changes: 861 additions & 0 deletions
861
core/src/main/java/org/jruby/util/io/ChannelDescriptor.java
Large diffs are not rendered by default.
Oops, something went wrong.
1,699 changes: 1,699 additions & 0 deletions
1,699
core/src/main/java/org/jruby/util/io/ChannelStream.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/***** BEGIN LICENSE BLOCK ***** | ||
* Version: EPL 1.0/GPL 2.0/LGPL 2.1 | ||
* | ||
* The contents of this file are subject to the Eclipse Public | ||
* License Version 1.0 (the "License"); you may not use this file | ||
* except in compliance with the License. You may obtain a copy of | ||
* the License at http://www.eclipse.org/legal/epl-v10.html | ||
* | ||
* Software distributed under the License is distributed on an "AS | ||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
* implied. See the License for the specific language governing | ||
* rights and limitations under the License. | ||
* | ||
* Copyright (C) 2008-2009 The JRuby Community <www.jruby.org> | ||
* | ||
* Alternatively, the contents of this file may be used under the terms of | ||
* either of the GNU General Public License Version 2 or later (the "GPL"), | ||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
* in which case the provisions of the GPL or the LGPL are applicable instead | ||
* of those above. If you wish to allow use of your version of this file only | ||
* under the terms of either the GPL or the LGPL, and not to allow others to | ||
* use your version of this file under the terms of the EPL, indicate your | ||
* decision by deleting the provisions above and replace them with the notice | ||
* and other provisions required by the GPL or the LGPL. If you do not delete | ||
* the provisions above, a recipient may use your version of this file under | ||
* the terms of any one of the EPL, the GPL or the LGPL. | ||
***** END LICENSE BLOCK *****/ | ||
package org.jruby.util.io; | ||
|
||
import java.io.EOFException; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.Channel; | ||
import org.jruby.util.ByteList; | ||
import org.jruby.Ruby; | ||
|
||
/** | ||
*/ | ||
public interface Stream { | ||
static final int SEEK_SET = 0; | ||
static final int SEEK_CUR = 1; | ||
static final int SEEK_END = 2; | ||
|
||
// We use a highly uncommon string to represent the paragraph delimiter (100% soln not worth it) | ||
static final ByteList PARAGRAPH_DELIMETER = ByteList.create("PARAGRPH_DELIM_MRK_ER"); | ||
|
||
static final ByteList PARAGRAPH_SEPARATOR = ByteList.create("\n\n"); | ||
|
||
ChannelDescriptor getDescriptor(); | ||
|
||
void clearerr(); | ||
|
||
ByteBuffer getBuffer(); | ||
|
||
ModeFlags getModes(); | ||
|
||
void setModes(ModeFlags modeFlags); | ||
|
||
boolean isSync(); | ||
|
||
void setSync(boolean sync); | ||
|
||
int bufferedAvailable(); | ||
|
||
int refillBuffer() throws IOException; | ||
|
||
ByteList fgets(ByteList separatorString) throws IOException, BadDescriptorException, EOFException; | ||
ByteList readall() throws IOException, BadDescriptorException, EOFException; | ||
|
||
|
||
/** | ||
* Read all bytes up to and including a terminator byte. | ||
* | ||
* <p>If the terminator byte is found, it will be the last byte in the output buffer.</p> | ||
* | ||
* @param dst The output buffer. | ||
* @param terminator The byte to terminate reading. | ||
* @return The number of bytes read, or -1 if EOF is reached. | ||
* | ||
* @throws java.io.IOException | ||
* @throws org.jruby.util.io.BadDescriptorException | ||
*/ | ||
int getline(ByteList dst, byte terminator) throws IOException, BadDescriptorException; | ||
|
||
/** | ||
* Reads all bytes up to and including a terminator byte or until limit is reached. | ||
* | ||
* <p>If the terminator byte is found, it will be the last byte in the output buffer.</p> | ||
* | ||
* @param dst The output buffer. | ||
* @param terminator The byte to terminate reading. | ||
* @param limit the number of bytes to read unless EOF or terminator is found | ||
* @return The number of bytes read, or -1 if EOF is reached. | ||
* | ||
* @throws java.io.IOException | ||
* @throws org.jruby.util.io.BadDescriptorException | ||
*/ | ||
int getline(ByteList dst, byte terminator, long limit) throws IOException, BadDescriptorException; | ||
|
||
// TODO: We overflow on large files...We could increase to long to limit | ||
// this, but then the impl gets more involved since java io APIs based on | ||
// int (means we have to chunk up a long into a series of int ops). | ||
|
||
ByteList fread(int number) throws IOException, BadDescriptorException, EOFException; | ||
int fwrite(ByteList string) throws IOException, BadDescriptorException; | ||
|
||
int fgetc() throws IOException, BadDescriptorException, EOFException; | ||
int ungetc(int c); | ||
void fputc(int c) throws IOException, BadDescriptorException; | ||
|
||
ByteList read(int number) throws IOException, BadDescriptorException, EOFException; | ||
|
||
void fclose() throws IOException, BadDescriptorException; | ||
int fflush() throws IOException, BadDescriptorException; | ||
|
||
/** | ||
* <p>Flush and sync all writes to the filesystem.</p> | ||
* | ||
* @throws IOException if the sync does not work | ||
*/ | ||
void sync() throws IOException, BadDescriptorException; | ||
|
||
/** | ||
* <p>Return true when at end of file (EOF).</p> | ||
* | ||
* @return true if at EOF; false otherwise | ||
* @throws IOException | ||
* @throws BadDescriptorException | ||
*/ | ||
boolean feof() throws IOException, BadDescriptorException; | ||
|
||
/** | ||
* <p>Get the current position within the file associated with this | ||
* handler.</p> | ||
* | ||
* @return the current position in the file. | ||
* @throws IOException | ||
* @throws PipeException ESPIPE (illegal seek) when not a file | ||
* | ||
*/ | ||
long fgetpos() throws IOException, PipeException, BadDescriptorException, InvalidValueException; | ||
|
||
/** | ||
* <p>Perform a seek based on pos(). </p> | ||
* @throws IOException | ||
* @throws PipeException | ||
* @throws InvalidValueException | ||
*/ | ||
void lseek(long offset, int type) throws IOException, InvalidValueException, PipeException, BadDescriptorException; | ||
void ftruncate(long newLength) throws IOException, PipeException, | ||
InvalidValueException, BadDescriptorException; | ||
|
||
/** | ||
* Implement IO#ready? as per io/wait in MRI. | ||
* returns non-nil if input available without blocking, or nil. | ||
*/ | ||
int ready() throws IOException; | ||
|
||
/** | ||
* Implement IO#wait as per io/wait in MRI. | ||
* waits until input available or timed out and returns self, or nil when EOF reached. | ||
* | ||
* The default implementation loops while ready returns 0. | ||
*/ | ||
void waitUntilReady() throws IOException, InterruptedException; | ||
|
||
boolean readDataBuffered(); | ||
boolean writeDataBuffered(); | ||
|
||
InputStream newInputStream(); | ||
|
||
OutputStream newOutputStream(); | ||
|
||
boolean isBlocking(); | ||
|
||
void setBlocking(boolean blocking) throws IOException; | ||
|
||
void freopen(Ruby runtime, String path, ModeFlags modes) throws DirectoryAsFileException, IOException, InvalidValueException, PipeException, BadDescriptorException; | ||
|
||
void setBinmode(); | ||
boolean isBinmode(); | ||
Channel getChannel(); | ||
|
||
boolean isAutoclose(); | ||
void setAutoclose(boolean autoclose); | ||
} |