001: /*
002: * Copyright (c) 2000 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.nbio;
026:
027: import java.io.*;
028:
029: /**
030: * Package-internal class implementing NonblockingInputStream for
031: * nonblocking sockets.
032: */
033: class NonblockingSocketInputStream extends NonblockingInputStream {
034:
035: private NBIOFileDescriptor fd;
036: private boolean eof;
037: private NonblockingSocketImpl impl;
038: private byte temp[] = new byte[1];
039:
040: private static final int SKIPBUFLEN = 4096;
041:
042: /* Non-blocking read on the underlying socket.
043: * Returns -1 if EOF has been reached, 0 if no data is available, otherwise
044: * the number of bytes read.
045: */
046: private native int nbSocketRead(byte b[], int off, int len)
047: throws IOException;
048:
049: NonblockingSocketInputStream(NonblockingSocketImpl impl) {
050: fd = impl.getFileDescriptor();
051: this .impl = impl;
052: }
053:
054: /**
055: * Perform a <b>blocking</b> read of one byte from this input stream.
056: * Returns -1 if the end of the stream has been reached.
057: * Use nbRead() to perform a non-blocking read of one byte.
058: */
059: public int read() throws IOException {
060: if (eof)
061: return -1;
062: int n;
063: // Spin until we read a byte -- ugly
064: while ((n = read(temp, 0, 1)) == 0)
065: ;
066: if (n < 0) {
067: eof = true;
068: return -1;
069: }
070: return temp[0] & 0xff;
071: }
072:
073: /**
074: * Perform a non-blocking read of one byte from this input stream.
075: * Returns -1 if no data is available, or throws an EOFException if the
076: * end of the stream has been reached. Use read() to perform a blocking
077: * read of one byte.
078: */
079: public int nbRead() throws IOException {
080: if (eof)
081: throw new EOFException("EOF on " + toString());
082: int n = read(temp, 0, 1);
083: if (n == 0)
084: return -1;
085: if (n < 0) {
086: eof = true;
087: throw new EOFException("EOF on " + toString());
088: }
089: return temp[0] & 0xff;
090: }
091:
092: /**
093: * Perform a non-blocking read of up to <code>b.length</code> bytes
094: * from the underlying stream.
095: *
096: * @return The total number of bytes read into the buffer, 0 if
097: * no data was available, or -1 if the end of the stream has
098: * been reached.
099: *
100: */
101: public int read(byte b[]) throws IOException {
102: return read(b, 0, b.length);
103: }
104:
105: /**
106: * Perform a non-blocking read of up to <code>len</code> bytes from the
107: * underlying stream into the byte array <code>b</code> starting at offset
108: * <code>off</code>.
109: *
110: * @return The total number of bytes read into the buffer, 0 if
111: * no data was available, or -1 if the end of the stream has
112: * been reached.
113: */
114: public int read(byte b[], int off, int len) throws IOException {
115: if (eof)
116: return -1;
117: int n = nbSocketRead(b, off, len);
118: if (n < 0) {
119: eof = true;
120: return -1;
121: }
122: return n;
123: }
124:
125: /**
126: * Skip n bytes of input. This is a <b>blocking</b> operation.
127: */
128: public long skip(long n) throws IOException {
129: if (n <= 0)
130: return 0;
131: int buflen = (int) Math.min(SKIPBUFLEN, n);
132: byte data[] = new byte[buflen];
133: while (n > 0) {
134: int r = read(data, 0, (int) Math.min((long) buflen, n));
135: if (r < 0)
136: break;
137: n -= r;
138: }
139: return n;
140: }
141:
142: public int available() throws IOException {
143: return impl.available();
144: }
145:
146: public void close() throws IOException {
147: impl.close();
148: }
149:
150: }
|