You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by pr...@apache.org on 2008/03/19 19:36:53 UTC
svn commit: r638965 - in /mina/trunk/core/src:
main/java/org/apache/mina/common/AbstractIoBuffer.java
test/java/org/apache/mina/common/IoBufferTest.java
Author: proyal
Date: Wed Mar 19 11:36:43 2008
New Revision: 638965
URL: http://svn.apache.org/viewvc?rev=638965&view=rev
Log:
DIRMINA-557 - Apply smart expanding logic to putPrefixedString as well.
Modified:
mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoBuffer.java
mina/trunk/core/src/test/java/org/apache/mina/common/IoBufferTest.java
Modified: mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoBuffer.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoBuffer.java?rev=638965&r1=638964&r2=638965&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoBuffer.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/AbstractIoBuffer.java Wed Mar 19 11:36:43 2008
@@ -56,7 +56,7 @@
* @see IoBufferAllocator
*/
public abstract class AbstractIoBuffer extends IoBuffer {
-
+
private final IoBufferAllocator allocator;
private final boolean derived;
private boolean autoExpand;
@@ -80,7 +80,7 @@
this.derived = false;
this.minimumCapacity = initialCapacity;
}
-
+
/**
* Creates a new derived buffer.
*/
@@ -110,7 +110,7 @@
public final int minimumCapacity() {
return minimumCapacity;
}
-
+
@Override
public final IoBuffer minimumCapacity(int minimumCapacity) {
if (minimumCapacity < 0) {
@@ -143,7 +143,7 @@
//// Reallocate.
ByteBuffer oldBuf = buf();
- ByteBuffer newBuf =
+ ByteBuffer newBuf =
allocator.allocateNioBuffer(newCapacity, isDirect());
oldBuf.clear();
newBuf.put(oldBuf);
@@ -158,7 +158,7 @@
buf().position(pos);
buf().order(bo);
}
-
+
return this;
}
@@ -166,12 +166,12 @@
public final boolean isAutoExpand() {
return autoExpand && recapacityAllowed;
}
-
+
@Override
public final boolean isAutoShrink() {
return autoShrink && recapacityAllowed;
}
-
+
@Override
public final boolean isDerived() {
return derived;
@@ -201,7 +201,7 @@
public final IoBuffer expand(int expectedRemaining) {
return expand(position(), expectedRemaining, false);
}
-
+
private IoBuffer expand(int expectedRemaining, boolean autoExpand) {
return expand(position(), expectedRemaining, autoExpand);
}
@@ -210,7 +210,7 @@
public final IoBuffer expand(int pos, int expectedRemaining) {
return expand(pos, expectedRemaining, false);
}
-
+
private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) {
if (!recapacityAllowed) {
throw new IllegalStateException(
@@ -235,7 +235,7 @@
}
return this;
}
-
+
@Override
public final IoBuffer shrink() {
@@ -243,7 +243,7 @@
throw new IllegalStateException(
"Derived buffers and their parent can't be expanded.");
}
-
+
int position = position();
int capacity = capacity();
int limit = limit();
@@ -259,9 +259,9 @@
}
newCapacity >>>= 1;
}
-
+
newCapacity = Math.max(minCapacity, newCapacity);
-
+
if (newCapacity == capacity) {
return this;
}
@@ -272,19 +272,19 @@
//// Reallocate.
ByteBuffer oldBuf = buf();
- ByteBuffer newBuf =
+ ByteBuffer newBuf =
allocator.allocateNioBuffer(newCapacity, isDirect());
oldBuf.position(0);
oldBuf.limit(limit);
newBuf.put(oldBuf);
buf(newBuf);
-
+
//// Restore the state.
buf().position(position);
buf().limit(limit);
buf().order(bo);
mark = -1;
-
+
return this;
}
@@ -354,7 +354,7 @@
clear();
return fillAndReset(value, remaining());
}
-
+
@Override
public final IoBuffer flip() {
buf().flip();
@@ -373,7 +373,7 @@
public final int remaining() {
return limit() - position();
}
-
+
@Override
public final boolean hasRemaining() {
return limit() > position();
@@ -437,7 +437,7 @@
public final IoBuffer compact() {
int remaining = remaining();
int capacity = capacity();
-
+
if (capacity == 0) {
return this;
}
@@ -451,9 +451,9 @@
}
newCapacity >>>= 1;
}
-
+
newCapacity = Math.max(minCapacity, newCapacity);
-
+
if (newCapacity == capacity) {
return this;
}
@@ -471,11 +471,11 @@
//// Reallocate.
ByteBuffer oldBuf = buf();
- ByteBuffer newBuf =
+ ByteBuffer newBuf =
allocator.allocateNioBuffer(newCapacity, isDirect());
newBuf.put(oldBuf);
buf(newBuf);
-
+
//// Restore the state.
buf().order(bo);
} else {
@@ -699,7 +699,7 @@
recapacityAllowed = false;
return slice0();
}
-
+
@Override
public final IoBuffer getSlice(int index, int length) {
if (length < 0) {
@@ -738,7 +738,7 @@
"position + length (" + nextPos + ") is greater " +
"than limit (" + limit + ").");
}
-
+
limit(pos + length);
IoBuffer slice = slice();
position(nextPos);
@@ -751,7 +751,7 @@
* buffer.
*/
protected abstract IoBuffer slice0();
-
+
@Override
public int hashCode() {
int h = 1;
@@ -761,7 +761,7 @@
}
return h;
}
-
+
@Override
public boolean equals(Object o) {
if (!(o instanceof IoBuffer)) {
@@ -914,13 +914,13 @@
byte b1 = (byte) (value >> 16);
byte b2 = (byte) (value >> 8);
byte b3 = (byte) value;
-
+
if (ByteOrder.BIG_ENDIAN.equals(order())) {
put(b1).put(b2).put(b3);
} else {
put(b3).put(b2).put(b1);
}
-
+
return this;
}
@@ -929,13 +929,13 @@
byte b1 = (byte) (value >> 16);
byte b2 = (byte) (value >> 8);
byte b3 = (byte) value;
-
+
if (ByteOrder.BIG_ENDIAN.equals(order())) {
put(index, b1).put(index + 1, b2).put(index + 2, b3);
} else {
put(index, b3).put(index + 1, b2).put(index + 2, b1);
}
-
+
return this;
}
@@ -951,17 +951,17 @@
public int available() {
return AbstractIoBuffer.this.remaining();
}
-
+
@Override
public synchronized void mark(int readlimit) {
AbstractIoBuffer.this.mark();
}
-
+
@Override
public boolean markSupported() {
return true;
}
-
+
@Override
public int read() {
if (AbstractIoBuffer.this.hasRemaining()) {
@@ -970,7 +970,7 @@
return -1;
}
}
-
+
@Override
public int read(byte[] b, int off, int len) {
int remaining = AbstractIoBuffer.this.remaining();
@@ -982,12 +982,12 @@
return -1;
}
}
-
+
@Override
public synchronized void reset() {
AbstractIoBuffer.this.reset();
}
-
+
@Override
public long skip(long n) {
int bytes;
@@ -1009,7 +1009,7 @@
public void write(byte[] b, int off, int len) {
AbstractIoBuffer.this.put(b, off, len);
}
-
+
@Override
public void write(int b) {
AbstractIoBuffer.this.put((byte) b);
@@ -1032,14 +1032,14 @@
if (!hasRemaining()) {
return "";
}
-
+
boolean utf16 = decoder.charset().name().startsWith("UTF-16");
-
+
int oldPos = position();
int oldLimit = limit();
int end = -1;
int newPos;
-
+
if (!utf16) {
end = indexOf((byte) 0x00);
if (end < 0) {
@@ -1052,11 +1052,11 @@
for (;;) {
boolean wasZero = get(i) == 0;
i++;
-
+
if (i >= oldLimit) {
break;
}
-
+
if (get(i) != 0) {
i++;
if (i >= oldLimit) {
@@ -1065,13 +1065,13 @@
continue;
}
}
-
+
if (wasZero) {
end = i - 1;
break;
}
}
-
+
if (end < 0) {
newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
} else {
@@ -1082,15 +1082,15 @@
}
}
}
-
+
if (oldPos == end) {
position(newPos);
return "";
}
-
+
limit(end);
decoder.reset();
-
+
int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
CharBuffer out = CharBuffer.allocate(expectedLength);
for (;;) {
@@ -1100,11 +1100,11 @@
} else {
cr = decoder.flush(out);
}
-
+
if (cr.isUnderflow()) {
break;
}
-
+
if (cr.isOverflow()) {
CharBuffer o = CharBuffer.allocate(out.capacity()
+ expectedLength);
@@ -1113,7 +1113,7 @@
out = o;
continue;
}
-
+
if (cr.isError()) {
// Revert the buffer back to the previous state.
limit(oldLimit);
@@ -1121,7 +1121,7 @@
cr.throwException();
}
}
-
+
limit(oldLimit);
position(newPos);
return out.flip().toString();
@@ -1131,38 +1131,38 @@
public String getString(int fieldSize, CharsetDecoder decoder)
throws CharacterCodingException {
checkFieldSize(fieldSize);
-
+
if (fieldSize == 0) {
return "";
}
-
+
if (!hasRemaining()) {
return "";
}
-
+
boolean utf16 = decoder.charset().name().startsWith("UTF-16");
-
+
if (utf16 && (fieldSize & 1) != 0) {
throw new IllegalArgumentException("fieldSize is not even.");
}
-
+
int oldPos = position();
int oldLimit = limit();
int end = oldPos + fieldSize;
-
+
if (oldLimit < end) {
throw new BufferUnderflowException();
}
-
+
int i;
-
+
if (!utf16) {
for (i = oldPos; i < end; i++) {
if (get(i) == 0) {
break;
}
}
-
+
if (i == end) {
limit(end);
} else {
@@ -1174,21 +1174,21 @@
break;
}
}
-
+
if (i == end) {
limit(end);
} else {
limit(i);
}
}
-
+
if (!hasRemaining()) {
limit(oldLimit);
position(end);
return "";
}
decoder.reset();
-
+
int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
CharBuffer out = CharBuffer.allocate(expectedLength);
for (;;) {
@@ -1198,11 +1198,11 @@
} else {
cr = decoder.flush(out);
}
-
+
if (cr.isUnderflow()) {
break;
}
-
+
if (cr.isOverflow()) {
CharBuffer o = CharBuffer.allocate(out.capacity()
+ expectedLength);
@@ -1211,7 +1211,7 @@
out = o;
continue;
}
-
+
if (cr.isError()) {
// Revert the buffer back to the previous state.
limit(oldLimit);
@@ -1219,7 +1219,7 @@
cr.throwException();
}
}
-
+
limit(oldLimit);
position(end);
return out.flip().toString();
@@ -1231,12 +1231,12 @@
if (val.length() == 0) {
return this;
}
-
+
CharBuffer in = CharBuffer.wrap(val);
encoder.reset();
-
+
int expandedState = 0;
-
+
for (;;) {
CoderResult cr;
if (in.hasRemaining()) {
@@ -1244,7 +1244,7 @@
} else {
cr = encoder.flush(buf());
}
-
+
if (cr.isUnderflow()) {
break;
}
@@ -1281,26 +1281,26 @@
public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder)
throws CharacterCodingException {
checkFieldSize(fieldSize);
-
+
if (fieldSize == 0) {
return this;
}
-
+
autoExpand(fieldSize);
-
+
boolean utf16 = encoder.charset().name().startsWith("UTF-16");
-
+
if (utf16 && (fieldSize & 1) != 0) {
throw new IllegalArgumentException("fieldSize is not even.");
}
-
+
int oldLimit = limit();
int end = position() + fieldSize;
-
+
if (oldLimit < end) {
throw new BufferOverflowException();
}
-
+
if (val.length() == 0) {
if (!utf16) {
put((byte) 0x00);
@@ -1311,11 +1311,11 @@
position(end);
return this;
}
-
+
CharBuffer in = CharBuffer.wrap(val);
limit(end);
encoder.reset();
-
+
for (;;) {
CoderResult cr;
if (in.hasRemaining()) {
@@ -1323,15 +1323,15 @@
} else {
cr = encoder.flush(buf());
}
-
+
if (cr.isUnderflow() || cr.isOverflow()) {
break;
}
cr.throwException();
}
-
+
limit(oldLimit);
-
+
if (position() < end) {
if (!utf16) {
put((byte) 0x00);
@@ -1340,7 +1340,7 @@
put((byte) 0x00);
}
}
-
+
position(end);
return this;
}
@@ -1367,9 +1367,9 @@
if (!prefixedDataAvailable(prefixLength)) {
throw new BufferUnderflowException();
}
-
+
int fieldSize = 0;
-
+
switch (prefixLength) {
case 1:
fieldSize = getUnsigned();
@@ -1381,28 +1381,28 @@
fieldSize = getInt();
break;
}
-
+
if (fieldSize == 0) {
return "";
}
-
+
boolean utf16 = decoder.charset().name().startsWith("UTF-16");
-
+
if (utf16 && (fieldSize & 1) != 0) {
throw new BufferDataException(
"fieldSize is not even for a UTF-16 string.");
}
-
+
int oldLimit = limit();
int end = position() + fieldSize;
-
+
if (oldLimit < end) {
throw new BufferUnderflowException();
}
-
+
limit(end);
decoder.reset();
-
+
int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
CharBuffer out = CharBuffer.allocate(expectedLength);
for (;;) {
@@ -1412,11 +1412,11 @@
} else {
cr = decoder.flush(out);
}
-
+
if (cr.isUnderflow()) {
break;
}
-
+
if (cr.isOverflow()) {
CharBuffer o = CharBuffer.allocate(out.capacity()
+ expectedLength);
@@ -1425,10 +1425,10 @@
out = o;
continue;
}
-
+
cr.throwException();
}
-
+
limit(oldLimit);
position(end);
return out.flip().toString();
@@ -1469,7 +1469,7 @@
default:
throw new IllegalArgumentException("prefixLength: " + prefixLength);
}
-
+
if (val.length() > maxLength) {
throw new IllegalArgumentException(
"The specified string is too long.");
@@ -1488,7 +1488,7 @@
}
return this;
}
-
+
int padMask;
switch (padding) {
case 0:
@@ -1504,15 +1504,14 @@
default:
throw new IllegalArgumentException("padding: " + padding);
}
-
+
CharBuffer in = CharBuffer.wrap(val);
- int expectedLength = (int) (in.remaining() * encoder
- .averageBytesPerChar()) + 1;
-
skip(prefixLength); // make a room for the length field
int oldPos = position();
encoder.reset();
-
+
+ int expandedState = 0;
+
for (;;) {
CoderResult cr;
if (in.hasRemaining()) {
@@ -1520,22 +1519,42 @@
} else {
cr = encoder.flush(buf());
}
-
+
if (position() - oldPos > maxLength) {
throw new IllegalArgumentException(
"The specified string is too long.");
}
-
+
if (cr.isUnderflow()) {
break;
}
- if (cr.isOverflow() && isAutoExpand()) {
- autoExpand(expectedLength);
- continue;
+ if (cr.isOverflow()) {
+ if (isAutoExpand()) {
+ switch (expandedState) {
+ case 0:
+ autoExpand((int) Math.ceil(in.remaining()
+ * encoder.averageBytesPerChar()));
+ expandedState++;
+ break;
+ case 1:
+ autoExpand((int) Math.ceil(in.remaining()
+ * encoder.maxBytesPerChar()));
+ expandedState++;
+ break;
+ default:
+ throw new RuntimeException("Expanded by "
+ + (int) Math.ceil(in.remaining()
+ * encoder.maxBytesPerChar())
+ + " but that wasn't enough for '" + val + "'");
+ }
+ continue;
+ }
+ } else {
+ expandedState = 0;
}
cr.throwException();
}
-
+
// Write the length field
fill(padValue, padding - (position() - oldPos & padMask));
int length = position() - oldPos;
@@ -1563,13 +1582,13 @@
if (!prefixedDataAvailable(4)) {
throw new BufferUnderflowException();
}
-
+
int length = getInt();
if (length <= 4) {
throw new BufferDataException(
"Object length should be greater than 4: " + length);
}
-
+
int oldLimit = limit();
limit(position() + length);
try {
@@ -1594,7 +1613,7 @@
"Unexpected class descriptor type: " + type);
}
}
-
+
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
String name = desc.getName();
@@ -1636,7 +1655,7 @@
} catch (IOException e) {
throw new BufferDataException(e);
}
-
+
// Fill the length field
int newPos = position();
position(oldPos);
@@ -1655,7 +1674,7 @@
if (remaining() < prefixLength) {
return false;
}
-
+
int dataLength;
switch (prefixLength) {
case 1:
@@ -1670,11 +1689,11 @@
default:
throw new IllegalArgumentException("prefixLength: " + prefixLength);
}
-
+
if (dataLength < 0 || dataLength > maxDataLength) {
throw new BufferDataException("dataLength: " + dataLength);
}
-
+
return remaining() - prefixLength >= dataLength;
}
@@ -1685,7 +1704,7 @@
int beginPos = arrayOffset + position();
int limit = arrayOffset + limit();
byte[] array = array();
-
+
for (int i = beginPos; i < limit; i++) {
if (array[i] == b) {
return i - arrayOffset;
@@ -1694,14 +1713,14 @@
} else {
int beginPos = position();
int limit = limit();
-
+
for (int i = beginPos; i < limit; i++) {
if (get(i) == b) {
return i;
}
}
}
-
+
return -1;
}
@@ -1716,38 +1735,38 @@
autoExpand(size);
int q = size >>> 3;
int r = size & 7;
-
+
if (q > 0) {
int intValue = value | value << 8 | value << 16 | value << 24;
long longValue = intValue;
longValue <<= 32;
longValue |= intValue;
-
+
for (int i = q; i > 0; i--) {
putLong(longValue);
}
}
-
+
q = r >>> 2;
r = r & 3;
-
+
if (q > 0) {
int intValue = value | value << 8 | value << 16 | value << 24;
putInt(intValue);
}
-
+
q = r >> 1;
r = r & 1;
-
+
if (q > 0) {
short shortValue = (short) (value | value << 8);
putShort(shortValue);
}
-
+
if (r > 0) {
put(value);
}
-
+
return this;
}
@@ -1768,29 +1787,29 @@
autoExpand(size);
int q = size >>> 3;
int r = size & 7;
-
+
for (int i = q; i > 0; i--) {
putLong(0L);
}
-
+
q = r >>> 2;
r = r & 3;
-
+
if (q > 0) {
putInt(0);
}
-
+
q = r >> 1;
r = r & 1;
-
+
if (q > 0) {
putShort((short) 0);
}
-
+
if (r > 0) {
put((byte) 0);
}
-
+
return this;
}
@@ -1803,7 +1822,7 @@
} finally {
position(pos);
}
-
+
return this;
}
Modified: mina/trunk/core/src/test/java/org/apache/mina/common/IoBufferTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/common/IoBufferTest.java?rev=638965&r1=638964&r2=638965&view=diff
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/common/IoBufferTest.java (original)
+++ mina/trunk/core/src/test/java/org/apache/mina/common/IoBufferTest.java Wed Mar 19 11:36:43 2008
@@ -127,14 +127,14 @@
buf.reset();
Assert.assertEquals(3, buf.position());
}
-
+
public void testAutoShrink() throws Exception {
IoBuffer buf = IoBuffer.allocate(8).setAutoShrink(true);
-
+
// Make sure the buffer doesn't shrink too much (less than the initial
// capacity.)
buf.sweep((byte) 1);
- buf.fill(7);
+ buf.fill(7);
buf.compact();
Assert.assertEquals(8, buf.capacity());
Assert.assertEquals(1, buf.position());
@@ -145,7 +145,7 @@
// Expand the buffer.
buf.capacity(32).clear();
Assert.assertEquals(32, buf.capacity());
-
+
// Make sure the buffer shrinks when only 1/4 is being used.
buf.sweep((byte) 1);
buf.fill(24);
@@ -161,7 +161,7 @@
// Expand the buffer.
buf.capacity(32).clear();
Assert.assertEquals(32, buf.capacity());
-
+
// Make sure the buffer shrinks when only 1/8 is being used.
buf.sweep((byte) 1);
buf.fill(28);
@@ -177,7 +177,7 @@
// Expand the buffer.
buf.capacity(32).clear();
Assert.assertEquals(32, buf.capacity());
-
+
// Make sure the buffer shrinks when 0 byte is being used.
buf.fill(32);
buf.compact();
@@ -188,7 +188,7 @@
// Expand the buffer.
buf.capacity(32).clear();
Assert.assertEquals(32, buf.capacity());
-
+
// Make sure the buffer doesn't shrink when more than 1/4 is being used.
buf.sweep((byte) 1);
buf.fill(23);
@@ -525,6 +525,7 @@
for (int i = 0; i < 5; i++) {
try {
buffer.putString("\u89d2", encoder);
+ buffer.putPrefixedString("\u89d2", encoder);
} catch (CharacterCodingException e) {
fail(e.getMessage());
}