/*
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * 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 org.apache.slide.webdav.logger;

import java.io.IOException;

import org.apache.slide.common.Domain;

/**
 * Un-synchronized byte buffer. We have methods to write and read from the
 * buffer, and helpers can convert various data formats.
 *
 * The idea is to minimize the number of buffers and the amount of copy from
 * layer to layer. It's _not_ premature optimization - it's the way things
 * should work.
 *
 * The Request and Response will use several buffers, same for the protocol
 * adapters.
 *
 * Note that the Buffer owns his byte[], while the Chunk is just a light
 * cursor.
 *
 *
 */


public class XByteBuffer {
    // everything happens inside one thread !!!
        
    protected static final int DEFAULT_BUFFER_SIZE = 8*1024;
    int defaultBufferSize = DEFAULT_BUFFER_SIZE;
    int bytesWritten = 0;

    /** The buffers
     */
    private byte buf[];
    private byte buf2[];

    /**
     * The index one greater than the index of the last valid byte in
     * the buffer.
     */
    public int count = 0;
    // count==-1 for end of stream
    

    public XByteBuffer() {
        buf = new byte[defaultBufferSize];
    }

    public void write(int b) throws IOException {
        if (count >= buf.length) {
            resize();
        }
        buf[count++] = (byte)b;
        bytesWritten++;
    }

    public void write(byte b[], int off, int len) throws IOException {
        int avail = buf.length - count;
        Domain.debug("ENTER: XByteBuffer:write(len="+len+") avail="+avail);

        if ( len > avail ) {
            int newLength = buf.length;
            do {
                newLength = newLength + newLength / 2;
            } while ( newLength <= count + len );
            resize( newLength );
        }

        if ( len > 0 ) {
            System.arraycopy(b, off, buf, count, len);
            count += len;
            bytesWritten += len;
        }
        Domain.debug("LEAVE: XByteBuffer:write(len="+len+") bytesWritten="+bytesWritten);
        return;
    }

    /**
     * enlarge the buffer.
     * @pre   buf != null
     */
    private void resize() {
        resize( buf.length + buf.length / 2 );
    }

    /**
     * enlarge the buffer.
     * @pre   buf != null
     */
    private void resize( int neededSize ) {
        Domain.debug("XByteBuffer:resize( neededSize="+neededSize+")");
        buf2 = new byte[neededSize];
        System.arraycopy( buf, 0, buf2, 0, buf.length );
        buf = buf2;
        buf2 = null;
    }

    public boolean isContentWritten() {
    return bytesWritten!=0;
    }
    
    public void setBufferSize(int size) {
    if( size > buf.length ) {
        buf=new byte[size];
    }
    }

    public int getBufferSize() {
    return buf.length;
    }


    // -------------------- Utils

    public byte[] getBuffer() {
        return buf;
    }

    public String getBufferContent() {
        return new String( buf ).substring( 0, bytesWritten );
//hak       return new String( buf );
    }

    public int getNumberOfBytesWritten() {
        return bytesWritten;
    }
    
}
