mirror of
https://github.com/moparisthebest/mailiverse
synced 2024-12-01 12:32:15 -05:00
234 lines
8.3 KiB
Java
234 lines
8.3 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package java.io;
|
|
|
|
/**
|
|
* Reader is an Abstract class for reading Character Streams. Subclasses of
|
|
* Reader must implement the methods <code>read(char[], int, int)</code> and
|
|
* <code>close()</code>.
|
|
*
|
|
* @see Writer
|
|
*/
|
|
public abstract class Reader {
|
|
/**
|
|
* The object used to synchronize access to the reader.
|
|
*/
|
|
protected Object lock;
|
|
|
|
/**
|
|
* Constructs a new character stream Reader using <code>this</code> as the
|
|
* Object to synchronize critical regions around.
|
|
*/
|
|
protected Reader() {
|
|
super();
|
|
lock = this;
|
|
}
|
|
|
|
/**
|
|
* Constructs a new character stream Reader using <code>lock</code> as the
|
|
* Object to synchronize critical regions around.
|
|
*
|
|
* @param lock
|
|
* the <code>Object</code> to synchronize critical regions
|
|
* around.
|
|
*/
|
|
protected Reader(Object lock) {
|
|
if (lock == null) {
|
|
throw new NullPointerException();
|
|
}
|
|
this.lock = lock;
|
|
}
|
|
|
|
/**
|
|
* Close this Reader. This must be implemented by any concrete subclasses.
|
|
* The implementation should free any resources associated with the Reader.
|
|
*
|
|
* @throws IOException
|
|
* If an error occurs attempting to close this Reader.
|
|
*/
|
|
public abstract void close() throws IOException;
|
|
|
|
/**
|
|
* Set a Mark position in this Reader. The parameter <code>readLimit</code>
|
|
* indicates how many characters can be read before a mark is invalidated.
|
|
* Sending reset() will reposition the reader back to the marked position
|
|
* provided <code>readLimit</code> has not been surpassed.
|
|
* <p>
|
|
* This default implementation simply throws IOException and concrete
|
|
* subclasses must provide their own implementations.
|
|
*
|
|
* @param readLimit
|
|
* an int representing how many characters must be read before
|
|
* invalidating the mark.
|
|
*
|
|
* @throws IOException
|
|
* If an error occurs attempting mark this Reader.
|
|
*/
|
|
public void mark(int readLimit) throws IOException {
|
|
throw new IOException();
|
|
}
|
|
|
|
/**
|
|
* Answers a boolean indicating whether or not this Reader supports mark()
|
|
* and reset(). This class a default implementation which answers false.
|
|
*
|
|
* @return <code>true</code> if mark() and reset() are supported,
|
|
* <code>false</code> otherwise. This implementation returns
|
|
* <code>false</code>.
|
|
*/
|
|
public boolean markSupported() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Reads a single character from this reader and returns the result as an
|
|
* int. The 2 higher-order characters are set to 0. If the end of reader was
|
|
* encountered then return -1.
|
|
*
|
|
* @return the character read or -1 if end of reader.
|
|
*
|
|
* @throws IOException
|
|
* If the Reader is already closed or some other IO error
|
|
* occurs.
|
|
*/
|
|
public int read() throws IOException {
|
|
synchronized (lock) {
|
|
char charArray[] = new char[1];
|
|
if (read(charArray, 0, 1) != -1) {
|
|
return charArray[0];
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads characters from this Reader and stores them in the character array
|
|
* <code>buf</code> starting at offset 0. Returns the number of characters
|
|
* actually read or -1 if the end of reader was encountered.
|
|
*
|
|
* @param buf
|
|
* character array to store the read characters
|
|
* @return how many characters were successfully read in or else -1 if the
|
|
* end of the reader was detected.
|
|
*
|
|
* @throws IOException
|
|
* If the Reader is already closed or some other IO error
|
|
* occurs.
|
|
*/
|
|
public int read(char buf[]) throws IOException {
|
|
return read(buf, 0, buf.length);
|
|
}
|
|
|
|
/**
|
|
* Reads at most <code>count</code> characters from this Reader and stores
|
|
* them at <code>offset</code> in the character array <code>buf</code>.
|
|
* Returns the number of characters actually read or -1 if the end of reader
|
|
* was encountered.
|
|
*
|
|
* @param buf
|
|
* character array to store the read characters
|
|
* @param offset
|
|
* offset in buf to store the read characters
|
|
* @param count
|
|
* how many characters should be read in
|
|
* @return how many characters were successfully read in or else -1 if the
|
|
* end of the reader was detected.
|
|
*
|
|
* @throws IOException
|
|
* If the Reader is already closed or some other IO error
|
|
* occurs.
|
|
*/
|
|
public abstract int read(char buf[], int offset, int count)
|
|
throws IOException;
|
|
|
|
/**
|
|
* Answers a <code>boolean</code> indicating whether or not this Reader is
|
|
* ready to be read without blocking. If the result is <code>true</code>,
|
|
* the next <code>read()</code> will not block. If the result is
|
|
* <code>false</code> this Reader may or may not block when
|
|
* <code>read()</code> is sent.
|
|
*
|
|
* @return <code>true</code> if the receiver will not block when
|
|
* <code>read()</code> is called, <code>false</code> if unknown
|
|
* or blocking will occur.
|
|
*
|
|
* @throws IOException
|
|
* If the Reader is already closed or some other IO error
|
|
* occurs.
|
|
*/
|
|
public boolean ready() throws IOException {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Reset this Readers position to the last <code>mark()</code> location.
|
|
* Invocations of <code>read()/skip()</code> will occur from this new
|
|
* location. If this Reader was not marked, the implementation of
|
|
* <code>reset()</code> is implementation specific. See the comment for
|
|
* the specific Reader subclass for implementation details. The default
|
|
* action is to throw <code>IOException</code>.
|
|
*
|
|
* @throws IOException
|
|
* If a problem occured or the receiver does not support
|
|
* <code>mark()/reset()</code>.
|
|
*/
|
|
public void reset() throws IOException {
|
|
throw new IOException();
|
|
}
|
|
|
|
/**
|
|
* Skips <code>count</code> number of characters in this Reader.
|
|
* Subsequent <code>read()</code>'s will not return these characters
|
|
* unless <code>reset()</code> is used. This method may perform multiple
|
|
* reads to read <code>count</code> characters.
|
|
*
|
|
* @param count
|
|
* how many characters should be passed over
|
|
* @return how many characters were successfully passed over
|
|
*
|
|
* @throws IOException
|
|
* If the Reader is closed when the call is made or if an IO
|
|
* error occurs during the operation.
|
|
*/
|
|
public long skip(long count) throws IOException {
|
|
if (count < 0) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
synchronized (lock) {
|
|
long skipped = 0;
|
|
int toRead = count < 512 ? (int) count : 512;
|
|
char charsSkipped[] = new char[toRead];
|
|
while (skipped < count) {
|
|
int read = read(charsSkipped, 0, toRead);
|
|
if (read == -1) {
|
|
return skipped;
|
|
}
|
|
skipped += read;
|
|
if (read < toRead) {
|
|
return skipped;
|
|
}
|
|
if (count - skipped < toRead) {
|
|
toRead = (int) (count - skipped);
|
|
}
|
|
}
|
|
return skipped;
|
|
}
|
|
}
|
|
|
|
|
|
} |