0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: *
0019: */
0020: package org.apache.mina.common;
0021:
0022: import java.io.EOFException;
0023: import java.io.IOException;
0024: import java.io.InputStream;
0025: import java.io.ObjectInputStream;
0026: import java.io.ObjectOutputStream;
0027: import java.io.ObjectStreamClass;
0028: import java.io.OutputStream;
0029: import java.io.StreamCorruptedException;
0030: import java.nio.BufferOverflowException;
0031: import java.nio.BufferUnderflowException;
0032: import java.nio.ByteBuffer;
0033: import java.nio.ByteOrder;
0034: import java.nio.CharBuffer;
0035: import java.nio.DoubleBuffer;
0036: import java.nio.FloatBuffer;
0037: import java.nio.IntBuffer;
0038: import java.nio.LongBuffer;
0039: import java.nio.ShortBuffer;
0040: import java.nio.charset.CharacterCodingException;
0041: import java.nio.charset.CharsetDecoder;
0042: import java.nio.charset.CharsetEncoder;
0043: import java.nio.charset.CoderResult;
0044: import java.util.EnumSet;
0045: import java.util.Set;
0046:
0047: /**
0048: * A base implementation of {@link IoBuffer}. This implementation
0049: * assumes that {@link IoBuffer#buf()} always returns a correct NIO
0050: * {@link ByteBuffer} instance. Most implementations could
0051: * extend this class and implement their own buffer management mechanism.
0052: *
0053: * @author The Apache MINA Project (dev@mina.apache.org)
0054: * @version $Rev: 611312 $, $Date: 2008-01-11 14:59:43 -0700 (Fri, 11 Jan 2008) $
0055: * @see IoBufferAllocator
0056: */
0057: public abstract class AbstractIoBuffer extends IoBuffer {
0058:
0059: private final IoBufferAllocator allocator;
0060: private final boolean derived;
0061: private boolean autoExpand;
0062: private boolean autoShrink;
0063: private boolean recapacityAllowed = true;
0064: private int minimumCapacity;
0065:
0066: /**
0067: * We don't have any access to Buffer.markValue(), so we need to track it down,
0068: * which will cause small extra overhead.
0069: */
0070: private int mark = -1;
0071:
0072: /**
0073: * Creates a new parent buffer.
0074: */
0075: protected AbstractIoBuffer(IoBufferAllocator allocator,
0076: int initialCapacity) {
0077: this .allocator = allocator;
0078: this .recapacityAllowed = true;
0079: this .derived = false;
0080: this .minimumCapacity = initialCapacity;
0081: }
0082:
0083: /**
0084: * Creates a new derived buffer.
0085: */
0086: protected AbstractIoBuffer(AbstractIoBuffer parent) {
0087: this .allocator = parent.allocator;
0088: this .recapacityAllowed = false;
0089: this .derived = true;
0090: this .minimumCapacity = parent.minimumCapacity;
0091: }
0092:
0093: @Override
0094: public final boolean isDirect() {
0095: return buf().isDirect();
0096: }
0097:
0098: @Override
0099: public final boolean isReadOnly() {
0100: return buf().isReadOnly();
0101: }
0102:
0103: /**
0104: * Sets the underlying NIO buffer instance.
0105: */
0106: protected abstract void buf(ByteBuffer newBuf);
0107:
0108: @Override
0109: public final int minimumCapacity() {
0110: return minimumCapacity;
0111: }
0112:
0113: @Override
0114: public final IoBuffer minimumCapacity(int minimumCapacity) {
0115: if (minimumCapacity < 0) {
0116: throw new IllegalArgumentException("minimumCapacity: "
0117: + minimumCapacity);
0118: }
0119: this .minimumCapacity = minimumCapacity;
0120: return this ;
0121: }
0122:
0123: @Override
0124: public final int capacity() {
0125: return buf().capacity();
0126: }
0127:
0128: @Override
0129: public final IoBuffer capacity(int newCapacity) {
0130: if (!recapacityAllowed) {
0131: throw new IllegalStateException(
0132: "Derived buffers and their parent can't be expanded.");
0133: }
0134:
0135: // Allocate a new buffer and transfer all settings to it.
0136: if (newCapacity > capacity()) {
0137: // Expand:
0138: //// Save the state.
0139: int pos = position();
0140: int limit = limit();
0141: ByteOrder bo = order();
0142:
0143: //// Reallocate.
0144: ByteBuffer oldBuf = buf();
0145: ByteBuffer newBuf = allocator.allocateNioBuffer(
0146: newCapacity, isDirect());
0147: oldBuf.clear();
0148: newBuf.put(oldBuf);
0149: buf(newBuf);
0150:
0151: //// Restore the state.
0152: buf().limit(limit);
0153: if (mark >= 0) {
0154: buf().position(mark);
0155: buf().mark();
0156: }
0157: buf().position(pos);
0158: buf().order(bo);
0159: }
0160:
0161: return this ;
0162: }
0163:
0164: @Override
0165: public final boolean isAutoExpand() {
0166: return autoExpand && recapacityAllowed;
0167: }
0168:
0169: @Override
0170: public final boolean isAutoShrink() {
0171: return autoShrink && recapacityAllowed;
0172: }
0173:
0174: @Override
0175: public final boolean isDerived() {
0176: return derived;
0177: }
0178:
0179: @Override
0180: public final IoBuffer setAutoExpand(boolean autoExpand) {
0181: if (!recapacityAllowed) {
0182: throw new IllegalStateException(
0183: "Derived buffers and their parent can't be expanded.");
0184: }
0185: this .autoExpand = autoExpand;
0186: return this ;
0187: }
0188:
0189: @Override
0190: public final IoBuffer setAutoShrink(boolean autoShrink) {
0191: if (!recapacityAllowed) {
0192: throw new IllegalStateException(
0193: "Derived buffers and their parent can't be shrinked.");
0194: }
0195: this .autoShrink = autoShrink;
0196: return this ;
0197: }
0198:
0199: @Override
0200: public final IoBuffer expand(int expectedRemaining) {
0201: return expand(position(), expectedRemaining);
0202: }
0203:
0204: @Override
0205: public final IoBuffer expand(int pos, int expectedRemaining) {
0206: if (!recapacityAllowed) {
0207: throw new IllegalStateException(
0208: "Derived buffers and their parent can't be expanded.");
0209: }
0210:
0211: int end = pos + expectedRemaining;
0212: if (end > capacity()) {
0213: // The buffer needs expansion.
0214: capacity(end);
0215: }
0216:
0217: if (end > limit()) {
0218: // We call limit() directly to prevent StackOverflowError
0219: buf().limit(end);
0220: }
0221: return this ;
0222: }
0223:
0224: @Override
0225: public final IoBuffer shrink() {
0226:
0227: if (!recapacityAllowed) {
0228: throw new IllegalStateException(
0229: "Derived buffers and their parent can't be expanded.");
0230: }
0231:
0232: int position = position();
0233: int capacity = capacity();
0234: int limit = limit();
0235: if (capacity == limit) {
0236: return this ;
0237: }
0238:
0239: int newCapacity = capacity;
0240: int minCapacity = Math.max(minimumCapacity, limit);
0241: for (;;) {
0242: if (newCapacity >>> 1 < minCapacity) {
0243: break;
0244: }
0245: newCapacity >>>= 1;
0246: }
0247:
0248: newCapacity = Math.max(minCapacity, newCapacity);
0249:
0250: if (newCapacity == capacity) {
0251: return this ;
0252: }
0253:
0254: // Shrink and compact:
0255: //// Save the state.
0256: ByteOrder bo = order();
0257:
0258: //// Reallocate.
0259: ByteBuffer oldBuf = buf();
0260: ByteBuffer newBuf = allocator.allocateNioBuffer(newCapacity,
0261: isDirect());
0262: oldBuf.position(0);
0263: oldBuf.limit(limit);
0264: newBuf.put(oldBuf);
0265: buf(newBuf);
0266:
0267: //// Restore the state.
0268: buf().position(position);
0269: buf().limit(limit);
0270: buf().order(bo);
0271: mark = -1;
0272:
0273: return this ;
0274: }
0275:
0276: @Override
0277: public final int position() {
0278: return buf().position();
0279: }
0280:
0281: @Override
0282: public final IoBuffer position(int newPosition) {
0283: autoExpand(newPosition, 0);
0284: buf().position(newPosition);
0285: if (mark > newPosition) {
0286: mark = -1;
0287: }
0288: return this ;
0289: }
0290:
0291: @Override
0292: public final int limit() {
0293: return buf().limit();
0294: }
0295:
0296: @Override
0297: public final IoBuffer limit(int newLimit) {
0298: autoExpand(newLimit, 0);
0299: buf().limit(newLimit);
0300: if (mark > newLimit) {
0301: mark = -1;
0302: }
0303: return this ;
0304: }
0305:
0306: @Override
0307: public final IoBuffer mark() {
0308: buf().mark();
0309: mark = position();
0310: return this ;
0311: }
0312:
0313: @Override
0314: public final int markValue() {
0315: return mark;
0316: }
0317:
0318: @Override
0319: public final IoBuffer reset() {
0320: buf().reset();
0321: return this ;
0322: }
0323:
0324: @Override
0325: public final IoBuffer clear() {
0326: buf().clear();
0327: mark = -1;
0328: return this ;
0329: }
0330:
0331: @Override
0332: public final IoBuffer sweep() {
0333: clear();
0334: return fillAndReset(remaining());
0335: }
0336:
0337: @Override
0338: public final IoBuffer sweep(byte value) {
0339: clear();
0340: return fillAndReset(value, remaining());
0341: }
0342:
0343: @Override
0344: public final IoBuffer flip() {
0345: buf().flip();
0346: mark = -1;
0347: return this ;
0348: }
0349:
0350: @Override
0351: public final IoBuffer rewind() {
0352: buf().rewind();
0353: mark = -1;
0354: return this ;
0355: }
0356:
0357: @Override
0358: public final int remaining() {
0359: return limit() - position();
0360: }
0361:
0362: @Override
0363: public final boolean hasRemaining() {
0364: return limit() > position();
0365: }
0366:
0367: @Override
0368: public final byte get() {
0369: return buf().get();
0370: }
0371:
0372: @Override
0373: public final short getUnsigned() {
0374: return (short) (get() & 0xff);
0375: }
0376:
0377: @Override
0378: public final IoBuffer put(byte b) {
0379: autoExpand(1);
0380: buf().put(b);
0381: return this ;
0382: }
0383:
0384: @Override
0385: public final byte get(int index) {
0386: return buf().get(index);
0387: }
0388:
0389: @Override
0390: public final short getUnsigned(int index) {
0391: return (short) (get(index) & 0xff);
0392: }
0393:
0394: @Override
0395: public final IoBuffer put(int index, byte b) {
0396: autoExpand(index, 1);
0397: buf().put(index, b);
0398: return this ;
0399: }
0400:
0401: @Override
0402: public final IoBuffer get(byte[] dst, int offset, int length) {
0403: buf().get(dst, offset, length);
0404: return this ;
0405: }
0406:
0407: @Override
0408: public final IoBuffer put(ByteBuffer src) {
0409: autoExpand(src.remaining());
0410: buf().put(src);
0411: return this ;
0412: }
0413:
0414: @Override
0415: public final IoBuffer put(byte[] src, int offset, int length) {
0416: autoExpand(length);
0417: buf().put(src, offset, length);
0418: return this ;
0419: }
0420:
0421: @Override
0422: public final IoBuffer compact() {
0423: int remaining = remaining();
0424: int capacity = capacity();
0425:
0426: if (capacity == 0) {
0427: return this ;
0428: }
0429:
0430: if (isAutoShrink() && remaining <= capacity >>> 2
0431: && capacity > minimumCapacity) {
0432: int newCapacity = capacity;
0433: int minCapacity = Math.max(minimumCapacity, remaining << 1);
0434: for (;;) {
0435: if (newCapacity >>> 1 < minCapacity) {
0436: break;
0437: }
0438: newCapacity >>>= 1;
0439: }
0440:
0441: newCapacity = Math.max(minCapacity, newCapacity);
0442:
0443: if (newCapacity == capacity) {
0444: return this ;
0445: }
0446:
0447: // Shrink and compact:
0448: //// Save the state.
0449: ByteOrder bo = order();
0450:
0451: //// Sanity check.
0452: if (remaining > newCapacity) {
0453: throw new IllegalStateException(
0454: "The amount of the remaining bytes is greater than "
0455: + "the new capacity.");
0456: }
0457:
0458: //// Reallocate.
0459: ByteBuffer oldBuf = buf();
0460: ByteBuffer newBuf = allocator.allocateNioBuffer(
0461: newCapacity, isDirect());
0462: newBuf.put(oldBuf);
0463: buf(newBuf);
0464:
0465: //// Restore the state.
0466: buf().order(bo);
0467: } else {
0468: buf().compact();
0469: }
0470: mark = -1;
0471: return this ;
0472: }
0473:
0474: @Override
0475: public final ByteOrder order() {
0476: return buf().order();
0477: }
0478:
0479: @Override
0480: public final IoBuffer order(ByteOrder bo) {
0481: buf().order(bo);
0482: return this ;
0483: }
0484:
0485: @Override
0486: public final char getChar() {
0487: return buf().getChar();
0488: }
0489:
0490: @Override
0491: public final IoBuffer putChar(char value) {
0492: autoExpand(2);
0493: buf().putChar(value);
0494: return this ;
0495: }
0496:
0497: @Override
0498: public final char getChar(int index) {
0499: return buf().getChar(index);
0500: }
0501:
0502: @Override
0503: public final IoBuffer putChar(int index, char value) {
0504: autoExpand(index, 2);
0505: buf().putChar(index, value);
0506: return this ;
0507: }
0508:
0509: @Override
0510: public final CharBuffer asCharBuffer() {
0511: return buf().asCharBuffer();
0512: }
0513:
0514: @Override
0515: public final short getShort() {
0516: return buf().getShort();
0517: }
0518:
0519: @Override
0520: public final IoBuffer putShort(short value) {
0521: autoExpand(2);
0522: buf().putShort(value);
0523: return this ;
0524: }
0525:
0526: @Override
0527: public final short getShort(int index) {
0528: return buf().getShort(index);
0529: }
0530:
0531: @Override
0532: public final IoBuffer putShort(int index, short value) {
0533: autoExpand(index, 2);
0534: buf().putShort(index, value);
0535: return this ;
0536: }
0537:
0538: @Override
0539: public final ShortBuffer asShortBuffer() {
0540: return buf().asShortBuffer();
0541: }
0542:
0543: @Override
0544: public final int getInt() {
0545: return buf().getInt();
0546: }
0547:
0548: @Override
0549: public final IoBuffer putInt(int value) {
0550: autoExpand(4);
0551: buf().putInt(value);
0552: return this ;
0553: }
0554:
0555: @Override
0556: public final int getInt(int index) {
0557: return buf().getInt(index);
0558: }
0559:
0560: @Override
0561: public final IoBuffer putInt(int index, int value) {
0562: autoExpand(index, 4);
0563: buf().putInt(index, value);
0564: return this ;
0565: }
0566:
0567: @Override
0568: public final IntBuffer asIntBuffer() {
0569: return buf().asIntBuffer();
0570: }
0571:
0572: @Override
0573: public final long getLong() {
0574: return buf().getLong();
0575: }
0576:
0577: @Override
0578: public final IoBuffer putLong(long value) {
0579: autoExpand(8);
0580: buf().putLong(value);
0581: return this ;
0582: }
0583:
0584: @Override
0585: public final long getLong(int index) {
0586: return buf().getLong(index);
0587: }
0588:
0589: @Override
0590: public final IoBuffer putLong(int index, long value) {
0591: autoExpand(index, 8);
0592: buf().putLong(index, value);
0593: return this ;
0594: }
0595:
0596: @Override
0597: public final LongBuffer asLongBuffer() {
0598: return buf().asLongBuffer();
0599: }
0600:
0601: @Override
0602: public final float getFloat() {
0603: return buf().getFloat();
0604: }
0605:
0606: @Override
0607: public final IoBuffer putFloat(float value) {
0608: autoExpand(4);
0609: buf().putFloat(value);
0610: return this ;
0611: }
0612:
0613: @Override
0614: public final float getFloat(int index) {
0615: return buf().getFloat(index);
0616: }
0617:
0618: @Override
0619: public final IoBuffer putFloat(int index, float value) {
0620: autoExpand(index, 4);
0621: buf().putFloat(index, value);
0622: return this ;
0623: }
0624:
0625: @Override
0626: public final FloatBuffer asFloatBuffer() {
0627: return buf().asFloatBuffer();
0628: }
0629:
0630: @Override
0631: public final double getDouble() {
0632: return buf().getDouble();
0633: }
0634:
0635: @Override
0636: public final IoBuffer putDouble(double value) {
0637: autoExpand(8);
0638: buf().putDouble(value);
0639: return this ;
0640: }
0641:
0642: @Override
0643: public final double getDouble(int index) {
0644: return buf().getDouble(index);
0645: }
0646:
0647: @Override
0648: public final IoBuffer putDouble(int index, double value) {
0649: autoExpand(index, 8);
0650: buf().putDouble(index, value);
0651: return this ;
0652: }
0653:
0654: @Override
0655: public final DoubleBuffer asDoubleBuffer() {
0656: return buf().asDoubleBuffer();
0657: }
0658:
0659: @Override
0660: public final IoBuffer asReadOnlyBuffer() {
0661: recapacityAllowed = false;
0662: return asReadOnlyBuffer0();
0663: }
0664:
0665: /**
0666: * Implement this method to return the unexpandable read only version of
0667: * this buffer.
0668: */
0669: protected abstract IoBuffer asReadOnlyBuffer0();
0670:
0671: @Override
0672: public final IoBuffer duplicate() {
0673: recapacityAllowed = false;
0674: return duplicate0();
0675: }
0676:
0677: /**
0678: * Implement this method to return the unexpandable duplicate of this
0679: * buffer.
0680: */
0681: protected abstract IoBuffer duplicate0();
0682:
0683: @Override
0684: public final IoBuffer slice() {
0685: recapacityAllowed = false;
0686: return slice0();
0687: }
0688:
0689: @Override
0690: public final IoBuffer getSlice(int index, int length) {
0691: if (length < 0) {
0692: throw new IllegalArgumentException("length: " + length);
0693: }
0694: int pos = position();
0695: int limit = limit();
0696: int endIndex = pos + length;
0697:
0698: if (capacity() < endIndex) {
0699: throw new IndexOutOfBoundsException("index + length ("
0700: + endIndex + ") is greater " + "than capacity ("
0701: + capacity() + ").");
0702: }
0703:
0704: clear();
0705: position(index);
0706: limit(endIndex);
0707:
0708: IoBuffer slice = slice();
0709: position(pos);
0710: limit(limit);
0711: return slice;
0712: }
0713:
0714: @Override
0715: public final IoBuffer getSlice(int length) {
0716: if (length < 0) {
0717: throw new IllegalArgumentException("length: " + length);
0718: }
0719: int pos = position();
0720: int limit = limit();
0721: int nextPos = pos + length;
0722: if (limit < nextPos) {
0723: throw new IndexOutOfBoundsException("position + length ("
0724: + nextPos + ") is greater " + "than limit ("
0725: + limit + ").");
0726: }
0727:
0728: limit(pos + length);
0729: IoBuffer slice = slice();
0730: position(nextPos);
0731: limit(limit);
0732: return slice;
0733: }
0734:
0735: /**
0736: * Implement this method to return the unexpandable slice of this
0737: * buffer.
0738: */
0739: protected abstract IoBuffer slice0();
0740:
0741: @Override
0742: public int hashCode() {
0743: int h = 1;
0744: int p = position();
0745: for (int i = limit() - 1; i >= p; i--) {
0746: h = 31 * h + get(i);
0747: }
0748: return h;
0749: }
0750:
0751: @Override
0752: public boolean equals(Object o) {
0753: if (!(o instanceof IoBuffer)) {
0754: return false;
0755: }
0756:
0757: IoBuffer that = (IoBuffer) o;
0758: if (this .remaining() != that.remaining()) {
0759: return false;
0760: }
0761:
0762: int p = this .position();
0763: for (int i = this .limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
0764: byte v1 = this .get(i);
0765: byte v2 = that.get(j);
0766: if (v1 != v2) {
0767: return false;
0768: }
0769: }
0770: return true;
0771: }
0772:
0773: public int compareTo(IoBuffer that) {
0774: int n = this .position()
0775: + Math.min(this .remaining(), that.remaining());
0776: for (int i = this .position(), j = that.position(); i < n; i++, j++) {
0777: byte v1 = this .get(i);
0778: byte v2 = that.get(j);
0779: if (v1 == v2) {
0780: continue;
0781: }
0782: if (v1 < v2) {
0783: return -1;
0784: }
0785:
0786: return +1;
0787: }
0788: return this .remaining() - that.remaining();
0789: }
0790:
0791: @Override
0792: public String toString() {
0793: StringBuffer buf = new StringBuffer();
0794: if (isDirect()) {
0795: buf.append("DirectBuffer");
0796: } else {
0797: buf.append("HeapBuffer");
0798: }
0799: buf.append("[pos=");
0800: buf.append(position());
0801: buf.append(" lim=");
0802: buf.append(limit());
0803: buf.append(" cap=");
0804: buf.append(capacity());
0805: buf.append(": ");
0806: buf.append(getHexDump(16));
0807: buf.append(']');
0808: return buf.toString();
0809: }
0810:
0811: @Override
0812: public IoBuffer get(byte[] dst) {
0813: return get(dst, 0, dst.length);
0814: }
0815:
0816: @Override
0817: public IoBuffer put(IoBuffer src) {
0818: return put(src.buf());
0819: }
0820:
0821: @Override
0822: public IoBuffer put(byte[] src) {
0823: return put(src, 0, src.length);
0824: }
0825:
0826: @Override
0827: public int getUnsignedShort() {
0828: return getShort() & 0xffff;
0829: }
0830:
0831: @Override
0832: public int getUnsignedShort(int index) {
0833: return getShort(index) & 0xffff;
0834: }
0835:
0836: @Override
0837: public long getUnsignedInt() {
0838: return getInt() & 0xffffffffL;
0839: }
0840:
0841: @Override
0842: public int getMediumInt() {
0843: byte b1 = get();
0844: byte b2 = get();
0845: byte b3 = get();
0846: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0847: return getMediumInt(b1, b2, b3);
0848: } else {
0849: return getMediumInt(b3, b2, b1);
0850: }
0851: }
0852:
0853: @Override
0854: public int getUnsignedMediumInt() {
0855: int b1 = getUnsigned();
0856: int b2 = getUnsigned();
0857: int b3 = getUnsigned();
0858: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0859: return b1 << 16 | b2 << 8 | b3;
0860: } else {
0861: return b3 << 16 | b2 << 8 | b1;
0862: }
0863: }
0864:
0865: @Override
0866: public int getMediumInt(int index) {
0867: byte b1 = get(index);
0868: byte b2 = get(index + 1);
0869: byte b3 = get(index + 2);
0870: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0871: return getMediumInt(b1, b2, b3);
0872: } else {
0873: return getMediumInt(b3, b2, b1);
0874: }
0875: }
0876:
0877: @Override
0878: public int getUnsignedMediumInt(int index) {
0879: int b1 = getUnsigned(index);
0880: int b2 = getUnsigned(index + 1);
0881: int b3 = getUnsigned(index + 2);
0882: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0883: return b1 << 16 | b2 << 8 | b3;
0884: } else {
0885: return b3 << 16 | b2 << 8 | b1;
0886: }
0887: }
0888:
0889: private int getMediumInt(byte b1, byte b2, byte b3) {
0890: int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
0891: // Check to see if the medium int is negative (high bit in b1 set)
0892: if ((b1 & 0x80) == 0x80) {
0893: // Make the the whole int negative
0894: ret |= 0xff000000;
0895: }
0896: return ret;
0897: }
0898:
0899: @Override
0900: public IoBuffer putMediumInt(int value) {
0901: byte b1 = (byte) (value >> 16);
0902: byte b2 = (byte) (value >> 8);
0903: byte b3 = (byte) value;
0904:
0905: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0906: put(b1).put(b2).put(b3);
0907: } else {
0908: put(b3).put(b2).put(b1);
0909: }
0910:
0911: return this ;
0912: }
0913:
0914: @Override
0915: public IoBuffer putMediumInt(int index, int value) {
0916: byte b1 = (byte) (value >> 16);
0917: byte b2 = (byte) (value >> 8);
0918: byte b3 = (byte) value;
0919:
0920: if (ByteOrder.BIG_ENDIAN.equals(order())) {
0921: put(index, b1).put(index + 1, b2).put(index + 2, b3);
0922: } else {
0923: put(index, b3).put(index + 1, b2).put(index + 2, b1);
0924: }
0925:
0926: return this ;
0927: }
0928:
0929: @Override
0930: public long getUnsignedInt(int index) {
0931: return getInt(index) & 0xffffffffL;
0932: }
0933:
0934: @Override
0935: public InputStream asInputStream() {
0936: return new InputStream() {
0937: @Override
0938: public int available() {
0939: return AbstractIoBuffer.this .remaining();
0940: }
0941:
0942: @Override
0943: public synchronized void mark(int readlimit) {
0944: AbstractIoBuffer.this .mark();
0945: }
0946:
0947: @Override
0948: public boolean markSupported() {
0949: return true;
0950: }
0951:
0952: @Override
0953: public int read() {
0954: if (AbstractIoBuffer.this .hasRemaining()) {
0955: return AbstractIoBuffer.this .get() & 0xff;
0956: } else {
0957: return -1;
0958: }
0959: }
0960:
0961: @Override
0962: public int read(byte[] b, int off, int len) {
0963: int remaining = AbstractIoBuffer.this .remaining();
0964: if (remaining > 0) {
0965: int readBytes = Math.min(remaining, len);
0966: AbstractIoBuffer.this .get(b, off, readBytes);
0967: return readBytes;
0968: } else {
0969: return -1;
0970: }
0971: }
0972:
0973: @Override
0974: public synchronized void reset() {
0975: AbstractIoBuffer.this .reset();
0976: }
0977:
0978: @Override
0979: public long skip(long n) {
0980: int bytes;
0981: if (n > Integer.MAX_VALUE) {
0982: bytes = AbstractIoBuffer.this .remaining();
0983: } else {
0984: bytes = Math.min(AbstractIoBuffer.this .remaining(),
0985: (int) n);
0986: }
0987: AbstractIoBuffer.this .skip(bytes);
0988: return bytes;
0989: }
0990: };
0991: }
0992:
0993: @Override
0994: public OutputStream asOutputStream() {
0995: return new OutputStream() {
0996: @Override
0997: public void write(byte[] b, int off, int len) {
0998: AbstractIoBuffer.this .put(b, off, len);
0999: }
1000:
1001: @Override
1002: public void write(int b) {
1003: AbstractIoBuffer.this .put((byte) b);
1004: }
1005: };
1006: }
1007:
1008: @Override
1009: public String getHexDump() {
1010: return this .getHexDump(Integer.MAX_VALUE);
1011: }
1012:
1013: @Override
1014: public String getHexDump(int lengthLimit) {
1015: return IoBufferHexDumper.getHexdump(this , lengthLimit);
1016: }
1017:
1018: @Override
1019: public String getString(CharsetDecoder decoder)
1020: throws CharacterCodingException {
1021: if (!hasRemaining()) {
1022: return "";
1023: }
1024:
1025: boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1026:
1027: int oldPos = position();
1028: int oldLimit = limit();
1029: int end = -1;
1030: int newPos;
1031:
1032: if (!utf16) {
1033: end = indexOf((byte) 0x00);
1034: if (end < 0) {
1035: newPos = end = oldLimit;
1036: } else {
1037: newPos = end + 1;
1038: }
1039: } else {
1040: int i = oldPos;
1041: for (;;) {
1042: boolean wasZero = get(i) == 0;
1043: i++;
1044:
1045: if (i >= oldLimit) {
1046: break;
1047: }
1048:
1049: if (get(i) != 0) {
1050: i++;
1051: if (i >= oldLimit) {
1052: break;
1053: } else {
1054: continue;
1055: }
1056: }
1057:
1058: if (wasZero) {
1059: end = i - 1;
1060: break;
1061: }
1062: }
1063:
1064: if (end < 0) {
1065: newPos = end = oldPos
1066: + (oldLimit - oldPos & 0xFFFFFFFE);
1067: } else {
1068: if (end + 2 <= oldLimit) {
1069: newPos = end + 2;
1070: } else {
1071: newPos = end;
1072: }
1073: }
1074: }
1075:
1076: if (oldPos == end) {
1077: position(newPos);
1078: return "";
1079: }
1080:
1081: limit(end);
1082: decoder.reset();
1083:
1084: int expectedLength = (int) (remaining() * decoder
1085: .averageCharsPerByte()) + 1;
1086: CharBuffer out = CharBuffer.allocate(expectedLength);
1087: for (;;) {
1088: CoderResult cr;
1089: if (hasRemaining()) {
1090: cr = decoder.decode(buf(), out, true);
1091: } else {
1092: cr = decoder.flush(out);
1093: }
1094:
1095: if (cr.isUnderflow()) {
1096: break;
1097: }
1098:
1099: if (cr.isOverflow()) {
1100: CharBuffer o = CharBuffer.allocate(out.capacity()
1101: + expectedLength);
1102: out.flip();
1103: o.put(out);
1104: out = o;
1105: continue;
1106: }
1107:
1108: if (cr.isError()) {
1109: // Revert the buffer back to the previous state.
1110: limit(oldLimit);
1111: position(oldPos);
1112: cr.throwException();
1113: }
1114: }
1115:
1116: limit(oldLimit);
1117: position(newPos);
1118: return out.flip().toString();
1119: }
1120:
1121: @Override
1122: public String getString(int fieldSize, CharsetDecoder decoder)
1123: throws CharacterCodingException {
1124: checkFieldSize(fieldSize);
1125:
1126: if (fieldSize == 0) {
1127: return "";
1128: }
1129:
1130: if (!hasRemaining()) {
1131: return "";
1132: }
1133:
1134: boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1135:
1136: if (utf16 && (fieldSize & 1) != 0) {
1137: throw new IllegalArgumentException("fieldSize is not even.");
1138: }
1139:
1140: int oldPos = position();
1141: int oldLimit = limit();
1142: int end = oldPos + fieldSize;
1143:
1144: if (oldLimit < end) {
1145: throw new BufferUnderflowException();
1146: }
1147:
1148: int i;
1149:
1150: if (!utf16) {
1151: for (i = oldPos; i < end; i++) {
1152: if (get(i) == 0) {
1153: break;
1154: }
1155: }
1156:
1157: if (i == end) {
1158: limit(end);
1159: } else {
1160: limit(i);
1161: }
1162: } else {
1163: for (i = oldPos; i < end; i += 2) {
1164: if (get(i) == 0 && get(i + 1) == 0) {
1165: break;
1166: }
1167: }
1168:
1169: if (i == end) {
1170: limit(end);
1171: } else {
1172: limit(i);
1173: }
1174: }
1175:
1176: if (!hasRemaining()) {
1177: limit(oldLimit);
1178: position(end);
1179: return "";
1180: }
1181: decoder.reset();
1182:
1183: int expectedLength = (int) (remaining() * decoder
1184: .averageCharsPerByte()) + 1;
1185: CharBuffer out = CharBuffer.allocate(expectedLength);
1186: for (;;) {
1187: CoderResult cr;
1188: if (hasRemaining()) {
1189: cr = decoder.decode(buf(), out, true);
1190: } else {
1191: cr = decoder.flush(out);
1192: }
1193:
1194: if (cr.isUnderflow()) {
1195: break;
1196: }
1197:
1198: if (cr.isOverflow()) {
1199: CharBuffer o = CharBuffer.allocate(out.capacity()
1200: + expectedLength);
1201: out.flip();
1202: o.put(out);
1203: out = o;
1204: continue;
1205: }
1206:
1207: if (cr.isError()) {
1208: // Revert the buffer back to the previous state.
1209: limit(oldLimit);
1210: position(oldPos);
1211: cr.throwException();
1212: }
1213: }
1214:
1215: limit(oldLimit);
1216: position(end);
1217: return out.flip().toString();
1218: }
1219:
1220: @Override
1221: public IoBuffer putString(CharSequence val, CharsetEncoder encoder)
1222: throws CharacterCodingException {
1223: if (val.length() == 0) {
1224: return this ;
1225: }
1226:
1227: CharBuffer in = CharBuffer.wrap(val);
1228: encoder.reset();
1229:
1230: int expandedState = 0;
1231:
1232: for (;;) {
1233: CoderResult cr;
1234: if (in.hasRemaining()) {
1235: cr = encoder.encode(in, buf(), true);
1236: } else {
1237: cr = encoder.flush(buf());
1238: }
1239:
1240: if (cr.isUnderflow()) {
1241: break;
1242: }
1243: if (cr.isOverflow()) {
1244: if (isAutoExpand()) {
1245: switch (expandedState) {
1246: case 0:
1247: autoExpand((int) Math.ceil(in.remaining()
1248: * encoder.averageBytesPerChar()));
1249: expandedState++;
1250: break;
1251: case 1:
1252: autoExpand((int) Math.ceil(in.remaining()
1253: * encoder.maxBytesPerChar()));
1254: expandedState++;
1255: break;
1256: default:
1257: throw new RuntimeException("Expanded by "
1258: + (int) Math.ceil(in.remaining()
1259: * encoder.maxBytesPerChar())
1260: + " but that wasn't enough for '" + val
1261: + "'");
1262: }
1263: continue;
1264: }
1265: } else {
1266: expandedState = 0;
1267: }
1268: cr.throwException();
1269: }
1270: return this ;
1271: }
1272:
1273: @Override
1274: public IoBuffer putString(CharSequence val, int fieldSize,
1275: CharsetEncoder encoder) throws CharacterCodingException {
1276: checkFieldSize(fieldSize);
1277:
1278: if (fieldSize == 0) {
1279: return this ;
1280: }
1281:
1282: autoExpand(fieldSize);
1283:
1284: boolean utf16 = encoder.charset().name().startsWith("UTF-16");
1285:
1286: if (utf16 && (fieldSize & 1) != 0) {
1287: throw new IllegalArgumentException("fieldSize is not even.");
1288: }
1289:
1290: int oldLimit = limit();
1291: int end = position() + fieldSize;
1292:
1293: if (oldLimit < end) {
1294: throw new BufferOverflowException();
1295: }
1296:
1297: if (val.length() == 0) {
1298: if (!utf16) {
1299: put((byte) 0x00);
1300: } else {
1301: put((byte) 0x00);
1302: put((byte) 0x00);
1303: }
1304: position(end);
1305: return this ;
1306: }
1307:
1308: CharBuffer in = CharBuffer.wrap(val);
1309: limit(end);
1310: encoder.reset();
1311:
1312: for (;;) {
1313: CoderResult cr;
1314: if (in.hasRemaining()) {
1315: cr = encoder.encode(in, buf(), true);
1316: } else {
1317: cr = encoder.flush(buf());
1318: }
1319:
1320: if (cr.isUnderflow() || cr.isOverflow()) {
1321: break;
1322: }
1323: cr.throwException();
1324: }
1325:
1326: limit(oldLimit);
1327:
1328: if (position() < end) {
1329: if (!utf16) {
1330: put((byte) 0x00);
1331: } else {
1332: put((byte) 0x00);
1333: put((byte) 0x00);
1334: }
1335: }
1336:
1337: position(end);
1338: return this ;
1339: }
1340:
1341: @Override
1342: public String getPrefixedString(CharsetDecoder decoder)
1343: throws CharacterCodingException {
1344: return getPrefixedString(2, decoder);
1345: }
1346:
1347: /**
1348: * Reads a string which has a length field before the actual
1349: * encoded string, using the specified <code>decoder</code> and returns it.
1350: *
1351: * @param prefixLength the length of the length field (1, 2, or 4)
1352: * @param decoder the decoder to use for decoding the string
1353: * @return the prefixed string
1354: * @throws CharacterCodingException when decoding fails
1355: * @throws BufferUnderflowException when there is not enough data available
1356: */
1357: @Override
1358: public String getPrefixedString(int prefixLength,
1359: CharsetDecoder decoder) throws CharacterCodingException {
1360: if (!prefixedDataAvailable(prefixLength)) {
1361: throw new BufferUnderflowException();
1362: }
1363:
1364: int fieldSize = 0;
1365:
1366: switch (prefixLength) {
1367: case 1:
1368: fieldSize = getUnsigned();
1369: break;
1370: case 2:
1371: fieldSize = getUnsignedShort();
1372: break;
1373: case 4:
1374: fieldSize = getInt();
1375: break;
1376: }
1377:
1378: if (fieldSize == 0) {
1379: return "";
1380: }
1381:
1382: boolean utf16 = decoder.charset().name().startsWith("UTF-16");
1383:
1384: if (utf16 && (fieldSize & 1) != 0) {
1385: throw new BufferDataException(
1386: "fieldSize is not even for a UTF-16 string.");
1387: }
1388:
1389: int oldLimit = limit();
1390: int end = position() + fieldSize;
1391:
1392: if (oldLimit < end) {
1393: throw new BufferUnderflowException();
1394: }
1395:
1396: limit(end);
1397: decoder.reset();
1398:
1399: int expectedLength = (int) (remaining() * decoder
1400: .averageCharsPerByte()) + 1;
1401: CharBuffer out = CharBuffer.allocate(expectedLength);
1402: for (;;) {
1403: CoderResult cr;
1404: if (hasRemaining()) {
1405: cr = decoder.decode(buf(), out, true);
1406: } else {
1407: cr = decoder.flush(out);
1408: }
1409:
1410: if (cr.isUnderflow()) {
1411: break;
1412: }
1413:
1414: if (cr.isOverflow()) {
1415: CharBuffer o = CharBuffer.allocate(out.capacity()
1416: + expectedLength);
1417: out.flip();
1418: o.put(out);
1419: out = o;
1420: continue;
1421: }
1422:
1423: cr.throwException();
1424: }
1425:
1426: limit(oldLimit);
1427: position(end);
1428: return out.flip().toString();
1429: }
1430:
1431: @Override
1432: public IoBuffer putPrefixedString(CharSequence in,
1433: CharsetEncoder encoder) throws CharacterCodingException {
1434: return putPrefixedString(in, 2, 0, encoder);
1435: }
1436:
1437: @Override
1438: public IoBuffer putPrefixedString(CharSequence in,
1439: int prefixLength, CharsetEncoder encoder)
1440: throws CharacterCodingException {
1441: return putPrefixedString(in, prefixLength, 0, encoder);
1442: }
1443:
1444: @Override
1445: public IoBuffer putPrefixedString(CharSequence in,
1446: int prefixLength, int padding, CharsetEncoder encoder)
1447: throws CharacterCodingException {
1448: return putPrefixedString(in, prefixLength, padding, (byte) 0,
1449: encoder);
1450: }
1451:
1452: @Override
1453: public IoBuffer putPrefixedString(CharSequence val,
1454: int prefixLength, int padding, byte padValue,
1455: CharsetEncoder encoder) throws CharacterCodingException {
1456: int maxLength;
1457: switch (prefixLength) {
1458: case 1:
1459: maxLength = 255;
1460: break;
1461: case 2:
1462: maxLength = 65535;
1463: break;
1464: case 4:
1465: maxLength = Integer.MAX_VALUE;
1466: break;
1467: default:
1468: throw new IllegalArgumentException("prefixLength: "
1469: + prefixLength);
1470: }
1471:
1472: if (val.length() > maxLength) {
1473: throw new IllegalArgumentException(
1474: "The specified string is too long.");
1475: }
1476: if (val.length() == 0) {
1477: switch (prefixLength) {
1478: case 1:
1479: put((byte) 0);
1480: break;
1481: case 2:
1482: putShort((short) 0);
1483: break;
1484: case 4:
1485: putInt(0);
1486: break;
1487: }
1488: return this ;
1489: }
1490:
1491: int padMask;
1492: switch (padding) {
1493: case 0:
1494: case 1:
1495: padMask = 0;
1496: break;
1497: case 2:
1498: padMask = 1;
1499: break;
1500: case 4:
1501: padMask = 3;
1502: break;
1503: default:
1504: throw new IllegalArgumentException("padding: " + padding);
1505: }
1506:
1507: CharBuffer in = CharBuffer.wrap(val);
1508: int expectedLength = (int) (in.remaining() * encoder
1509: .averageBytesPerChar()) + 1;
1510:
1511: skip(prefixLength); // make a room for the length field
1512: int oldPos = position();
1513: encoder.reset();
1514:
1515: for (;;) {
1516: CoderResult cr;
1517: if (in.hasRemaining()) {
1518: cr = encoder.encode(in, buf(), true);
1519: } else {
1520: cr = encoder.flush(buf());
1521: }
1522:
1523: if (position() - oldPos > maxLength) {
1524: throw new IllegalArgumentException(
1525: "The specified string is too long.");
1526: }
1527:
1528: if (cr.isUnderflow()) {
1529: break;
1530: }
1531: if (cr.isOverflow() && isAutoExpand()) {
1532: autoExpand(expectedLength);
1533: continue;
1534: }
1535: cr.throwException();
1536: }
1537:
1538: // Write the length field
1539: fill(padValue, padding - (position() - oldPos & padMask));
1540: int length = position() - oldPos;
1541: switch (prefixLength) {
1542: case 1:
1543: put(oldPos - 1, (byte) length);
1544: break;
1545: case 2:
1546: putShort(oldPos - 2, (short) length);
1547: break;
1548: case 4:
1549: putInt(oldPos - 4, length);
1550: break;
1551: }
1552: return this ;
1553: }
1554:
1555: @Override
1556: public Object getObject() throws ClassNotFoundException {
1557: return getObject(Thread.currentThread().getContextClassLoader());
1558: }
1559:
1560: @Override
1561: public Object getObject(final ClassLoader classLoader)
1562: throws ClassNotFoundException {
1563: if (!prefixedDataAvailable(4)) {
1564: throw new BufferUnderflowException();
1565: }
1566:
1567: int length = getInt();
1568: if (length <= 4) {
1569: throw new BufferDataException(
1570: "Object length should be greater than 4: " + length);
1571: }
1572:
1573: int oldLimit = limit();
1574: limit(position() + length);
1575: try {
1576: ObjectInputStream in = new ObjectInputStream(
1577: asInputStream()) {
1578: @Override
1579: protected ObjectStreamClass readClassDescriptor()
1580: throws IOException, ClassNotFoundException {
1581: int type = read();
1582: if (type < 0) {
1583: throw new EOFException();
1584: }
1585: switch (type) {
1586: case 0: // Primitive types
1587: return super .readClassDescriptor();
1588: case 1: // Non-primitive types
1589: String className = readUTF();
1590: Class<?> clazz = Class.forName(className, true,
1591: classLoader);
1592: return ObjectStreamClass.lookup(clazz);
1593: default:
1594: throw new StreamCorruptedException(
1595: "Unexpected class descriptor type: "
1596: + type);
1597: }
1598: }
1599:
1600: @Override
1601: protected Class<?> resolveClass(ObjectStreamClass desc)
1602: throws IOException, ClassNotFoundException {
1603: String name = desc.getName();
1604: try {
1605: return Class.forName(name, false, classLoader);
1606: } catch (ClassNotFoundException ex) {
1607: return super .resolveClass(desc);
1608: }
1609: }
1610: };
1611: return in.readObject();
1612: } catch (IOException e) {
1613: throw new BufferDataException(e);
1614: } finally {
1615: limit(oldLimit);
1616: }
1617: }
1618:
1619: @Override
1620: public IoBuffer putObject(Object o) {
1621: int oldPos = position();
1622: skip(4); // Make a room for the length field.
1623: try {
1624: ObjectOutputStream out = new ObjectOutputStream(
1625: asOutputStream()) {
1626: @Override
1627: protected void writeClassDescriptor(
1628: ObjectStreamClass desc) throws IOException {
1629: String className = desc.getName();
1630: if (primitiveTypeNames.contains(className)) {
1631: write(0);
1632: super .writeClassDescriptor(desc);
1633: } else {
1634: write(1);
1635: writeUTF(desc.getName());
1636: }
1637: }
1638: };
1639: out.writeObject(o);
1640: out.flush();
1641: } catch (IOException e) {
1642: throw new BufferDataException(e);
1643: }
1644:
1645: // Fill the length field
1646: int newPos = position();
1647: position(oldPos);
1648: putInt(newPos - oldPos - 4);
1649: position(newPos);
1650: return this ;
1651: }
1652:
1653: @Override
1654: public boolean prefixedDataAvailable(int prefixLength) {
1655: return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
1656: }
1657:
1658: @Override
1659: public boolean prefixedDataAvailable(int prefixLength,
1660: int maxDataLength) {
1661: if (remaining() < prefixLength) {
1662: return false;
1663: }
1664:
1665: int dataLength;
1666: switch (prefixLength) {
1667: case 1:
1668: dataLength = getUnsigned(position());
1669: break;
1670: case 2:
1671: dataLength = getUnsignedShort(position());
1672: break;
1673: case 4:
1674: dataLength = getInt(position());
1675: break;
1676: default:
1677: throw new IllegalArgumentException("prefixLength: "
1678: + prefixLength);
1679: }
1680:
1681: if (dataLength < 0 || dataLength > maxDataLength) {
1682: throw new BufferDataException("dataLength: " + dataLength);
1683: }
1684:
1685: return remaining() - prefixLength >= dataLength;
1686: }
1687:
1688: @Override
1689: public int indexOf(byte b) {
1690: if (hasArray()) {
1691: int arrayOffset = arrayOffset();
1692: int beginPos = arrayOffset + position();
1693: int limit = arrayOffset + limit();
1694: byte[] array = array();
1695:
1696: for (int i = beginPos; i < limit; i++) {
1697: if (array[i] == b) {
1698: return i - arrayOffset;
1699: }
1700: }
1701: } else {
1702: int beginPos = position();
1703: int limit = limit();
1704:
1705: for (int i = beginPos; i < limit; i++) {
1706: if (get(i) == b) {
1707: return i;
1708: }
1709: }
1710: }
1711:
1712: return -1;
1713: }
1714:
1715: @Override
1716: public IoBuffer skip(int size) {
1717: autoExpand(size);
1718: return position(position() + size);
1719: }
1720:
1721: @Override
1722: public IoBuffer fill(byte value, int size) {
1723: autoExpand(size);
1724: int q = size >>> 3;
1725: int r = size & 7;
1726:
1727: if (q > 0) {
1728: int intValue = value | value << 8 | value << 16
1729: | value << 24;
1730: long longValue = intValue;
1731: longValue <<= 32;
1732: longValue |= intValue;
1733:
1734: for (int i = q; i > 0; i--) {
1735: putLong(longValue);
1736: }
1737: }
1738:
1739: q = r >>> 2;
1740: r = r & 3;
1741:
1742: if (q > 0) {
1743: int intValue = value | value << 8 | value << 16
1744: | value << 24;
1745: putInt(intValue);
1746: }
1747:
1748: q = r >> 1;
1749: r = r & 1;
1750:
1751: if (q > 0) {
1752: short shortValue = (short) (value | value << 8);
1753: putShort(shortValue);
1754: }
1755:
1756: if (r > 0) {
1757: put(value);
1758: }
1759:
1760: return this ;
1761: }
1762:
1763: @Override
1764: public IoBuffer fillAndReset(byte value, int size) {
1765: autoExpand(size);
1766: int pos = position();
1767: try {
1768: fill(value, size);
1769: } finally {
1770: position(pos);
1771: }
1772: return this ;
1773: }
1774:
1775: @Override
1776: public IoBuffer fill(int size) {
1777: autoExpand(size);
1778: int q = size >>> 3;
1779: int r = size & 7;
1780:
1781: for (int i = q; i > 0; i--) {
1782: putLong(0L);
1783: }
1784:
1785: q = r >>> 2;
1786: r = r & 3;
1787:
1788: if (q > 0) {
1789: putInt(0);
1790: }
1791:
1792: q = r >> 1;
1793: r = r & 1;
1794:
1795: if (q > 0) {
1796: putShort((short) 0);
1797: }
1798:
1799: if (r > 0) {
1800: put((byte) 0);
1801: }
1802:
1803: return this ;
1804: }
1805:
1806: @Override
1807: public IoBuffer fillAndReset(int size) {
1808: autoExpand(size);
1809: int pos = position();
1810: try {
1811: fill(size);
1812: } finally {
1813: position(pos);
1814: }
1815:
1816: return this ;
1817: }
1818:
1819: private static final long BYTE_MASK = 0xFFL;
1820: private static final long SHORT_MASK = 0xFFFFL;
1821: private static final long INT_MASK = 0xFFFFFFFFL;
1822:
1823: @Override
1824: public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
1825: return toEnum(enumClass, get());
1826: }
1827:
1828: @Override
1829: public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
1830: return toEnum(enumClass, get(index));
1831: }
1832:
1833: @Override
1834: public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
1835: return toEnum(enumClass, getShort());
1836: }
1837:
1838: @Override
1839: public <E extends Enum<E>> E getEnumShort(int index,
1840: Class<E> enumClass) {
1841: return toEnum(enumClass, getShort(index));
1842: }
1843:
1844: @Override
1845: public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
1846: return toEnum(enumClass, getInt());
1847: }
1848:
1849: @Override
1850: public <E extends Enum<E>> E getEnumInt(int index,
1851: Class<E> enumClass) {
1852: return toEnum(enumClass, getInt(index));
1853: }
1854:
1855: @Override
1856: public IoBuffer putEnum(Enum<?> e) {
1857: if (e.ordinal() > Byte.MAX_VALUE) {
1858: throw new IllegalArgumentException(
1859: enumConversionErrorMessage(e, "byte"));
1860: }
1861: return put((byte) e.ordinal());
1862: }
1863:
1864: @Override
1865: public IoBuffer putEnum(int index, Enum<?> e) {
1866: if (e.ordinal() > Byte.MAX_VALUE) {
1867: throw new IllegalArgumentException(
1868: enumConversionErrorMessage(e, "byte"));
1869: }
1870: return put(index, (byte) e.ordinal());
1871: }
1872:
1873: @Override
1874: public IoBuffer putEnumShort(Enum<?> e) {
1875: if (e.ordinal() > Short.MAX_VALUE) {
1876: throw new IllegalArgumentException(
1877: enumConversionErrorMessage(e, "short"));
1878: }
1879: return putShort((short) e.ordinal());
1880: }
1881:
1882: @Override
1883: public IoBuffer putEnumShort(int index, Enum<?> e) {
1884: if (e.ordinal() > Short.MAX_VALUE) {
1885: throw new IllegalArgumentException(
1886: enumConversionErrorMessage(e, "short"));
1887: }
1888: return putShort(index, (short) e.ordinal());
1889: }
1890:
1891: @Override
1892: public IoBuffer putEnumInt(Enum<?> e) {
1893: return putInt(e.ordinal());
1894: }
1895:
1896: @Override
1897: public IoBuffer putEnumInt(int index, Enum<?> e) {
1898: return putInt(index, e.ordinal());
1899: }
1900:
1901: private <E> E toEnum(Class<E> enumClass, int i) {
1902: E[] enumConstants = enumClass.getEnumConstants();
1903: if (i > enumConstants.length) {
1904: throw new IndexOutOfBoundsException(
1905: String
1906: .format(
1907: "%d is too large of an ordinal to convert to the enum %s",
1908: i, enumClass.getName()));
1909: }
1910: return enumConstants[i];
1911: }
1912:
1913: private String enumConversionErrorMessage(Enum<?> e, String type) {
1914: return String.format(
1915: "%s.%s has an ordinal value too large for a %s", e
1916: .getClass().getName(), e.name(), type);
1917: }
1918:
1919: @Override
1920: public <E extends Enum<E>> EnumSet<E> getEnumSet(Class<E> enumClass) {
1921: return toEnumSet(enumClass, get() & BYTE_MASK);
1922: }
1923:
1924: @Override
1925: public <E extends Enum<E>> EnumSet<E> getEnumSet(int index,
1926: Class<E> enumClass) {
1927: return toEnumSet(enumClass, get(index) & BYTE_MASK);
1928: }
1929:
1930: @Override
1931: public <E extends Enum<E>> EnumSet<E> getEnumSetShort(
1932: Class<E> enumClass) {
1933: return toEnumSet(enumClass, getShort() & SHORT_MASK);
1934: }
1935:
1936: @Override
1937: public <E extends Enum<E>> EnumSet<E> getEnumSetShort(int index,
1938: Class<E> enumClass) {
1939: return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
1940: }
1941:
1942: @Override
1943: public <E extends Enum<E>> EnumSet<E> getEnumSetInt(
1944: Class<E> enumClass) {
1945: return toEnumSet(enumClass, getInt() & INT_MASK);
1946: }
1947:
1948: @Override
1949: public <E extends Enum<E>> EnumSet<E> getEnumSetInt(int index,
1950: Class<E> enumClass) {
1951: return toEnumSet(enumClass, getInt(index) & INT_MASK);
1952: }
1953:
1954: @Override
1955: public <E extends Enum<E>> EnumSet<E> getEnumSetLong(
1956: Class<E> enumClass) {
1957: return toEnumSet(enumClass, getLong());
1958: }
1959:
1960: @Override
1961: public <E extends Enum<E>> EnumSet<E> getEnumSetLong(int index,
1962: Class<E> enumClass) {
1963: return toEnumSet(enumClass, getLong(index));
1964: }
1965:
1966: private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz,
1967: long vector) {
1968: EnumSet<E> set = EnumSet.noneOf(clazz);
1969: long mask = 1;
1970: for (E e : clazz.getEnumConstants()) {
1971: if ((mask & vector) == mask) {
1972: set.add(e);
1973: }
1974: mask <<= 1;
1975: }
1976: return set;
1977: }
1978:
1979: @Override
1980: public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
1981: long vector = toLong(set);
1982: if ((vector & ~BYTE_MASK) != 0) {
1983: throw new IllegalArgumentException(
1984: "The enum set is too large to fit in a byte: "
1985: + set);
1986: }
1987: return put((byte) vector);
1988: }
1989:
1990: @Override
1991: public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
1992: long vector = toLong(set);
1993: if ((vector & ~BYTE_MASK) != 0) {
1994: throw new IllegalArgumentException(
1995: "The enum set is too large to fit in a byte: "
1996: + set);
1997: }
1998: return put(index, (byte) vector);
1999: }
2000:
2001: @Override
2002: public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
2003: long vector = toLong(set);
2004: if ((vector & ~SHORT_MASK) != 0) {
2005: throw new IllegalArgumentException(
2006: "The enum set is too large to fit in a short: "
2007: + set);
2008: }
2009: return putShort((short) vector);
2010: }
2011:
2012: @Override
2013: public <E extends Enum<E>> IoBuffer putEnumSetShort(int index,
2014: Set<E> set) {
2015: long vector = toLong(set);
2016: if ((vector & ~SHORT_MASK) != 0) {
2017: throw new IllegalArgumentException(
2018: "The enum set is too large to fit in a short: "
2019: + set);
2020: }
2021: return putShort(index, (short) vector);
2022: }
2023:
2024: @Override
2025: public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
2026: long vector = toLong(set);
2027: if ((vector & ~INT_MASK) != 0) {
2028: throw new IllegalArgumentException(
2029: "The enum set is too large to fit in an int: "
2030: + set);
2031: }
2032: return putInt((int) vector);
2033: }
2034:
2035: @Override
2036: public <E extends Enum<E>> IoBuffer putEnumSetInt(int index,
2037: Set<E> set) {
2038: long vector = toLong(set);
2039: if ((vector & ~INT_MASK) != 0) {
2040: throw new IllegalArgumentException(
2041: "The enum set is too large to fit in an int: "
2042: + set);
2043: }
2044: return putInt(index, (int) vector);
2045: }
2046:
2047: @Override
2048: public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
2049: return putLong(toLong(set));
2050: }
2051:
2052: @Override
2053: public <E extends Enum<E>> IoBuffer putEnumSetLong(int index,
2054: Set<E> set) {
2055: return putLong(index, toLong(set));
2056: }
2057:
2058: private <E extends Enum<E>> long toLong(Set<E> set) {
2059: long vector = 0;
2060: for (E e : set) {
2061: if (e.ordinal() >= Long.SIZE) {
2062: throw new IllegalArgumentException(
2063: "The enum set is too large to fit in a bit vector: "
2064: + set);
2065: }
2066: vector |= 1L << e.ordinal();
2067: }
2068: return vector;
2069: }
2070:
2071: /**
2072: * This method forwards the call to {@link #expand(int)} only when
2073: * <tt>autoExpand</tt> property is <tt>true</tt>.
2074: */
2075: private IoBuffer autoExpand(int expectedRemaining) {
2076: if (isAutoExpand()) {
2077: expand(expectedRemaining);
2078: }
2079: return this ;
2080: }
2081:
2082: /**
2083: * This method forwards the call to {@link #expand(int)} only when
2084: * <tt>autoExpand</tt> property is <tt>true</tt>.
2085: */
2086: private IoBuffer autoExpand(int pos, int expectedRemaining) {
2087: if (isAutoExpand()) {
2088: expand(pos, expectedRemaining);
2089: }
2090: return this ;
2091: }
2092:
2093: private static void checkFieldSize(int fieldSize) {
2094: if (fieldSize < 0) {
2095: throw new IllegalArgumentException(
2096: "fieldSize cannot be negative: " + fieldSize);
2097: }
2098: }
2099: }
|