Package org.xlightweb

Source Code of org.xlightweb.ComposedByteBuffer$IBufferSink

/*
*  Copyright (c) xlightweb.org, 2008 - 2009. All rights reserved.
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
* The latest copy of this software may be found on http://www.xlightweb.org/
*/
package org.xlightweb;


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import org.xsocket.DataConverter;
import static org.xlightweb.HttpUtils.*;




/**
* Composed ByteBuffer
*
* @author grro@xlightweb.org
*/
final class ComposedByteBuffer {
 
  private ArrayList<ByteBuffer> buffers = new ArrayList<ByteBuffer>();
 
  private int bufferIdx;
 
  private ByteBuffer currentBuffer = null;
  private int remainingCurrentBuffer;  
 
  private int remainingTotal;
 
 
 
  /**
   * appends data
   * @param bufs the data to append
   */
  void append(ByteBuffer[] bufs) {
   
    if (bufs == null) {
      return;
    }
   
    for (ByteBuffer byteBuffer : bufs) {
     
      if ((byteBuffer != null) && (byteBuffer.hasRemaining())) {
        remainingTotal += byteBuffer.remaining();
         
        if (buffers.size() == 0) {
          currentBuffer = bufs[0];
          remainingCurrentBuffer = currentBuffer.remaining();
        }
        buffers.add(byteBuffer);
      }
    }
  }
 
 
  /**
   * add data to the first position
   * @param data the data to add
   */
  void addFirst(byte[] data) {
    List<ByteBuffer> buffers = drain();
    clear();
   
    append(new ByteBuffer[] { ByteBuffer.wrap(data) });
    append(buffers.toArray(new ByteBuffer[buffers.size()]))
  }
 
 
  /**
   * read data by length
   *
   * @param length          the numbers of bytes to read
   * @param bufferSink      the data sink to write the data
   * @throws IOException if an exception occurs
   */
  void readByteBufferByLength(int length, IBufferSink bufferSink) throws IOException {
   
    // current buffer is empty?
    if (remainingCurrentBuffer == 0) {
      bufferIdx++;
      currentBuffer = buffers.get(bufferIdx);
      remainingCurrentBuffer = currentBuffer.remaining();
    }
   
   
   
    if (remainingCurrentBuffer == length) {
      bufferSink.add(currentBuffer);
      remainingTotal -= remainingCurrentBuffer;
      remainingCurrentBuffer = 0;  
       
     
    } else if (remainingCurrentBuffer < length) {
      int remainingRequired = length - remainingCurrentBuffer;
     
      bufferSink.add(currentBuffer);
      remainingTotal -= remainingCurrentBuffer;
      remainingCurrentBuffer = 0;  

      readByteBufferByLength(remainingRequired, bufferSink)// recursive call
       
     
    } else // remainingCurrentBuffer > length
      int savedLimit = currentBuffer.limit();
      currentBuffer.limit(currentBuffer.position() + length);
      ByteBuffer sliced = currentBuffer.slice();
       
      bufferSink.add(sliced);
      currentBuffer.position(currentBuffer.limit());
      currentBuffer.limit(savedLimit);

      remainingCurrentBuffer = currentBuffer.remaining();  
      remainingTotal -= length;
    }
  }

 
 
  int indexOfBoundaryDelimiter(byte[] delimiter) {

    int state = 1;
   
    int pos = 0;
    int length = 0;
   
 
 
   
    for (int i = bufferIdx; i <= buffers.size(); i++) {
      ByteBuffer buf = buffers.get(bufferIdx).duplicate();
     
      while (buf.hasRemaining()) {
        byte b = buf.get();
        length++;
       
        switch (state) {
          case 1:
            if (b == delimiter[pos]) {
              pos++;
              if (pos == delimiter.length) {
                state = 2
              }
            } else {
              pos = 0;
            }
            break;
           
          case 2:
            if ((b == HTAB) || (b == SPACE)) {
              break;
            }
           
            if (b == CR) {
              state = 3;
            } else {
              pos = 0;
              state = 1;
            }
            break;
           
          case 3:
            if ((b == HTAB) || (b == SPACE)) {
              break;
            }
           
            if (b == LF) {
              return length;
            } else {
              pos = 0;
              state = 1;
            }
            break;
           
           
          default:
            break;
        }       
      }     
    }
   
    return 0;
  }
 
 
  /**
   * return true if is empty
   * @return  true if is empty
   */
  boolean isEmpty() {
    return (remainingTotal == 0);
  }

 
  /**
   * returns the number of remaining bytes
   * @return the number of remaining bytes
   */
  int remaining() {
    return remainingTotal;
  }
 
 
  /**
   * drains the buffer
   *
   * @return the data
   */
  List<ByteBuffer> drain() {
   
    ArrayList<ByteBuffer> result = null;
   
    if (bufferIdx == 0) {
      result = buffers;
      buffers = new ArrayList<ByteBuffer>();
     
    } else {
      result = new ArrayList<ByteBuffer>();
      for (int i = bufferIdx; i < buffers.size(); i++) {
        result.add(buffers.get(i));
      }
     
      buffers = new ArrayList<ByteBuffer>();
    }
   
    clear();
    return result;
  }
 
 
 
  /**
   * drains the buffer
   * 
   * @param bufferSink    the data sink to write the data
   * @return the number of transfered bytes
   * @throws IOException if an exctpion occurs
   */
  int drain(IBufferSink bufferSink) throws IOException {
   
    int read = 0;
   
    for (int i = bufferIdx; i < buffers.size(); i++) {
      ByteBuffer buffer = buffers.get(i);
      read += buffer.remaining();
     
      bufferSink.add(buffer);
    }
   
    clear();
    return read;
  }

 
  /**
   * returns the number of available bytes
   * @return the number of available bytes
   */
  int available() {
    return remainingTotal;
  }
 

  /**
   * return the next byte
   * @return the next byte
   */
  byte getByte() {
 
    if (remainingCurrentBuffer > 0) {

      assert (currentBuffer == buffers.get(bufferIdx));
     
      // dec remaining
      remainingTotal--;
      remainingCurrentBuffer--;
     
      // return byte
      return currentBuffer.get();
     
    } else {
     
      bufferIdx++;
      currentBuffer = buffers.get(bufferIdx);
      remainingCurrentBuffer = currentBuffer.remaining();
      return getByte();
    }
  } 
 
 
 
  /**
   * clears the buffer
   */
  void clear() {
    buffers.clear();
   
    bufferIdx = 0;

    currentBuffer = null;
    remainingCurrentBuffer = 0;  
    remainingTotal = 0;
  }
 
 
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    List<ByteBuffer> bufferCopy = new ArrayList<ByteBuffer>();
    for (int i = bufferIdx; i < buffers.size(); i++) {
      bufferCopy.add(buffers.get(i).duplicate());
    }
   
    try {
      return DataConverter.toString(bufferCopy, "US-ASCII");
    } catch (UnsupportedEncodingException use) {
      return DataConverter.toHexString(bufferCopy, Integer.MAX_VALUE);
    }
  }
 
 
  /**
   * buffer sink definition
   * @author grro
   */
  static interface IBufferSink {
   
    /**
     * add data
     *
     * @param buffer data
     * @throws IOException if an exception occurs
     */
    void add(ByteBuffer buffer) throws IOException;
  }
}
TOP

Related Classes of org.xlightweb.ComposedByteBuffer$IBufferSink

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.