/* * Copyright 2014 NAVER Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.navercorp.pinpoint.common.buffer; import com.navercorp.pinpoint.common.util.BytesUtils; /** * Buffer that can be expanded automatically * @author emeroad */ public class AutomaticBuffer extends FixedBuffer { public AutomaticBuffer() { super(32); } public AutomaticBuffer(final int size) { super(size); } public AutomaticBuffer(final byte[] buffer) { super(buffer); } protected void checkExpand(final int size) { final int remain = remaining(); if (remain >= size) { return; } int length = buffer.length; if (length == 0) { length = 1; } // after compute the buffer size, allocate it once for ado. final int expandedBufferSize = computeExpandedBufferSize(size, length, remain); // allocate buffer final byte[] expandedBuffer = new byte[expandedBufferSize]; System.arraycopy(buffer, 0, expandedBuffer, 0, buffer.length); buffer = expandedBuffer; } protected int computeExpandedBufferSize(final int size, int length, int remain) { int expandedBufferSize = 0; while (remain < size) { length <<= 1; expandedBufferSize = length; remain = expandedBufferSize - offset; } return expandedBufferSize; } @Override public void putPadBytes(byte[] bytes, int totalLength) { checkExpand(totalLength); super.putPadBytes(bytes, totalLength); } @Override public void putPrefixedBytes(final byte[] bytes) { if (bytes == null) { checkExpand(1); super.putSVInt(NULL); } else { checkExpand(bytes.length + BytesUtils.VINT_MAX_SIZE); super.putSVInt(bytes.length); super.putBytes(bytes); } } @Override public void put2PrefixedBytes(final byte[] bytes) { if (bytes == null) { checkExpand(BytesUtils.SHORT_BYTE_LENGTH); super.putShort((short)NULL); } else { if (bytes.length > Short.MAX_VALUE) { throw new IndexOutOfBoundsException("too large bytes length:" + bytes.length); } checkExpand(bytes.length + BytesUtils.SHORT_BYTE_LENGTH); super.putShort((short)bytes.length); super.putBytes(bytes); } } @Override public void put4PrefixedBytes(final byte[] bytes) { if (bytes == null) { checkExpand(BytesUtils.INT_BYTE_LENGTH); super.putInt(NULL); } else { checkExpand(bytes.length + BytesUtils.INT_BYTE_LENGTH); super.putInt(bytes.length); super.putBytes(bytes); } } @Override public void putPadString(String string, int totalLength) { checkExpand(totalLength); super.putPadString(string, totalLength); } @Override public void putPrefixedString(final String string) { byte[] bytes = BytesUtils.toBytes(string); this.putPrefixedBytes(bytes); } @Override public void put2PrefixedString(final String string) { byte[] bytes = BytesUtils.toBytes(string); this.put2PrefixedBytes(bytes); } @Override public void put4PrefixedString(final String string) { byte[] bytes = BytesUtils.toBytes(string); this.put4PrefixedBytes(bytes); } @Override public void putByte(final byte v) { checkExpand(1); super.putByte(v); } @Override public void putBoolean(final boolean v) { checkExpand(1); super.putBoolean(v); } @Override public void putShort(final short v) { checkExpand(2); super.putShort(v); } @Override public void putInt(final int v) { checkExpand(4); super.putInt(v); } @Override public void putVInt(final int v) { checkExpand(BytesUtils.VLONG_MAX_SIZE); super.putVInt(v); } @Override public void putSVInt(final int v) { checkExpand(BytesUtils.VINT_MAX_SIZE); super.putSVInt(v); } @Override public void putVLong(final long v) { checkExpand(BytesUtils.VLONG_MAX_SIZE); super.putVLong(v); } @Override public void putSVLong(final long v) { checkExpand(BytesUtils.VLONG_MAX_SIZE); super.putSVLong(v); } @Override public void putLong(final long v) { checkExpand(8); super.putLong(v); } @Override public void putBytes(final byte[] v) { if (v == null) { throw new NullPointerException("v must not be null"); } checkExpand(v.length); super.putBytes(v); } }