org.eclipse.jetty.io.AbstractBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
*
*
*/
public abstract class AbstractBuffer implements Buffer
{
private static final Logger LOG = Log.getLogger(AbstractBuffer.class);
private final static boolean __boundsChecking = Boolean.getBoolean("org.eclipse.jetty.io.AbstractBuffer.boundsChecking");
protected final static String
__IMMUTABLE = "IMMUTABLE",
__READONLY = "READONLY",
__READWRITE = "READWRITE",
__VOLATILE = "VOLATILE";
protected int _access;
protected boolean _volatile;
protected int _get;
protected int _put;
protected int _hash;
protected int _hashGet;
protected int _hashPut;
protected int _mark;
protected String _string;
protected View _view;
/**
* Constructor for BufferView
*
* @param access 0==IMMUTABLE, 1==READONLY, 2==READWRITE
*/
public AbstractBuffer(int access, boolean isVolatile)
{
if (access == IMMUTABLE && isVolatile)
throw new IllegalArgumentException("IMMUTABLE && VOLATILE");
setMarkIndex(-1);
_access = access;
_volatile = isVolatile;
}
/*
* @see org.eclipse.io.Buffer#toArray()
*/
public byte[] asArray()
{
byte[] bytes = new byte[length()];
byte[] array = array();
if (array != null)
System.arraycopy(array, getIndex(), bytes, 0, bytes.length);
else
peek(getIndex(), bytes, 0, length());
return bytes;
}
public ByteArrayBuffer duplicate(int access)
{
Buffer b=this.buffer();
if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve)
return new ByteArrayBuffer.CaseInsensitive(asArray(), 0, length(),access);
else
return new ByteArrayBuffer(asArray(), 0, length(), access);
}
/*
* @see org.eclipse.io.Buffer#asNonVolatile()
*/
public Buffer asNonVolatileBuffer()
{
if (!isVolatile()) return this;
return duplicate(_access);
}
public Buffer asImmutableBuffer()
{
if (isImmutable()) return this;
return duplicate(IMMUTABLE);
}
/*
* @see org.eclipse.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 duplicate(READWRITE);
}
return new View(b, markIndex(), getIndex(), putIndex(), _access);
}
public Buffer buffer()
{
return this;
}
public void clear()
{
setMarkIndex(-1);
setGetIndex(0);
setPutIndex(0);
}
public void compact()
{
if (isReadOnly()) throw new IllegalStateException(__READONLY);
int s = markIndex() >= 0 ? markIndex() : getIndex();
if (s > 0)
{
byte array[] = array();
int length = putIndex() - s;
if (length > 0)
{
if (array != null)
System.arraycopy(array(), s, array(), 0, length);
else
poke(0, peek(s, length));
}
if (markIndex() > 0) setMarkIndex(markIndex() - s);
setGetIndex(getIndex() - s);
setPutIndex(putIndex() - s);
}
}
@Override
public boolean equals(Object obj)
{
if (obj==this)
return true;
// reject non buffers;
if (obj == null || !(obj instanceof Buffer)) return false;
Buffer b = (Buffer) obj;
if (this instanceof Buffer.CaseInsensitve || b instanceof Buffer.CaseInsensitve)
return equalsIgnoreCase(b);
// reject different lengths
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;
}
// Nothing for it but to do the hard grind.
int get=getIndex();
int bi=b.putIndex();
for (int i = putIndex(); i-->get;)
{
byte b1 = peek(i);
byte b2 = b.peek(--bi);
if (b1 != b2) return false;
}
return true;
}
public boolean equalsIgnoreCase(Buffer b)
{
if (b==this)
return true;
// reject different lengths
if (b.length() != length()) return false;
// reject AbstractBuffer with different hash value
if (_hash != 0 && b instanceof AbstractBuffer)
{
AbstractBuffer ab = (AbstractBuffer) b;
if (ab._hash != 0 && _hash != ab._hash) return false;
}
// Nothing for it but to do the hard grind.
int get=getIndex();
int bi=b.putIndex();
byte[] array = array();
byte[] barray= b.array();
if (array!=null && barray!=null)
{
for (int i = putIndex(); i-->get;)
{
byte b1 = array[i];
byte b2 = barray[--bi];
if (b1 != b2)
{
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;
}
}
}
else
{
for (int i = putIndex(); i-->get;)
{
byte b1 = peek(i);
byte b2 = b.peek(--bi);
if (b1 != b2)
{
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;
}
public byte get()
{
return peek(_get++);
}
public int get(byte[] b, int offset, int length)
{
int gi = getIndex();
int l=length();
if (l==0)
return -1;
if (length>l)
length=l;
length = peek(gi, b, offset, length);
if (length>0)
setGetIndex(gi + length);
return length;
}
public Buffer get(int length)
{
int gi = getIndex();
Buffer view = peek(gi, length);
setGetIndex(gi + length);
return view;
}
public final int getIndex()
{
return _get;
}
public boolean hasContent()
{
return _put > _get;
}
@Override
public int hashCode()
{
if (_hash == 0 || _hashGet!=_get || _hashPut!=_put)
{
int get=getIndex();
byte[] array = array();
if (array==null)
{
for (int i = putIndex(); i-- >get;)
{
byte b = peek(i);
if ('a' <= b && b <= 'z')
b = (byte) (b - 'a' + 'A');
_hash = 31 * _hash + b;
}
}
else
{
for (int i = putIndex(); i-- >get;)
{
byte b = array[i];
if ('a' <= b && b <= 'z')
b = (byte) (b - 'a' + 'A');
_hash = 31 * _hash + b;
}
}
if (_hash == 0)
_hash = -1;
_hashGet=_get;
_hashPut=_put;
}
return _hash;
}
public boolean isImmutable()
{
return _access <= IMMUTABLE;
}
public boolean isReadOnly()
{
return _access <= READONLY;
}
public boolean isVolatile()
{
return _volatile;
}
public int length()
{
return _put - _get;
}
public void mark()
{
setMarkIndex(_get - 1);
}
public void mark(int offset)
{
setMarkIndex(_get + offset);
}
public int markIndex()
{
return _mark;
}
public byte peek()
{
return peek(_get);
}
public Buffer peek(int index, int length)
{
if (_view == null)
{
_view = new View(this, -1, index, index + length, isReadOnly() ? READONLY : READWRITE);
}
else
{
_view.update(this.buffer());
_view.setMarkIndex(-1);
_view.setGetIndex(0);
_view.setPutIndex(index + length);
_view.setGetIndex(index);
}
return _view;
}
public int poke(int index, Buffer src)
{
_hash=0;
/*
if (isReadOnly())
throw new IllegalStateException(__READONLY);
if (index < 0)
throw new IllegalArgumentException("index<0: " + index + "<0");
*/
int length=src.length();
if (index + length > capacity())
{
length=capacity()-index;
/*
if (length<0)
throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
*/
}
byte[] src_array = src.array();
byte[] dst_array = array();
if (src_array != null && dst_array != null)
System.arraycopy(src_array, src.getIndex(), dst_array, index, length);
else if (src_array != null)
{
int s=src.getIndex();
for (int i=0;i capacity())
{
length=capacity()-index;
/* if (length<0)
throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
*/
}
byte[] dst_array = array();
if (dst_array != null)
System.arraycopy(b, offset, dst_array, index, length);
else
{
int s=offset;
for (int i=0;i= 0) setGetIndex(markIndex());
}
public void rewind()
{
setGetIndex(0);
setMarkIndex(-1);
}
public void setGetIndex(int getIndex)
{
/* bounds checking
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (getIndex < 0)
throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0");
if (getIndex > putIndex())
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex());
*/
_get = getIndex;
_hash=0;
}
public void setMarkIndex(int index)
{
/*
if (index>=0 && isImmutable())
throw new IllegalStateException(__IMMUTABLE);
*/
_mark = index;
}
public void setPutIndex(int putIndex)
{
/* bounds checking
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (putIndex > capacity())
throw new IllegalArgumentException("putIndex>capacity: " + putIndex + ">" + capacity());
if (getIndex() > putIndex)
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex() + ">" + putIndex);
*/
_put = putIndex;
_hash=0;
}
public int skip(int n)
{
if (length() < n) n = length();
setGetIndex(getIndex() + n);
return n;
}
public Buffer slice()
{
return peek(getIndex(), length());
}
public Buffer sliceFromMark()
{
return sliceFromMark(getIndex() - markIndex() - 1);
}
public Buffer sliceFromMark(int length)
{
if (markIndex() < 0) return null;
Buffer view = peek(markIndex(), length);
setMarkIndex(-1);
return view;
}
public int space()
{
return capacity() - _put;
}
public String toDetailString()
{
StringBuilder buf = new StringBuilder();
buf.append("[");
buf.append(super.hashCode());
buf.append(",");
buf.append(this.buffer().hashCode());
buf.append(",m=");
buf.append(markIndex());
buf.append(",g=");
buf.append(getIndex());
buf.append(",p=");
buf.append(putIndex());
buf.append(",c=");
buf.append(capacity());
buf.append("]={");
if (markIndex() >= 0)
{
for (int i = markIndex(); i < getIndex(); i++)
{
byte b = peek(i);
TypeUtil.toHex(b,buf);
}
buf.append("}{");
}
int count = 0;
for (int i = getIndex(); i < putIndex(); i++)
{
byte b = peek(i);
TypeUtil.toHex(b,buf);
if (count++ == 50)
{
if (putIndex() - i > 20)
{
buf.append(" ... ");
i = putIndex() - 20;
}
}
}
buf.append('}');
return buf.toString();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
if (isImmutable())
{
if (_string == null)
_string = new String(asArray(), 0, length());
return _string;
}
return new String(asArray(), 0, length());
}
/* ------------------------------------------------------------ */
public String toString(String charset)
{
try
{
byte[] bytes=array();
if (bytes!=null)
return new String(bytes,getIndex(),length(),charset);
return new String(asArray(), 0, length(),charset);
}
catch(Exception e)
{
LOG.warn(e);
return new String(asArray(), 0, length());
}
}
/* ------------------------------------------------------------ */
public String toDebugString()
{
return getClass()+"@"+super.hashCode();
}
/* ------------------------------------------------------------ */
public void writeTo(OutputStream out)
throws IOException
{
byte[] array = array();
if (array!=null)
{
out.write(array,getIndex(),length());
}
else
{
int len = this.length();
byte[] buf=new byte[len>1024?1024:len];
int offset=_get;
while (len>0)
{
int l=peek(offset,buf,0,len>buf.length?buf.length:len);
out.write(buf,0,l);
offset+=l;
len-=l;
}
}
clear();
}
/* ------------------------------------------------------------ */
public int readFrom(InputStream in,int max) throws IOException
{
byte[] array = array();
int s=space();
if (s>max)
s=max;
if (array!=null)
{
int l=in.read(array,_put,s);
if (l>0)
_put+=l;
return l;
}
else
{
byte[] buf=new byte[s>1024?1024:s];
int total=0;
while (s>0)
{
int l=in.read(buf,0,buf.length);
if (l<0)
return total>0?total:-1;
int p=put(buf,0,l);
assert l==p;
s-=l;
}
return total;
}
}
}