⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 charchunk.java

📁 业界著名的tomcat服务器的最新6.0的源代码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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.tomcat.util.buf;

import java.io.IOException;
import java.io.Serializable;

/**
 * Utilities to manipluate char chunks. While String is
 * the easiest way to manipulate chars ( search, substrings, etc),
 * it is known to not be the most efficient solution - Strings are
 * designed as imutable and secure objects.
 * 
 * @author dac@sun.com
 * @author James Todd [gonzo@sun.com]
 * @author Costin Manolache
 * @author Remy Maucherat
 */
public final class CharChunk implements Cloneable, Serializable, CharSequence {

    // Input interface, used when the buffer is emptied.
    public static interface CharInputChannel {
        /** 
         * Read new bytes ( usually the internal conversion buffer ).
         * The implementation is allowed to ignore the parameters, 
         * and mutate the chunk if it wishes to implement its own buffering.
         */
        public int realReadChars(char cbuf[], int off, int len)
            throws IOException;
    }
    /**
     *  When we need more space we'll either
     *  grow the buffer ( up to the limit ) or send it to a channel.
     */
    public static interface CharOutputChannel {
	/** Send the bytes ( usually the internal conversion buffer ).
	 *  Expect 8k output if the buffer is full.
	 */
        public void realWriteChars(char cbuf[], int off, int len)
            throws IOException;
    }
    
    // -------------------- 
    // char[]
    private char buff[];

    private int start;
    private int end;

    private boolean isSet=false;  // XXX 

    private boolean isOutput=false;

    // -1: grow undefinitely
    // maximum amount to be cached
    private int limit=-1;

    private CharInputChannel in = null;
    private CharOutputChannel out = null;
    
    private boolean optimizedWrite=true;

    /**
     * Creates a new, uninitialized CharChunk object.
     */
    public CharChunk() {
    }

    public CharChunk(int size) {
	allocate( size, -1 );
    }

    // --------------------
    
    public CharChunk getClone() {
	try {
	    return (CharChunk)this.clone();
	} catch( Exception ex) {
	    return null;
	}
    }

    public boolean isNull() {
	if( end > 0 ) return false;
	return !isSet; //XXX 
    }
    
    /**
     * Resets the message bytes to an uninitialized state.
     */
    public void recycle() {
	//	buff=null;
	isSet=false; // XXX
	start=0;
	end=0;
    }

    public void reset() {
	buff=null;
    }

    // -------------------- Setup --------------------

    public void allocate( int initial, int limit  ) {
	isOutput=true;
	if( buff==null || buff.length < initial ) {
	    buff=new char[initial];
	}
	this.limit=limit;
	start=0;
	end=0;
	isOutput=true;
	isSet=true;
    }


    public void setOptimizedWrite(boolean optimizedWrite) {
        this.optimizedWrite = optimizedWrite;
    }

    public void setChars( char[] c, int off, int len ) {
        buff=c;
        start=off;
        end=start + len;
        isSet=true;
    }

    /** Maximum amount of data in this buffer.
     *
     *  If -1 or not set, the buffer will grow undefinitely.
     *  Can be smaller than the current buffer size ( which will not shrink ).
     *  When the limit is reached, the buffer will be flushed ( if out is set )
     *  or throw exception.
     */
    public void setLimit(int limit) {
	this.limit=limit;
    }
    
    public int getLimit() {
	return limit;
    }

    /**
     * When the buffer is empty, read the data from the input channel.
     */
    public void setCharInputChannel(CharInputChannel in) {
        this.in = in;
    }

    /** When the buffer is full, write the data to the output channel.
     * 	Also used when large amount of data is appended.
     *
     *  If not set, the buffer will grow to the limit.
     */
    public void setCharOutputChannel(CharOutputChannel out) {
	this.out=out;
    }

    // compat 
    public char[] getChars()
    {
	return getBuffer();
    }
    
    public char[] getBuffer()
    {
	return buff;
    }
    
    /**
     * Returns the start offset of the bytes.
     * For output this is the end of the buffer.
     */
    public int getStart() {
	return start;
    }
    
    public int getOffset() {
	return start;
    }

    /**
     * Returns the start offset of the bytes.
     */
    public void setOffset(int off) {
	start=off;
    }

    /**
     * Returns the length of the bytes.
     */
    public int getLength() {
	return end-start;
    }


    public int getEnd() {
	return end;
    }

    public void setEnd( int i ) {
	end=i;
    }

    // -------------------- Adding data --------------------
    
    public void append( char b )
	throws IOException
    {
	makeSpace( 1 );

	// couldn't make space
	if( limit >0 && end >= limit ) {
	    flushBuffer();
	}
	buff[end++]=b;
    }
    
    public void append( CharChunk src )
	throws IOException
    {
	append( src.getBuffer(), src.getOffset(), src.getLength());
    }

    /** Add data to the buffer
     */
    public void append( char src[], int off, int len )
	throws IOException
    {
	// will grow, up to limit
	makeSpace( len );

	// if we don't have limit: makeSpace can grow as it wants
	if( limit < 0 ) {
	    // assert: makeSpace made enough space
	    System.arraycopy( src, off, buff, end, len );
	    end+=len;
	    return;
	}

        // Optimize on a common case.
        // If the source is going to fill up all the space in buffer, may
        // as well write it directly to the output, and avoid an extra copy
        if ( optimizedWrite && len == limit && end == start && out != null ) {
            out.realWriteChars( src, off, len );
            return;
        }
	
	// if we have limit and we're below
	if( len <= limit - end ) {
	    // makeSpace will grow the buffer to the limit,
	    // so we have space
	    System.arraycopy( src, off, buff, end, len );
            
	    end+=len;
	    return;
	}

	// need more space than we can afford, need to flush
	// buffer

	// the buffer is already at ( or bigger than ) limit
	
	// Optimization:
	// If len-avail < length ( i.e. after we fill the buffer with
	// what we can, the remaining will fit in the buffer ) we'll just
	// copy the first part, flush, then copy the second part - 1 write
	// and still have some space for more. We'll still have 2 writes, but
	// we write more on the first.

	if( len + end < 2 * limit ) {
	    /* If the request length exceeds the size of the output buffer,
	       flush the output buffer and then write the data directly.
	       We can't avoid 2 writes, but we can write more on the second
	    */
	    int avail=limit-end;
	    System.arraycopy(src, off, buff, end, avail);
	    end += avail;
	    
	    flushBuffer();
	    
	    System.arraycopy(src, off+avail, buff, end, len - avail);
	    end+= len - avail;
	    
	} else {	// len > buf.length + avail
	    // long write - flush the buffer and write the rest
	    // directly from source
	    flushBuffer();
	    
	    out.realWriteChars( src, off, len );
	}
    }


    /** Add data to the buffer
     */
    public void append( StringBuffer sb )
	throws IOException
    {
	int len=sb.length();

	// will grow, up to limit
	makeSpace( len );

	// if we don't have limit: makeSpace can grow as it wants
	if( limit < 0 ) {
	    // assert: makeSpace made enough space
	    sb.getChars(0, len, buff, end );
	    end+=len;
	    return;
	}

	int off=0;
	int sbOff = off;
	int sbEnd = off + len;
	while (sbOff < sbEnd) {
	    int d = min(limit - end, sbEnd - sbOff);
	    sb.getChars( sbOff, sbOff+d, buff, end);
	    sbOff += d;
	    end += d;
	    if (end >= limit)
		flushBuffer();
	}
    }

    /** Append a string to the buffer
     */
    public void append(String s) throws IOException {
        append(s, 0, s.length());
    }
    
    /** Append a string to the buffer
     */
    public void append(String s, int off, int len) throws IOException {
	if (s==null) return;
	
	// will grow, up to limit
	makeSpace( len );

	// if we don't have limit: makeSpace can grow as it wants
	if( limit < 0 ) {
	    // assert: makeSpace made enough space
	    s.getChars(off, off+len, buff, end );
	    end+=len;
	    return;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -