Author: costin Date: Tue Nov 1 22:39:17 2005 New Revision: 330199 URL: http://svn.apache.org/viewcvs?rev=330199&view=rev Log: Well, NIO ByteBuffer is the most horrible interface in java. Whoever invented the flip() interface - and a buffer where you can't know where it starts and where it ends and where is the data - should be ashamed...
The only way we can use the buffer is by keeping track of start and end as before, anything that uses position() or limit() will never know if it's reading or writting or if the buffer has flipped. The use of ByteBuffer is still a good thing - if you ignore the stupid interface, as is the only way to work with direct and mapped byte[], and maybe in a smarter VM get some buffers that are not relocated. It is also usefull because it can work with the usefull parts of nio - like charset and channels. Modified: tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java Modified: tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java?rev=330199&r1=330198&r2=330199&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java Tue Nov 1 22:39:17 2005 @@ -20,9 +20,6 @@ import java.io.Serializable; import java.nio.ByteBuffer; -import sun.security.krb5.internal.crypto.b; -import sun.security.krb5.internal.crypto.t; - /* * In a server it is very important to be able to operate on * the original byte[] without converting everything to chars. @@ -37,6 +34,9 @@ * to be able to parse the request without converting to string. */ +// TODO: This class could either extend ByteBuffer, or better a ByteBuffer inside +// this way it could provide the search/etc on ByteBuffer, as a helper. + /** * This class is used to represent a chunk of bytes, and * utilities to manipulate byte[]. @@ -66,8 +66,6 @@ /** Input interface, used when the buffer is emptiy * * Same as java.nio.channel.ReadableByteChannel - * It is used in InputBuffer class in connector. - * @deprecated Use RedableByteChannel */ public static interface ByteInputChannel { /** @@ -80,8 +78,6 @@ } /** Same as java.nio.channel.WrittableByteChannel. - * - * @deprecated use WrittableByteChannel */ public static interface ByteOutputChannel { /** @@ -100,19 +96,17 @@ */ public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1"; + // byte[] + //private byte[] buff; private ByteBuffer bb; - // old style - while I'm updating - //private byte[] buff; - - //private int start=0; // bb.getPosition() - //private int end; // bb.getLimit() + private int start=0; + private int end; private String enc; - // true if null. Is this used ?? - private boolean isSet=false; - + private boolean isSet=false; // XXX + // How much can it grow, when data is added private int limit=-1; @@ -133,15 +127,6 @@ } //-------------------- - - public void setByteBuffer(ByteBuffer buf) { - bb=buf; - } - - public ByteBuffer getByteBuffer() { - return bb; - } - public ByteChunk getClone() { try { return (ByteChunk)this.clone(); @@ -150,9 +135,6 @@ } } - /** @deprecated The buffer shouldn't be null - track this on the - * MessageBytes. - */ public boolean isNull() { return ! isSet; // buff==null; } @@ -163,32 +145,26 @@ public void recycle() { // buff = null; enc=null; - //start=0; - //end=0; + start=0; + end=0; isSet=false; - if( bb!=null ) bb.clear(); } public void reset() { -// buff=null; - bb=null; + bb=null; } // -------------------- Setup -------------------- public void allocate( int initial, int limit ) { isOutput=true; - if( bb==null || bb.capacity() < initial ) { - bb=ByteBuffer.allocate( initial ); - } - -// if( buff==null || buff.length < initial ) { -// buff=new byte[initial]; -// } - + if( bb==null || bb.capacity() < initial ) { + //buff=new byte[initial]; + bb=ByteBuffer.allocate(initial); + } this.limit=limit; - //start=0; - //end=0; + start=0; + end=0; isSet=true; } @@ -198,15 +174,13 @@ * @param b the ascii bytes * @param off the start offset of the bytes * @param len the length of the bytes - * @deprecated use getByteBuffer().wrap( b, off, len ) */ public void setBytes(byte[] b, int off, int len) { -// buff = b; - //start = off; - //end = start+ len; + //buff = b; + bb=ByteBuffer.wrap( b, off, len ); + start = off; + end = start+ len; isSet=true; - - bb=ByteBuffer.wrap(b, off, len); } public void setOptimizedWrite(boolean optimizedWrite) { @@ -216,7 +190,6 @@ public void setEncoding( String enc ) { this.enc=enc; } - public String getEncoding() { if (enc == null) enc=DEFAULT_CHARACTER_ENCODING; @@ -225,7 +198,6 @@ /** * Returns the message bytes. - * @deprecated use getBuffer() ( or better - don't use it, ByteBuffer ) */ public byte[] getBytes() { return getBuffer(); @@ -233,10 +205,9 @@ /** * Returns the message bytes. - * @deprecated Should be avoided, it's optional on direct buffers */ public byte[] getBuffer() { - return bb.array(); //buff; + return bb.array(); } /** @@ -244,21 +215,16 @@ * For output this is the end of the buffer. */ public int getStart() { - return bb.position();// start; + return start; } public int getOffset() { - return bb.position();//start; + return start; } public void setOffset(int off) { - //if (end < off ) end=off; - if( bb.limit() < off ) { - bb.limit(off); - } - - //start=off; - bb.position( off ); + if (end < off ) end=off; + start=off; } /** @@ -266,7 +232,7 @@ * XXX need to clean this up */ public int getLength() { - return bb.remaining(); // end-start; + return end-start; } /** Maximum amount of data in this buffer. @@ -301,11 +267,11 @@ } public int getEnd() { - return bb.limit(); // end; + return end; } public void setEnd( int i ) { - bb.limit(i); // end=i; + end=i; } // -------------------- Adding data to the buffer -------------------- @@ -326,10 +292,11 @@ makeSpace( 1 ); // couldn't make space - if( limit >0 && bb.limit() >= limit ) { + if( limit >0 && end >= limit ) { flushBuffer(); } - bb.put( b ); //buff[end++]=b; + //buff[end++]=b; + bb.put(end++, b); } public void append( ByteChunk src ) @@ -338,15 +305,6 @@ append( src.getBytes(), src.getStart(), src.getLength()); } - /** - * Copy all data from another bytebuffer. - * - * @param bb - */ - public void append( ByteBuffer src ) { - bb.put( src ); - } - /** Add data to the buffer */ public void append( byte src[], int off, int len ) @@ -358,9 +316,8 @@ // if we don't have limit: makeSpace can grow as it wants if( limit < 0 ) { // assert: makeSpace made enough space - //System.arraycopy( src, off, buff, end, len ); - bb.put(src, off, len); - //end+=len; + System.arraycopy( src, off, bb.array(), end, len ); + end+=len; return; } @@ -368,17 +325,16 @@ // If the buffer is empty and the source is going to fill up all the // space in buffer, may as well write it directly to the output, // and avoid an extra copy - if ( optimizedWrite && len == limit && bb.limit() == bb.position()) { + if ( optimizedWrite && len == limit && end == start) { out.realWriteBytes( src, off, len ); return; } // if we have limit and we're below - if( len <= limit - bb.limit() ) { + if( len <= limit - end ) { // makeSpace will grow the buffer to the limit, // so we have space - //System.arraycopy( src, off, buff, end, len ); - bb.put( src, off, len ); - //end+=len; + System.arraycopy( src, off, bb.array(), end, len ); + end+=len; return; } @@ -390,23 +346,21 @@ // We chunk the data into slices fitting in the buffer limit, although // if the data is written directly if it doesn't fit - int avail=limit-bb.limit(); // end; - //System.arraycopy(src, off, buff, end, avail); - bb.put( src, off, avail ); - //end += avail; + int avail=limit-end; + System.arraycopy(src, off, bb.array(), end, avail); + end += avail; flushBuffer(); int remain = len - avail; - while (remain > (limit - bb.limit())) { - out.realWriteBytes( src, (off + len) - remain, limit - bb.limit() ); - remain = remain - (limit - bb.limit()); + while (remain > (limit - end)) { + out.realWriteBytes( src, (off + len) - remain, limit - end ); + remain = remain - (limit - end); } - //System.arraycopy(src, (off + len) - remain, buff, end, remain); - bb.put( src, (off+len ) - remain, remain); - //end += remain; + System.arraycopy(src, (off + len) - remain, bb.array(), end, remain); + end += remain; } @@ -416,43 +370,40 @@ public int substract() throws IOException { - if ((bb.limit() - bb.position()) == 0) { + if ((end - start) == 0) { if (in == null) return -1; - // TODO: if( in != null ) ... int n = in.realReadBytes( bb.array(), 0, bb.capacity() ); if (n < 0) return -1; } - return (bb.get() & 0xFF); + return (bb.get(start++) & 0xFF); } public int substract(ByteChunk src) throws IOException { - if ((bb.limit() - bb.position()) == 0) { + if ((end - start) == 0) { if (in == null) return -1; - int n = in.realReadBytes( bb.array(), 0, bb.capacity()); + int n = in.realReadBytes( bb.array(), 0, bb.capacity() ); if (n < 0) return -1; } int len = getLength(); - - src.getByteBuffer().put( bb ); - //src.append(buff, start, len); - //start = end; - + src.append(bb.array(), start, len); + start = end; return len; + } public int substract( byte src[], int off, int len ) throws IOException { - if ((bb.limit() - bb.position()) == 0) { + if ((end - start) == 0) { if (in == null) return -1; int n = in.realReadBytes( bb.array(), 0, bb.capacity() ); @@ -464,10 +415,8 @@ if (len > getLength()) { n = getLength(); } - - bb.get( src, off, n); - //System.arraycopy(buff, start, src, off, n); - //start += n; + System.arraycopy(bb.array(), start, src, off, n); + start += n; return n; } @@ -486,9 +435,8 @@ throw new IOException( "Buffer overflow, no sink " + limit + " " + bb.capacity() ); } - out.realWriteBytes( bb.array(), bb.position(), bb.limit()-bb.position()); - bb.position(bb.limit()); - //end=start; + out.realWriteBytes( bb.array(), start, end-start ); + end=start; } /** Make space for len chars. If len is small, allocate @@ -499,7 +447,7 @@ ByteBuffer tmp = null; int newSize; - int desiredSize=bb.limit() + count; + int desiredSize=end + count; // Can't grow above the limit if( limit > 0 && @@ -509,8 +457,7 @@ if( bb==null ) { if( desiredSize < 256 ) desiredSize=256; // take a minimum - //buff=new byte[desiredSize]; - bb=ByteBuffer.allocate(desiredSize); + bb=ByteBuffer.allocate(desiredSize); } // limit < buf.length ( the buffer is already big ) @@ -523,29 +470,26 @@ newSize= bb.capacity() * 2; if( limit >0 && newSize > limit ) newSize=limit; - tmp=ByteBuffer.allocate(newSize); } else { newSize= bb.capacity() * 2 + count ; if( limit > 0 && newSize > limit ) newSize=limit; - tmp=ByteBuffer.allocate(newSize); } + tmp=ByteBuffer.allocate(newSize); - //System.arraycopy(buff, start, tmp, 0, end-start); - tmp.put(bb); + System.arraycopy(bb.array(), start, tmp.array(), 0, end-start); bb = tmp; tmp = null; - //end=end-start; - bb.position(0); - //start=0; + end=end-start; + start=0; } // -------------------- Conversion and getters -------------------- public String toString() { - if (null == bb) { + if (null == bb.array()) { return null; - } else if (bb.remaining() == 0) { + } else if (end-start == 0) { return ""; } return StringCache.toString(this); @@ -555,7 +499,7 @@ String strValue=null; try { if( enc==null ) enc=DEFAULT_CHARACTER_ENCODING; - strValue = new String( bb.array(), bb.position(), bb.remaining(), enc ); + strValue = new String( bb.array(), start, end-start, enc ); /* Does not improve the speed too much on most systems, it's safer to use the "clasical" new String(). @@ -571,18 +515,18 @@ } catch (java.io.UnsupportedEncodingException e) { // Use the platform encoding in that case; the usage of a bad // encoding will have been logged elsewhere already - strValue = new String(bb.array(), bb.position(), bb.remaining()); + strValue = new String(bb.array(), start, end-start); } return strValue; } public int getInt() { - return Ascii.parseInt(bb.array(), bb.position(),bb.remaining()); + return Ascii.parseInt(bb.array(), start,end-start); } public long getLong() { - return Ascii.parseLong(bb.array(), bb.position(),bb.remaining()); + return Ascii.parseLong(bb.array(), start,end-start); } @@ -598,11 +542,11 @@ // ( ok for tomcat, where we compare ascii - header names, etc )!!! byte[] b = bb.array(); - int blen = bb.remaining(); + int blen = end-start; if (b == null || blen != s.length()) { return false; } - int boff = bb.position(); + int boff = start; for (int i = 0; i < blen; i++) { if (b[boff++] != s.charAt(i)) { return false; @@ -618,11 +562,11 @@ */ public boolean equalsIgnoreCase(String s) { byte[] b = bb.array(); - int blen = bb.remaining(); + int blen = end-start; if (b == null || blen != s.length()) { return false; } - int boff = bb.position(); + int boff = start; for (int i = 0; i < blen; i++) { if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) { return false; @@ -639,11 +583,11 @@ byte b1[]=bb.array(); if( b1==null && b2==null ) return true; - int len=bb.remaining(); + int len=end-start; if ( len2 != len || b1==null || b2==null ) return false; - int off1 = bb.position(); + int off1 = start; while ( len-- > 0) { if (b1[off1++] != b2[off2++]) { @@ -662,11 +606,11 @@ byte b1[]=bb.array(); if( c2==null && b1==null ) return true; - if (b1== null || c2==null || bb.remaining() != len2 ) { + if (b1== null || c2==null || end-start != len2 ) { return false; } - int off1 = bb.position(); - int len=bb.remaining(); + int off1 = start; + int len=end-start; while ( len-- > 0) { if ( (char)b1[off1++] != c2[off2++]) { @@ -684,10 +628,10 @@ // Works only if enc==UTF byte[] b = bb.array(); int blen = s.length(); - if (b == null || blen > bb.remaining()) { + if (b == null || blen > end-start) { return false; } - int boff = bb.position(); + int boff = start; for (int i = 0; i < blen; i++) { if (b[boff++] != s.charAt(i)) { return false; @@ -703,11 +647,11 @@ return true; } - int len = bb.remaining(); + int len = end - start; if (b1 == null || b2 == null || b2.length > len) { return false; } - for (int i = bb.position(), j = 0; i < bb.limit() && j < b2.length; ) { + for (int i = start, j = 0; i < end && j < b2.length; ) { if (b1[i++] != b2[j++]) return false; } @@ -722,10 +666,10 @@ public boolean startsWithIgnoreCase(String s, int pos) { byte[] b = bb.array(); int len = s.length(); - if (b == null || len+pos > bb.remaining()) { + if (b == null || len+pos > end-start) { return false; } - int off = bb.position()+pos; + int off = start+pos; for (int i = 0; i < len; i++) { if (Ascii.toLower( b[off++] ) != Ascii.toLower( s.charAt(i))) { return false; @@ -740,14 +684,14 @@ // Look for first char int srcEnd = srcOff + srcLen; - for( int i=myOff+bb.position(); i <= (bb.limit() - srcLen); i++ ) { + for( int i=myOff+start; i <= (end - srcLen); i++ ) { if( bb.get(i) != first ) continue; // found first char, now look for a match int myPos=i+1; for( int srcPos=srcOff + 1; srcPos< srcEnd; ) { if( bb.get(myPos++) != src.charAt( srcPos++ )) break; - if( srcPos==srcEnd ) return i-bb.position(); // found it + if( srcPos==srcEnd ) return i-start; // found it } } return -1; @@ -757,12 +701,12 @@ // normal hash. public int hash() { - return hashBytes( bb.array(), bb.position(), bb.remaining()); + return hashBytes( bb.array(), start, end-start); } // hash ignoring case public int hashIgnoreCase() { - return hashBytesIC( bb.array(), bb.position(), bb.remaining() ); + return hashBytesIC( bb.array(), start, end-start ); } private static int hashBytes( byte buff[], int start, int bytesLen ) { @@ -793,8 +737,8 @@ * @param starting The start position */ public int indexOf(char c, int starting) { - int ret = indexOf( bb.array(), bb.position()+starting, bb.limit(), c); - return (ret >= bb.position()) ? ret - bb.position() : -1; + int ret = indexOf( bb.array(), start+starting, end, c); + return (ret >= start) ? ret - start : -1; } public static int indexOf( byte bytes[], int off, int end, char qq ) --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]