adding new sources
git-svn-id: svn://10.0.0.236/trunk@8400 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
501
mozilla/msgsdk/java/protocol/MIME/src/ByteString.java
Normal file
501
mozilla/msgsdk/java/protocol/MIME/src/ByteString.java
Normal file
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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.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.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* ByteString is similar to java.lang.String, except that it contains
|
||||
* bytes instead of characters.
|
||||
*/
|
||||
public class ByteString extends Object implements Cloneable {
|
||||
protected byte[] buffer;
|
||||
protected int lo;
|
||||
protected int hi;
|
||||
|
||||
protected static byte CR = '\r';
|
||||
protected static byte LF = '\n';
|
||||
protected static byte[] CRLF = "\r\n".getBytes();
|
||||
|
||||
protected ByteString () {
|
||||
buffer = null;
|
||||
lo = 0;
|
||||
hi = 0;
|
||||
}
|
||||
|
||||
public ByteString (String string) {
|
||||
buffer = string.getBytes();
|
||||
lo = 0;
|
||||
hi = buffer.length;
|
||||
}
|
||||
|
||||
public ByteString (byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
this.lo = 0;
|
||||
this.hi = buffer.length;
|
||||
}
|
||||
|
||||
public ByteString (byte[] buffer, int lo, int hi) {
|
||||
if (lo > hi) throw new IndexOutOfBoundsException();
|
||||
this.buffer = buffer;
|
||||
this.lo = lo;
|
||||
this.hi = hi;
|
||||
}
|
||||
|
||||
/**
|
||||
* hashCode() -- Overrides java.lang.Object.hashCode()
|
||||
*/
|
||||
public final int hashCode () {
|
||||
int result = 0;
|
||||
// TODO: improve hash function
|
||||
for (int i = lo; i < hi; i++) {
|
||||
result += buffer[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* equals() -- Overrides java.lang.Object.equals()
|
||||
*/
|
||||
public final boolean equals (Object that) {
|
||||
if (this == that)
|
||||
return true;
|
||||
else
|
||||
return equals(((ByteString) that).buffer, ((ByteString) that).lo, ((ByteString) that).size());
|
||||
}
|
||||
|
||||
public final boolean equals (byte[] buf) {
|
||||
return equals(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
public final boolean equals (byte[] buf, int low, int length) {
|
||||
|
||||
if (this.size() != length)
|
||||
return false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (this.byteAt(i) != buf[low++])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare this to that in lex order
|
||||
*/
|
||||
public final boolean greaterOrEqual (ByteString that) {
|
||||
int m = this.size();
|
||||
int n = that.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (i >= m)
|
||||
return false;
|
||||
else {
|
||||
byte x = this.byteAt(i);
|
||||
byte y = that.byteAt(i);
|
||||
if (x < y)
|
||||
return false;
|
||||
else if (x > y)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bytes
|
||||
*/
|
||||
public final int size () {
|
||||
return (hi-lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return byte at given offset.
|
||||
*/
|
||||
public final byte byteAt (int i) {
|
||||
if (lo + i >= hi) throw new IndexOutOfBoundsException();
|
||||
return buffer[lo+i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the ByteString starts with the given byte[].
|
||||
* Ignores case.
|
||||
*/
|
||||
private final boolean startsWith (byte[] that) {
|
||||
if (that.length > hi - lo) return false;
|
||||
for (int i = 0; i < that.length; i++) {
|
||||
char x = (char)(buffer[lo+i]);
|
||||
char y = (char)(that[i]);
|
||||
if (x != y && (x < 'a' || x > 'z' || (x + 'A' - 'a') != y))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset for the first occurrence of a given byte
|
||||
* in the ByteString if present, and -1 otherwise.
|
||||
*/
|
||||
public final int firstIndexOf (byte x) {
|
||||
for (int i = lo; i < hi; i++) {
|
||||
if (buffer[i] == x)
|
||||
return (i-lo);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset for the first occurrence of a given byte
|
||||
* in the ByteString to the right of the given offset if present, and
|
||||
* -1 otherwise.
|
||||
*/
|
||||
public final int firstIndexOf (byte x, int offset) {
|
||||
for (int i = lo+offset+1; i < hi; i++) {
|
||||
if (buffer[i] == x)
|
||||
return (i-lo);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset for the last occurrence of a given byte
|
||||
* in the ByteString if present, and -1 otherwise.
|
||||
*/
|
||||
public final int lastIndexOf (byte x) {
|
||||
for (int i = hi; --i >= lo; ) {
|
||||
if (buffer[i] == x)
|
||||
return (i-lo);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset for the last occurrence of a given byte
|
||||
* in the ByteString to the left of the given offset if present, and
|
||||
* -1 otherwise.
|
||||
*/
|
||||
public final int lastIndexOf (byte x, int offset) {
|
||||
for (int i = lo+offset; --i >= lo; ) {
|
||||
if (buffer[i] == x)
|
||||
return (i-lo);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the offset for the first occurrence of a given byte[]
|
||||
* in the ByteString to the right of the given offset if present,
|
||||
* and -1 otherwise. Case insensitive.
|
||||
*/
|
||||
public final int firstIndexOf (byte[] that) {
|
||||
return firstIndexOf(that, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the offset for the first occurrence of a given byte[]
|
||||
* in the ByteString to the right of the given offset if present,
|
||||
* and -1 otherwise. Case insensitive.
|
||||
*/
|
||||
public final int firstIndexOf (byte[] that, int offset) {
|
||||
|
||||
for (int i = lo+offset; i <= hi-that.length; i++) {
|
||||
int j;
|
||||
for (j = 0; j < that.length; j++) {
|
||||
char x = (char)(buffer[i+j]);
|
||||
char y = (char)(that[j]);
|
||||
if (x != y && (x < 'a' || x > 'z' || (x + 'A' - 'a') != y))
|
||||
break;
|
||||
}
|
||||
if (j >= that.length) {
|
||||
return i-lo;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to String
|
||||
*/
|
||||
public final String toString () {
|
||||
return new String(buffer, lo, hi-lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to byte[]
|
||||
* clone version
|
||||
*/
|
||||
public final byte[] getBytes () { return getBytes( true ); }
|
||||
|
||||
/**
|
||||
* Convert to byte[]
|
||||
* clonable version
|
||||
*/
|
||||
public final byte[] getBytes ( boolean clone )
|
||||
{
|
||||
if ( clone )
|
||||
{
|
||||
byte[] result = new byte[hi-lo];
|
||||
System.arraycopy(buffer, lo, result, 0, hi-lo);
|
||||
return result;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public final byte[] getBytes ( int len[] )
|
||||
{
|
||||
len[0] = hi;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract X out of ByteString X+Y+Z, where Y is the given delimiter.
|
||||
* Replace original ByteString (X+Y+Z) by Z. Not MT-safe.
|
||||
* Returns null if Y is absent.
|
||||
*/
|
||||
public final ByteString extractTill (byte[] y) {
|
||||
int offset = firstIndexOf(y, 0);
|
||||
if (offset < 0) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
ByteString result = substring(0, offset);
|
||||
lo += (offset + y.length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove Y from ByteString Y+Z, where Y is the given token,
|
||||
* If successful, replace original ByteString (Y+Z) by Z, and
|
||||
* & return true. Else return false. Not MT-safe.
|
||||
* Throw ArrayIndexOutOfBoundsException if ByteString does
|
||||
* not start with Y.
|
||||
*/
|
||||
public final boolean extractToken (byte[] y) {
|
||||
if (startsWith(y)) {
|
||||
lo += y.length;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard COUNT bytes from ByteString
|
||||
*/
|
||||
public final void discard(int count) {
|
||||
if (lo + count > hi) throw new IndexOutOfBoundsException();
|
||||
lo += count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard X+Y from ByteString X+Y+Z, where Y is the given token.
|
||||
* Throw ArrayIndexOutOfBoundsException if Y is absent.
|
||||
*/
|
||||
public final void discardTill (byte[] y) {
|
||||
lo += (firstIndexOf(y, 0) + y.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard X+Y from ByteString X+Y+Z, where Y is LF or CRLF.
|
||||
* Throw ArrayIndexOutOfBoundsException if Y is absent.
|
||||
*/
|
||||
public final void discardLine () {
|
||||
lo += (firstIndexOf(LF, 0) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for absence of complete lines
|
||||
*/
|
||||
public final boolean noLines () {
|
||||
return firstIndexOf(LF, 0) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for absence of complete lines to the right of the given offset
|
||||
*/
|
||||
public final boolean noLines (int offset) {
|
||||
return firstIndexOf(LF, offset) < 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the first line and return it as a substring.
|
||||
* Throw ArrayIndexOutOfBoundsException if there are no lines.
|
||||
*/
|
||||
public final ByteString extractLine() {
|
||||
ByteString result;
|
||||
int offset = firstIndexOf(LF, 0);
|
||||
if (offset > 1 && byteAt(offset-1) == CR) {
|
||||
result = substring(0, offset-1);
|
||||
lo += (offset + 1);
|
||||
}
|
||||
else {
|
||||
result = substring(0, offset);
|
||||
lo += (offset + 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the first line and write it to given output stream.
|
||||
* Throw ArrayIndexOutOfBoundsException if there are no lines.
|
||||
* return number of byte wrote
|
||||
*/
|
||||
|
||||
public final int extractLine(OutputStream stream)
|
||||
throws IOException {
|
||||
|
||||
int origin = lo;
|
||||
|
||||
int offset = firstIndexOf(LF, 0);
|
||||
if (offset > 1 && byteAt(offset-1) == CR) {
|
||||
stream.write(buffer, lo, offset-1);
|
||||
stream.write(CRLF);
|
||||
lo += (offset + 1);
|
||||
}
|
||||
else {
|
||||
stream.write(buffer, lo, offset);
|
||||
stream.write(CRLF);
|
||||
lo += (offset + 1);
|
||||
}
|
||||
return (lo - origin);
|
||||
}
|
||||
|
||||
public void discardLeadingSpace()
|
||||
{
|
||||
// skip leading space
|
||||
for (; lo < hi; lo++) {
|
||||
if (buffer[lo] != ' ' )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bulk write to a stream.
|
||||
*/
|
||||
public final void write (OutputStream stream)
|
||||
throws IOException {
|
||||
|
||||
stream.write(buffer, lo, hi-lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a long
|
||||
**/
|
||||
public final long extractLong() {
|
||||
long n = 0;
|
||||
for (int i = lo; i < lo+8; i++) {
|
||||
n <<= 8;
|
||||
n += buffer[i];
|
||||
}
|
||||
lo += 8;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract an int
|
||||
**/
|
||||
public final int extractInt() {
|
||||
int n = 0;
|
||||
for (int i = lo; i < lo+4; i++) {
|
||||
n <<= 8;
|
||||
n += buffer[i];
|
||||
}
|
||||
lo += 4;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return substring from offset start (inclusive) till offset
|
||||
* finish (exclusive).
|
||||
*/
|
||||
public ByteString substring (int start, int finish) {
|
||||
if (start > finish || lo+finish > hi)
|
||||
throw new IndexOutOfBoundsException();
|
||||
return new ByteString(buffer, lo+start, lo+finish);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return substring from offset start (inclusive) till the
|
||||
* end of the ByteString.
|
||||
*/
|
||||
public ByteString substring (int start) {
|
||||
if (lo+start > hi) throw new IndexOutOfBoundsException();
|
||||
return new ByteString(buffer, lo+start, hi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the contents of the ByteString for
|
||||
* the purpose of debugging
|
||||
*/
|
||||
public void displayBuffer (String caption, BufferedOutputStream stream) {
|
||||
int saved = lo;
|
||||
|
||||
try {
|
||||
for (int i = 0; !noLines(); i++) {
|
||||
stream.write(caption.getBytes());
|
||||
extractLine(stream);
|
||||
}
|
||||
stream.write(caption.getBytes());
|
||||
stream.write(getBytes());
|
||||
lo = saved;
|
||||
stream.flush();
|
||||
} catch (IOException e) {
|
||||
System.err.println(e + " while displaying contents of ByteString");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clones an instance of the ByteString object.
|
||||
* @exception CloneNotSupportedException could be thrown by constituent components.
|
||||
*/
|
||||
public Object clone () throws CloneNotSupportedException
|
||||
{
|
||||
ByteString l_theClone = (ByteString) super.clone();
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
l_theClone.buffer = new byte [buffer.length];
|
||||
System.arraycopy (buffer, 0, l_theClone.buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
return (l_theClone);
|
||||
}
|
||||
|
||||
|
||||
public void setSize( int len )
|
||||
{
|
||||
hi = len;
|
||||
lo = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user