// ********************************************************************** // // Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** package IceInternal; // // An instance of java.nio.ByteBuffer cannot grow beyond its initial capacity. // This class wraps a ByteBuffer and supports reallocation. // public class Buffer { public Buffer(int maxCapacity, boolean direct) { b = _emptyBuffer; _size = 0; _capacity = 0; _maxCapacity = maxCapacity; _direct = direct; } public int size() { return _size; } public boolean empty() { return _size == 0; } public void clear() { b = _emptyBuffer; _size = 0; _capacity = 0; } // // Call expand(n) to add room for n additional bytes. Note that expand() // examines the current position of the buffer first; we don't want to // expand the buffer if the caller is writing to a location that is // already in the buffer. // public void expand(int n) { final int sz = (b == _emptyBuffer) ? n : b.position() + n; if(sz > _size) { resize(sz, false); } } public void resize(int n, boolean reading) { if(n == 0) { clear(); } else if(n > _capacity) { reserve(n); } _size = n; // // When used for reading, we want to set the buffer's limit to the new size. // if(reading) { b.limit(_size); } } public void reset() { if(_size > 0 && _size * 2 < _capacity) { // // If the current buffer size is smaller than the // buffer capacity, we shrink the buffer memory to the // current size. This is to avoid holding on to too much // memory if it's not needed anymore. // if(++_shrinkCounter > 2) { reserve(_size); _shrinkCounter = 0; } } else { _shrinkCounter = 0; } _size = 0; if(b != _emptyBuffer) { b.limit(b.capacity()); b.position(0); } } private void reserve(int n) { if(n > _capacity) { _capacity = java.lang.Math.max(n, java.lang.Math.min(2 * _capacity, _maxCapacity)); _capacity = java.lang.Math.max(240, _capacity); } else if(n < _capacity) { _capacity = n; } else { return; } try { java.nio.ByteBuffer buf; if(_direct) { buf = java.nio.ByteBuffer.allocateDirect(_capacity); } else { buf = java.nio.ByteBuffer.allocate(_capacity); } if(b == _emptyBuffer) { b = buf; } else { final int pos = b.position(); b.position(0); b.limit(java.lang.Math.min(_capacity, b.capacity())); buf.put(b); b = buf; b.limit(b.capacity()); b.position(pos); } b.order(java.nio.ByteOrder.LITTLE_ENDIAN); } catch(OutOfMemoryError ex) { Ice.MarshalException e = new Ice.MarshalException(); e.reason = "OutOfMemoryError occurred while allocating a ByteBuffer"; e.initCause(ex); throw e; } } public java.nio.ByteBuffer b; // Sentinel used for null buffer. public java.nio.ByteBuffer _emptyBuffer = java.nio.ByteBuffer.allocate(0); private int _size; private int _capacity; // Cache capacity to avoid excessive method calls. private int _maxCapacity; private boolean _direct; // Use direct buffers? private int _shrinkCounter; }