From: Greg W. <gre...@us...> - 2004-07-22 00:59:36
|
User: gregwilkins Date: 04/07/21 17:59:29 Modified: src/org/mortbay/io ByteArrayBuffer.java AbstractBuffer.java Buffer.java Added: src/org/mortbay/io View.java Log: More faffing about with the buffer model. Important to get right as it will be central to the speed and portability of everything. Just about happy with it now and will get on with the real async HTTP handling soon Revision Changes Path 1.9 +81 -234 JettyExperimental/src/org/mortbay/io/ByteArrayBuffer.java Index: ByteArrayBuffer.java =================================================================== RCS file: /cvsroot/jetty/JettyExperimental/src/org/mortbay/io/ByteArrayBuffer.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -r1.8 -r1.9 --- ByteArrayBuffer.java 23 Jun 2004 11:12:01 -0000 1.8 +++ ByteArrayBuffer.java 22 Jul 2004 00:59:29 -0000 1.9 @@ -15,7 +15,6 @@ package org.mortbay.io; - /* ------------------------------------------------------------------------------- */ /** * @version $Revision$ @@ -24,39 +23,33 @@ public class ByteArrayBuffer extends AbstractBuffer { private byte[] _bytes; - private int _mark; - private int _get; - private int _put; - - private String _string; - private ByteArrayBuffer _subBuffer; - private boolean _volatile; - public ByteArrayBuffer(byte[] bytes) { - this(bytes, 0, bytes.length, READWRITE, NONVOLATILE); + this(bytes, 0, bytes.length, READWRITE); } - public ByteArrayBuffer(byte[] bytes, int position, int length) + public ByteArrayBuffer(byte[] bytes, int index, int length) { - this(bytes, position, length, READWRITE, NONVOLATILE); + this(bytes, index, length, READWRITE); } - public ByteArrayBuffer(byte[] bytes, int position, int length, boolean readonly) + public ByteArrayBuffer(byte[] bytes, int index, int length, int access) { - this(bytes, position, length, readonly, NONVOLATILE); + super(READWRITE, NON_VOLATILE); + _bytes = bytes; + setPutIndex(index + length); + setGetIndex(index); + _access = access; } - public ByteArrayBuffer(byte[] bytes, int position, int length, boolean readonly, - boolean isVolatile) + public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile) { - super(READWRITE); + super(READWRITE, isVolatile); _bytes = bytes; - setPutIndex(position + length); - setGetIndex(position); - this._readOnly = readonly; - this._volatile = isVolatile; + setPutIndex(index + length); + setGetIndex(index); + _access = access; } public ByteArrayBuffer(int size) @@ -67,11 +60,11 @@ public ByteArrayBuffer(String value) { - super(READWRITE); + super(READWRITE,NON_VOLATILE); _bytes = Portable.getBytes(value); setGetIndex(0); setPutIndex(_bytes.length); - _readOnly = READONLY; + _access=IMMUTABLE; _string = value; } @@ -80,179 +73,33 @@ return _bytes; } - - public byte get() - { - return _bytes[_get++]; - } - - public int getIndex() - { - return _get; - } - - public int markIndex() - { - return _mark; - } - - public int putIndex() - { - return _put; - } - - public void setMarkIndex(int newMark) - { - _mark = newMark; - } - - /** - * @see org.mortbay.util.Buffer#limit(int) - */ - public void setPutIndex(int newPutIndex) - { - if (_readOnly) - Portable.throwIllegalState("read only"); - if (newPutIndex > capacity()) - Portable.throwIllegalArgument("newLimit>capacity: " + newPutIndex + ">" + capacity()); - if (getIndex() > newPutIndex) - Portable.throwIllegalArgument("position>newLimit: " + getIndex() + ">" + newPutIndex); - _put = newPutIndex; - } - - public void setGetIndex(int newGetIndex) - { - if (_readOnly) - Portable.throwIllegalState("read only"); - if (newGetIndex < 0) - Portable.throwIllegalArgument("newposition<0: " + newGetIndex + "<0"); - if (newGetIndex > putIndex()) - Portable.throwIllegalArgument("newposition>limit: " + newGetIndex + ">" + putIndex()); - _get=newGetIndex; - } - - /* - * @see org.mortbay.io.Buffer#asNonVolatile() - */ - public Buffer asNonVolatile() - { - if (!_volatile) - return this; - return new ByteArrayBuffer(_bytes, getIndex(), length(), isReadOnly()); - } - - /* - * @see org.mortbay.util.Buffer#asReadOnlyBuffer() - */ - public Buffer asReadOnlyBuffer() - { - if (!isReadOnly()) - { - byte[] bytes = new byte[putIndex() - getIndex()]; - Portable.arraycopy(array(), getIndex(), bytes, 0, bytes.length); - ByteArrayBuffer view = - new ByteArrayBuffer(bytes, 0, length(), READONLY); - return view; - } - else - return this; - } - public int capacity() { return _bytes.length; } - public Buffer duplicate() + public byte peek(int index) { - byte[] bytes = new byte[capacity()]; - if (markIndex() < 0) - Portable.arraycopy(array(), getIndex(), bytes, getIndex(), length()); - else - Portable.arraycopy( - array(), - markIndex(), - bytes, - markIndex(), - putIndex() - markIndex()); - ByteArrayBuffer view = - new ByteArrayBuffer(bytes, getIndex(), length(), !READONLY); - view.setMarkIndex(markIndex()); - return view; + return _bytes[index]; } - public int get(byte[] b, int offset, int length) + public int peek(int index, byte[] b, int offset, int length) { + if (index < 0) Portable.throwIllegalArgument("index<0: " + index + "<0"); int l = length; - if (l > length()) - l = length(); - if (l <= 0) - return -1; - Portable.arraycopy(_bytes, getIndex(), b, offset, l); - setGetIndex(getIndex() + l); + if (index + l > capacity()) l = capacity() - index; + if (l <= 0) return -1; + Portable.arraycopy(_bytes, index, b, offset, l); return l; } - public boolean isVolatile() + public void poke(int index, byte b) { - return _volatile; + if (isReadOnly()) Portable.throwIllegalState(__READONLY); + if (index < 0) Portable.throwIllegalArgument("index<0: " + index + "<0"); + if (index > capacity()) + Portable.throwIllegalArgument("index>capacity(): " + index + ">" + capacity()); + _bytes[index] = b; } - public byte peek(int position) - { - if (position < 0) - Portable.throwIllegalArgument("position<0: " + position + "<0"); - if (position > capacity()) - Portable.throwIllegalArgument("position>capacity(): " + position + ">" + capacity()); - return _bytes[position]; - } - - public Buffer peek(int position, int length) - { - if (position < 0) - Portable.throwIllegalArgument("position<0: " + position + "<0"); - if (position + length > capacity()) - Portable.throwIllegalArgument( - "position+length>capacity(): " + position + "+" + length + ">" + capacity()); - return subBuffer(position, length); - } - - public void poke(int position, byte b) - { - if (isReadOnly()) - Portable.throwIllegalState("readOnly"); - if (position < 0) - Portable.throwIllegalArgument("position<0: " + position + "<0"); - if (position > capacity()) - Portable.throwIllegalArgument("position>capacity(): " + position + ">" + capacity()); - _bytes[position] = b; - } - - protected Buffer subBuffer(int position, int length) - { - if (_subBuffer == null) - { - _subBuffer = new ByteArrayBuffer(array(), position, length, READWRITE); - _subBuffer._volatile = true; - } - else - { - _subBuffer.setGetIndex(0); - _subBuffer.setPutIndex(position + length); - _subBuffer.setGetIndex(position); - } - return _subBuffer; - } - - public String toString() - { - if (_string != null) - return _string; - if (isReadOnly() && !isVolatile()) - { - _string = new String(array(), getIndex(), length()); - return _string; - } - return new String(array(), getIndex(), length()); - } } 1.9 +462 -360 JettyExperimental/src/org/mortbay/io/AbstractBuffer.java Index: AbstractBuffer.java =================================================================== RCS file: /cvsroot/jetty/JettyExperimental/src/org/mortbay/io/AbstractBuffer.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -r1.8 -r1.9 --- AbstractBuffer.java 23 Jun 2004 11:12:01 -0000 1.8 +++ AbstractBuffer.java 22 Jul 2004 00:59:29 -0000 1.9 @@ -21,17 +21,33 @@ */ public abstract class AbstractBuffer implements Buffer { - protected boolean _caseSensitive; + + protected final static String __IMMUTABLE = "IMMUTABLE", __READONLY = "READONLY", + __READWRITE = "READWRITE", __VOLATILE = "VOLATILE"; + + protected int _access; + protected boolean _volatile; + + private boolean _caseSensitive; + private int _get; private int _hash; - protected boolean _readOnly; + private int _mark; + private int _put; + protected String _string; + private View _view; /** * Constructor for BufferView + * + * @param access 0==IMMUTABLE, 1==READONLY, 2==READWRITE */ - public AbstractBuffer(boolean readOnly) + public AbstractBuffer(int access, boolean isVolatile) { + if (access == IMMUTABLE && isVolatile) + Portable.throwIllegalArgument("IMMUTABLE && VOLATILE"); setMarkIndex(-1); - _readOnly = readOnly; + _access = access; + _volatile = isVolatile; } /* @@ -39,17 +55,52 @@ */ public byte[] asArray() { - byte[] bytes = new byte[putIndex() - getIndex()]; + byte[] bytes = new byte[length()]; byte[] array = array(); if (array!=null) Portable.arraycopy(array, getIndex(), bytes, 0, bytes.length); else + peek(getIndex(), bytes, 0, length()); + return bytes; + } + + /* + * @see org.mortbay.io.Buffer#asNonVolatile() + */ + public Buffer asNonVolatileBuffer() { - int p=0; - for (int i=getIndex() ; i < putIndex() ; i++ ) - bytes[p++]=peek(i); + if (!isVolatile()) return this; + return new ByteArrayBuffer(asArray(), 0, length(), _access, NON_VOLATILE); } - return bytes; + + public Buffer asImmutableBuffer() + { + if (isImmutable()) return this; + return new ByteArrayBuffer(asArray(), 0, length(), IMMUTABLE); + } + + /* + * @see org.mortbay.util.Buffer#asReadOnlyBuffer() + */ + public Buffer asReadOnlyBuffer() + { + if (isReadOnly()) return this; + return new View(this, markIndex(), getIndex(), putIndex(), READONLY); + } + + public Buffer asMutableBuffer() + { + if (!isImmutable()) return this; + + Buffer b=this.buffer(); + if (b.isReadOnly()) + return new ByteArrayBuffer(asArray(), 0, length(), READWRITE); + return new View(b, markIndex(), getIndex(), putIndex(), _access); + } + + public Buffer buffer() + { + return this; } public void clear() @@ -60,6 +111,7 @@ public void compact() { + if (isReadOnly()) Portable.throwIllegalState(__READONLY); int s = markIndex() >= 0 ? markIndex() : getIndex(); if (s > 0) { @@ -68,37 +120,35 @@ if (length > 0) { if (array != null) - Portable.arraycopy(array(), s, array(), 0, putIndex() - s); + Portable.arraycopy(array(), s, array(), 0, length); else { - for (int i = length; i-- > 0;) - poke(i, peek(s + i)); + poke(0, peek(s, length)); + // for (int i = length; i-- > 0;) + // poke(i, peek(s + i)); } } - if (markIndex() > 0) - setMarkIndex(markIndex() - s); + if (markIndex() > 0) setMarkIndex(markIndex() - s); setGetIndex(getIndex() - s); setPutIndex(putIndex() - s); } } + public boolean equals(Object obj) { // reject non buffers; - if (obj == null || !(obj instanceof Buffer)) - return false; + if (obj == null || !(obj instanceof Buffer)) return false; Buffer b = (Buffer) obj; // reject different lengths - if (b.length() != length()) - return false; + if (b.length() != length()) return false; // reject AbstractBuffer with different hash value if (_hash != 0 && obj instanceof AbstractBuffer) { AbstractBuffer ab = (AbstractBuffer) obj; - if (ab._hash != 0 && _hash != ab._hash) - return false; + if (ab._hash != 0 && _hash != ab._hash) return false; } // Nothing for it but to do the hard grind. @@ -108,14 +158,10 @@ byte b2 = b.peek(b.getIndex() + i); if (b1 != b2) { - if (isCaseSensitive() && b.isCaseSensitive()) - return false; - if ('a' <= b1 && b1 <= 'z') - b1 = (byte) (b1 - 'a' + 'A'); - if ('a' <= b2 && b2 <= 'z') - b2 = (byte) (b2 - 'a' + 'A'); - if (b1 != b2) - return false; + if (isCaseSensitive() && b.isCaseSensitive()) return false; + if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A'); + if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A'); + if (b1 != b2) return false; } } return true; @@ -129,6 +175,14 @@ return b; } + public int get(byte[] b, int offset, int length) + { + int gi = getIndex(); + length = peek(gi, b, offset, length); + setGetIndex(gi + length); + return length; + } + public Buffer get(int length) { int gi=getIndex(); @@ -137,6 +191,10 @@ return view; } + public int getIndex() + { + return _get; + } public boolean hasContent() { @@ -149,21 +207,17 @@ for (int i = putIndex(); i-- > getIndex();) { byte b = peek(i); - if (!isCaseSensitive() && 'a' >= b && b <= 'z') - b = (byte) (b - 'a' + 'A'); + if (!isCaseSensitive() && 'a' >= b && b <= 'z') b = (byte) (b - 'a' + 'A'); hash = 31 * hash + b; } - if (hash == 0) - hash = -1; + if (hash == 0) hash = -1; return hash; } public int hashCode() { - if (!isReadOnly()) - return hash(); - if (_hash == 0) - _hash = hash(); + if (!isImmutable()) return hash(); + if (_hash == 0) _hash = hash(); return _hash; } @@ -172,9 +226,19 @@ return _caseSensitive; } + public boolean isImmutable() + { + return _access <= IMMUTABLE; + } + public boolean isReadOnly() { - return _readOnly; + return _access <= READONLY; + } + + public boolean isVolatile() + { + return _volatile; } public int length() @@ -192,25 +256,39 @@ setMarkIndex(getIndex()+offset); } + public int markIndex() + { + return _mark; + } + public byte peek() { return peek(getIndex()); } + public Buffer peek(int index, int length) + { + if (_view == null) + { + _view = new View(this, -1, index, index + length, isReadOnly() ? READONLY : READWRITE); + } + else + { + _view.setMarkIndex(-1); + _view.setGetIndex(0); + _view.setPutIndex(index + length); + _view.setGetIndex(index); + } + return _view; + } + public void poke(int index, Buffer src) { - if (isReadOnly()) - Portable.throwIllegalState("read only"); - if (index < 0) - Portable.throwIllegalArgument("index<0: " + index + "<0"); + if (isReadOnly()) Portable.throwIllegalState(__READONLY); + if (index < 0) Portable.throwIllegalArgument("index<0: " + index + "<0"); if (index + src.length() > capacity()) - Portable.throwIllegalArgument( - "index+length>capacity(): " - + index - + "+" - + src.length() - + ">" - + capacity()); + Portable.throwIllegalArgument("index+length>capacity(): " + index + "+" + + src.length() + ">" + capacity()); byte[] src_array = src.array(); byte[] dst_array = array(); if (src_array != null && dst_array != null) @@ -234,18 +312,11 @@ public void poke(int index, byte[] b, int offset, int length) { - if (isReadOnly()) - Portable.throwIllegalState("read only"); - if (index < 0) - Portable.throwIllegalArgument("index<0: " + index + "<0"); + if (isReadOnly()) Portable.throwIllegalState(__READONLY); + if (index < 0) Portable.throwIllegalArgument("index<0: " + index + "<0"); if (index + length > capacity()) - Portable.throwIllegalArgument( - "index+length>capacity(): " - + index - + "+" - + length - + ">" - + capacity()); + Portable.throwIllegalArgument("index+length>capacity(): " + index + "+" + length + + ">" + capacity()); byte[] dst_array = array(); if (dst_array != null) Portable.arraycopy(b, offset, dst_array, index, length); @@ -277,10 +348,14 @@ setPutIndex(pi+length); } + public int putIndex() + { + return _put; + } + public void reset() { - if (markIndex()>=0) - setGetIndex(markIndex()); + if (markIndex() >= 0) setGetIndex(markIndex()); } public void rewind() @@ -294,11 +369,34 @@ _caseSensitive = c; } + public void setGetIndex(int getIndex) + { + if (isImmutable()) Portable.throwIllegalState(__IMMUTABLE); + if (getIndex < 0) Portable.throwIllegalArgument("getIndex<0: " + getIndex + "<0"); + if (getIndex > putIndex()) + Portable.throwIllegalArgument("getIndex>putIndex: " + getIndex + ">" + putIndex()); + _get = getIndex; + } + + public void setMarkIndex(int index) + { + if (index>=0 && isImmutable()) Portable.throwIllegalState(__IMMUTABLE); + _mark = index; + } + + public void setPutIndex(int putIndex) + { + if (isImmutable()) Portable.throwIllegalState(__IMMUTABLE); + if (putIndex > capacity()) + Portable.throwIllegalArgument("putIndex>capacity: " + putIndex + ">" + capacity()); + if (getIndex() > putIndex) + Portable.throwIllegalArgument("getIndex>putIndex: " + getIndex() + ">" + putIndex); + _put = putIndex; + } public int skip(int n) { - if (length() < n) - n = length(); + if (length() < n) n = length(); setGetIndex(getIndex()+n); return n; } @@ -315,8 +413,7 @@ public Buffer sliceFromMark(int length) { - if (markIndex() < 0) - return null; + if (markIndex() < 0) return null; Buffer view = peek(markIndex(), length); setMarkIndex(-1); return view; @@ -384,6 +481,11 @@ public String toString() { + if (isImmutable()) + { + if (_string == null) _string = new String(asArray(), 0, length()); + return _string; + } return new String(asArray(), 0, length()); } } 1.9 +49 -17 JettyExperimental/src/org/mortbay/io/Buffer.java Index: Buffer.java =================================================================== RCS file: /cvsroot/jetty/JettyExperimental/src/org/mortbay/io/Buffer.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -r1.8 -r1.9 --- Buffer.java 23 Jun 2004 11:12:01 -0000 1.8 +++ Buffer.java 22 Jul 2004 00:59:29 -0000 1.9 @@ -32,8 +32,14 @@ * * @version 1.0 */ -public interface Buffer +public interface Buffer extends Cloneable { + public final static int + IMMUTABLE=0, + READONLY=1, + READWRITE=2; + public final boolean VOLATILE=true; + public final boolean NON_VOLATILE=false; /** * Get the underlying array, if one exists. @@ -48,10 +54,16 @@ byte[] asArray(); /** + * Get the unerlying buffer. If this buffer wraps a backing buffer. + * @return The root backing buffer or this if there is no backing buffer; + */ + Buffer buffer(); + + /** * * @return a non volitile version of this <code>Buffer</code> value */ - Buffer asNonVolatile(); + Buffer asNonVolatileBuffer(); /** * @@ -59,6 +71,17 @@ */ Buffer asReadOnlyBuffer(); + /** + * + * @return an immutable version of this <code>Buffer</code>. + */ + Buffer asImmutableBuffer(); + + /** + * + * @return an immutable version of this <code>Buffer</code>. + */ + Buffer asMutableBuffer(); /** * @@ -86,12 +109,6 @@ void compact(); /** - * - * @return a <code>Buffer</code> duplicate. - */ - Buffer duplicate(); - - /** * Get the byte at the current getIndex and increment it. * @return The <code>byte</code> value from the current getIndex. */ @@ -131,16 +148,25 @@ */ boolean isCaseSensitive(); + + /** + * + * @return a <code>boolean</code> value true if the buffer is immutable and that neither + * the buffer contents nor the indexes may be changed. + */ + boolean isImmutable(); + /** * - * @return a <code>boolean</code> value true if the buffer is readonly + * @return a <code>boolean</code> value true if the buffer is readonly. The buffer indexes may + * be modified, but the buffer contents may not. */ boolean isReadOnly(); /** * - * @return a <code>boolean</code> value true if the buffer is expected to changed - * outside of the current scope. + * @return a <code>boolean</code> value true if the buffer contents may change + * via alternate paths than this buffer. */ boolean isVolatile(); @@ -189,6 +215,16 @@ Buffer peek(int index, int length); /** + * + * @param index an <code>int</code> value + * @param b The byte array to peek into + * @param offset The offset into the array to start peeking + * @param length an <code>int</code> value + * @return The number of bytes actually peeked + */ + int peek(int index, byte[] b, int offset, int length); + + /** * Put the contents of the buffer at the specific index. * @param index an <code>int</code> value * @param src a <code>Buffer</code> value @@ -291,8 +327,4 @@ String toDetailString(); - public final static boolean READONLY= true; - public final static boolean READWRITE= false; - public final static boolean VOLATILE= true; - public final static boolean NONVOLATILE= false; } 1.1 JettyExperimental/src/org/mortbay/io/View.java Index: View.java =================================================================== //======================================================================== //$Id: View.java,v 1.1 2004/07/22 00:59:29 gregwilkins Exp $ //Copyright 2004 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed 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 org.mortbay.io; /** * A View on another buffer. Allows operations that do not change the content or * indexes of the backing buffer. * * @author gregw * */ public class View extends AbstractBuffer { Buffer _buffer; /** * @param buffer * @param mark * @param get * @param put * @param readonly * @param b */ public View(Buffer buffer, int mark, int get, int put,int access) { super(READWRITE,!buffer.isImmutable()); _buffer=buffer.buffer(); setPutIndex(put); setGetIndex(get); setMarkIndex(mark); _access=access; } public View(Buffer buffer) { super(READWRITE,!buffer.isImmutable()); _buffer=buffer.buffer(); setPutIndex(buffer.putIndex()); setGetIndex(buffer.getIndex()); setMarkIndex(buffer.markIndex()); _access=buffer.isReadOnly()?READONLY:READWRITE; } public void update(Buffer buffer) { _access=READWRITE; _buffer=buffer.buffer(); setPutIndex(buffer.putIndex()); setGetIndex(buffer.getIndex()); setMarkIndex(buffer.markIndex()); _access=buffer.isReadOnly()?READONLY:READWRITE; } public void update(int get, int put) { int a=_access; _access=READWRITE; setPutIndex(put); setGetIndex(get); setMarkIndex(-1); _access=a; } /** * @return */ public byte[] array() { return _buffer.array(); } /** * @return */ public Buffer buffer() { return _buffer.buffer(); } /** * @return */ public int capacity() { return _buffer.capacity(); } /** * */ public void clear() { setMarkIndex(-1); setGetIndex(_buffer.getIndex()); setPutIndex(_buffer.getIndex()); } /** * */ public void compact() { // TODO } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object arg0) { return this==arg0 || super.equals(arg0); } /** * @return */ public boolean isReadOnly() { return _buffer.isReadOnly(); } /** * @return */ public boolean isVolatile() { return true; } /** * @param index * @return */ public byte peek(int index) { return _buffer.peek(index); } /** * @param index * @param length * @return */ public int peek(int index, byte[] b, int offset, int length) { return _buffer.peek(index,b,offset,length); } /** * @param index * @param length * @return */ public Buffer peek(int index, int length) { return _buffer.peek(index, length); } /** * @param index * @param src */ public void poke(int index, Buffer src) { _buffer.poke(index,src); } /** * @param index * @param b */ public void poke(int index, byte b) { _buffer.poke(index,b); } /** * @param index * @param b * @param offset * @param length */ public void poke(int index, byte[] b, int offset, int length) { _buffer.poke(index,b,offset,length); } } |