// ByteBufferHolder.java /** * Copyright (C) 2008 10gen Inc. * * 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.mongodb.io; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public class ByteBufferHolder { public ByteBufferHolder(){ this( 1024 * 1024 * 1024 ); // 1gb } public ByteBufferHolder( int max ){ _max = max; } public byte get( int i ){ if ( i >= _pos ) throw new RuntimeException( "out of bounds" ); final int num = i / _bufSize; final int pos = i % _bufSize; return _buffers.get( num ).get( pos ); } public void get( int pos , byte b[] ){ for ( int i=0; i<b.length; i++ ) b[i] = get( i + pos ); } public void put( int i , byte val ){ if ( i >= _pos ) throw new RuntimeException( "out of bounds" ); final int num = i / _bufSize; final int pos = i % _bufSize; _buffers.get( num ).put( pos , val ); } public int position(){ return _pos; } public void position( int p ){ _pos = p; int num = _pos / _bufSize; int pos = _pos % _bufSize; while ( _buffers.size() <= num ) _addBucket(); ByteBuffer bb = _buffers.get( num ); bb.position( pos ); for ( int i=num+1; i<_buffers.size(); i++ ) _buffers.get( i ).position( 0 ); } public int remaining(){ return Integer.MAX_VALUE; } public void put( ByteBuffer in ){ while ( in.hasRemaining() ){ int num = _pos / _bufSize; if ( num >= _buffers.size() ) _addBucket(); ByteBuffer bb = _buffers.get( num ); final int canRead = Math.min( bb.remaining() , in.remaining() ); final int oldLimit = in.limit(); in.limit( in.position() + canRead ); bb.put( in ); in.limit( oldLimit ); _pos += canRead; } } private void _addBucket(){ if ( capacity() + _bufSize > _max ) throw new RuntimeException( "too big current:" + capacity() ); _buffers.add( ByteBuffer.allocateDirect( _bufSize ) ); } public int capacity(){ return _buffers.size() * _bufSize; } public String toString(){ StringBuilder buf = new StringBuilder(); buf.append( "{ ByteBufferHolder pos:" + _pos + " " ); for ( ByteBuffer bb : _buffers ) buf.append( bb ).append( " " ); return buf.append( "}" ).toString(); } List<ByteBuffer> _buffers = new ArrayList<ByteBuffer>(); int _pos = 0; final int _max; static final int _bufSize = 4096; }