314 lines
7.8 KiB
Java
314 lines
7.8 KiB
Java
/*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (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.mozilla.org/NPL/
|
|
*
|
|
* 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.
|
|
*
|
|
* The Original Code is the Netscape Messaging Access SDK Version 3.5 code,
|
|
* released on or about June 15, 1998. *
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1997 and 1998 Netscape Communications Corporation
|
|
* (http://home.netscape.com/misc/trademarks.html)
|
|
*/
|
|
|
|
package netscape.messaging.mime;
|
|
|
|
import java.io.InputStream;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* Mutable subclass of ByteString.
|
|
*/
|
|
public final class ByteBuffer extends ByteString implements Cloneable {
|
|
boolean wasCloned;
|
|
|
|
/**
|
|
* Construct a ByteBuffer of the given capacity
|
|
*/
|
|
public ByteBuffer (int capacity) {
|
|
super();
|
|
buffer = new byte[capacity];
|
|
wasCloned = false;
|
|
}
|
|
|
|
/**
|
|
* Construct a ByteBuffer of the given capacity
|
|
*/
|
|
public ByteBuffer (ByteString bs) {
|
|
super();
|
|
buffer = bs.buffer;
|
|
hi = bs.hi;
|
|
lo = bs.lo;
|
|
wasCloned = false;
|
|
}
|
|
|
|
/**
|
|
* Construct a ByteBuffer of the given capacity
|
|
* no clone version
|
|
*/
|
|
public ByteBuffer (byte[] b)
|
|
{
|
|
super();
|
|
buffer = b;
|
|
hi = b.length;
|
|
lo = 0;
|
|
wasCloned = false;
|
|
}
|
|
|
|
/**
|
|
* Construct a ByteBuffer of the given capacity
|
|
* no clone version
|
|
*/
|
|
public ByteBuffer (byte[] b, int len)
|
|
{
|
|
super();
|
|
buffer = b;
|
|
hi = len;
|
|
lo = 0;
|
|
wasCloned = false;
|
|
}
|
|
|
|
/**/
|
|
|
|
/**
|
|
* Ensure there is capacity for appending num bytes.
|
|
*/
|
|
private final void ensureCapacity (int num) {
|
|
byte[] newBuffer = null;
|
|
int newsize;
|
|
|
|
if (hi == lo) erase();
|
|
if (buffer.length - hi >= num) return;
|
|
|
|
newsize = num + (hi-lo);
|
|
if (newsize*2 < buffer.length) {
|
|
newsize = buffer.length;
|
|
if (!wasCloned) newBuffer = buffer;
|
|
}
|
|
else if (newsize < buffer.length*2) newsize = buffer.length*2;
|
|
|
|
if (newBuffer == null)
|
|
newBuffer = new byte[newsize];
|
|
|
|
System.arraycopy(buffer, lo, newBuffer, 0, hi-lo );
|
|
|
|
buffer = newBuffer;
|
|
wasCloned = false;
|
|
hi -= lo;
|
|
lo = 0;
|
|
}
|
|
|
|
/**
|
|
* Append a ByteString. Not MT-safe.
|
|
*/
|
|
public final void append (ByteString that) {
|
|
ensureCapacity(that.size());
|
|
System.arraycopy(that.buffer, that.lo, this.buffer, this.hi, that.size());
|
|
this.hi += that.size();
|
|
}
|
|
|
|
/**
|
|
* Append a substring of a ByteString. Not MT-safe.
|
|
*/
|
|
public final void append (ByteString that, int start) {
|
|
int substrSize = that.size() - start;
|
|
|
|
if (substrSize < 0) throw new IndexOutOfBoundsException();
|
|
ensureCapacity(substrSize);
|
|
System.arraycopy(that.buffer, that.lo+start, this.buffer, this.hi,
|
|
substrSize);
|
|
this.hi += substrSize;
|
|
}
|
|
|
|
/**
|
|
* Append a substring of a ByteString. Not MT-safe.
|
|
*/
|
|
public final void append (ByteString that, int start, int finish) {
|
|
if (start > finish || finish > that.size())
|
|
throw new IndexOutOfBoundsException();
|
|
ensureCapacity(finish - start);
|
|
System.arraycopy(that.buffer, that.lo+start, this.buffer, this.hi, finish-start);
|
|
this.hi += (finish-start);
|
|
}
|
|
|
|
/**
|
|
* Append a byte[]. Not MT-safe.
|
|
*/
|
|
public final void append (byte[] that) {
|
|
ensureCapacity(that.length);
|
|
System.arraycopy(that, 0, this.buffer, this.hi, that.length);
|
|
this.hi += that.length;
|
|
}
|
|
|
|
/**
|
|
* Append a byte[]. Not MT-safe.
|
|
*/
|
|
public final void append (byte[] that, int len )
|
|
{
|
|
ensureCapacity(len);
|
|
System.arraycopy(that, 0, this.buffer, this.hi, len);
|
|
this.hi += len;
|
|
}
|
|
|
|
/**
|
|
* Add a long
|
|
*/
|
|
public final void append (long n) {
|
|
ensureCapacity(8);
|
|
for (int i=hi+8; --i>=hi; ) {
|
|
buffer[i] = (byte)(n & 0xff);
|
|
n >>= 8;
|
|
}
|
|
hi += 8;
|
|
}
|
|
|
|
/**
|
|
* Add an int
|
|
*/
|
|
public final void append (int n) {
|
|
ensureCapacity(4);
|
|
for (int i=hi+4; --i>=hi; ) {
|
|
buffer[i] = (byte)(n & 0xff);
|
|
n >>= 8;
|
|
}
|
|
hi += 4;
|
|
}
|
|
|
|
/**
|
|
* Add a byte
|
|
*/
|
|
public final void append (byte n) {
|
|
ensureCapacity(1);
|
|
buffer[hi] = n;
|
|
hi++;
|
|
}
|
|
|
|
/**
|
|
* Erase the contents of the ByteBuffering. Not MT safe.
|
|
* Will not shrink capacity.
|
|
*/
|
|
public final void erase () {
|
|
if (!wasCloned) hi = 0;
|
|
lo = hi;
|
|
}
|
|
|
|
/**
|
|
* Defragment the contents of buffer. Not MT safe.
|
|
*/
|
|
public final void cleanup () {
|
|
if (wasCloned || lo+lo <= buffer.length)
|
|
return;
|
|
System.arraycopy(buffer, lo, buffer, 0, hi-lo);
|
|
hi -= lo;
|
|
lo = 0;
|
|
}
|
|
|
|
/**
|
|
* Return substring from offset start (inclusive) till offset
|
|
* finish (exclusive).
|
|
*/
|
|
public ByteString substring (int start, int finish) {
|
|
ByteString result = super.substring(start, finish);
|
|
wasCloned = true;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Return substring to the right of the given offset (inclusive).
|
|
*/
|
|
public ByteString substring (int start) {
|
|
ByteString result = super.substring(start);
|
|
wasCloned = true;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add a line. Not MT-safe.
|
|
*/
|
|
public final void addLine (ByteString line) {
|
|
append(line);
|
|
append(CRLF);
|
|
}
|
|
|
|
/**
|
|
* Add a line. Not MT-safe.
|
|
*/
|
|
public final void addLine (byte[] line) {
|
|
append(line);
|
|
append(CRLF);
|
|
}
|
|
|
|
/**
|
|
* Read a line read (and maybe more) from a stream. Not MT-safe.
|
|
* Blocks until one line is read. May read multiple lines.
|
|
*/
|
|
public final void readLine (InputStream stream)
|
|
throws IOException {
|
|
while (noLines()) {
|
|
bulkRead(stream);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk read from a stream. Not MT-safe.
|
|
* Returns the number of bytes read.
|
|
*/
|
|
public final int bulkRead (InputStream stream)
|
|
throws IOException {
|
|
|
|
int n = -1;
|
|
ensureCapacity(1024); // TODO: is this a good number?
|
|
for (int attempt = 0; attempt < 10; attempt++) {
|
|
n = stream.read(buffer, hi, buffer.length-hi);
|
|
if (n > 0) {
|
|
hi += n;
|
|
return n;
|
|
}
|
|
else if (n == 0) {
|
|
System.err.println("BufferedInputStream.read(byte[], int, int) returns 0 on attempt #" + attempt);
|
|
try {
|
|
Thread.sleep(500);
|
|
} catch (InterruptedException e) {
|
|
System.err.println(e + " while waiting in bulkRead");
|
|
}
|
|
}
|
|
else {
|
|
throw new IOException("Bulk read returns " + n + " bytes");
|
|
}
|
|
}
|
|
throw new IOException("Bulk read returns " + n + " bytes");
|
|
}
|
|
|
|
/**
|
|
* Clones an instance of the ByteBuffer object.
|
|
* @exception CloneNotSupportedException could be thrown by constituent components.
|
|
*/
|
|
public Object clone () throws CloneNotSupportedException
|
|
{
|
|
ByteBuffer l_theClone = (ByteBuffer) super.clone();
|
|
|
|
return (l_theClone);
|
|
}
|
|
|
|
public InputStream getInputStream()
|
|
{
|
|
return new ByteArrayInputStream( buffer, lo, hi );
|
|
}
|
|
|
|
public void setSize( int len ) { ensureCapacity( len ); }
|
|
}
|