Source code analysis of java.nio.Buffer buffer

Keywords: less

1. Schematic diagram of buffer buffer


2. Common variables

//Temporary note location variable
    private int mark = -1;
	/**
	 * In write mode, position starts from 0 and can be written to capacity-1 all the time.
	 * In read mode, the position is read from a certain location. If you switch from write to read, the position is set to 0.
	 */
    private int position = 0;
	/**
	 * The readable and writable capacity of the buffer. When the readable and writable limit is maximum, limit=capacity
	 */
    private int limit;
	/**
	 * Total buffer capacity
	 */
    private int capacity;

    //Address to buffer
    long address;

3. Constructor

//Create a constructor that specifies the mark, pos, limit, and capacity parameters
    Buffer(int mark, int pos, int lim, int cap) {       
		//If the initialization capacity of the buffer is less than 0, an illegal parameter exception is thrown.
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
		//Set the initialization capacity of the buffer
        this.capacity = cap;
		//Set the Buffer limit and the latest Buffer
        limit(lim);
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            this.mark = mark;
        }
    }

	/**
     * Set the buffer limit.
	 * If position > limit, reset the new limit.
	 * If mark > limit, the latest limit will be discarded.
     */
    public final Buffer limit(int newLimit) {
		//If the input parameter newLimit is greater than the maximum buffer capacity or less than 0, an illegal parameter exception is thrown.
        if ((newLimit > capacity) || (newLimit < 0))
            throw new IllegalArgumentException();
		//Set the input parameter newLimit to the latest limit of the buffer.
        limit = newLimit;
		//If the start read / write location is larger than the capacity of stored data, set the read / write location to the capacity of stored data.
        if (position > limit) position = limit;
		//If the location of the temporary note is larger than the capacity of the stored data, set mark to - 1.
        if (mark > limit) mark = -1;
		//Returns the current Buffer
        return this;
    }
	
	/**
     * Set the start position of reading and writing.
	 * If mark > position, the position variable will be discarded.
     */
    public final Buffer position(int newPosition) {
		//If the input parameter newPosition is greater than the maximum readable and writable capacity or the newPosition is less than 0, an illegal parameter exception is thrown.
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
		//Set the input parameter newPosition as the latest read-write start position.
        position = newPosition;
		//If the temporary note position mark is greater than position, set mark to - 1.
        if (mark > position) mark = -1;
		//Returns the current Buffer
        return this;
    }

4. Common methods

/**
     * Get the maximum capacity of the current Buffer
     */
    public final int capacity() {
        return capacity;
    }

    /**
     * Get the read / write start position of the current Buffer
     */
    public final int position() {
        return position;
    }

    /**
     * Get the maximum read / write capacity of the current Buffer
     */
    public final int limit() {
        return limit;
    }

    /**
     * Set the memo variable of the current buffer to position
	 * Returns the current latest Buffer
     */
    public final Buffer mark() {
        mark = position;
        return this;
    }

    /**
     * Set the position of Buffer to the position stored in the previous temporary memo variable mark.
     */
    public final Buffer reset() {
		//Get the current temporary note variable mark
        int m = mark;
		//If the temporary memo variable m is less than 0, an invalid tag exception is thrown.
        if (m < 0)
            throw new InvalidMarkException();
		//Set the start position of current buffer read / write as the memo variable mark
        position = m;
		//Returns the current latest Buffer
        return this;
    }

    /**
     * Clear buffer
     */
    public final Buffer clear() {
		//Set the read-write start position to 0
        position = 0;
		//Set the maximum read / write capacity limit to the maximum buffer capacity
        limit = capacity;
		//Set the value of the temporary note variable to - 1
        mark = -1;
		//Returns the current latest Buffer
        return this;
    }

    /**
     * Invert this buffer
	 * Used when writing and reading
     */
    public final Buffer flip() {
		//Set the maximum read / write capacity to the current location
        limit = position;
		//Set position to 0
        position = 0;
		//Set the temporary note variable to - 1
        mark = -1;
		//Returns the current latest Buffer
        return this;
    }

    /**
     * Rewind this buffer
	 * Call before channel is written or acquired
     */
    public final Buffer rewind() {
		//Set current location to 0
        position = 0;
		//Set the temporary note variable to - 1
        mark = -1;
		//Returns the current latest Buffer
        return this;
    }

    /**
     * Returns the number of remaining elements of the current Buffer
     */
    public final int remaining() {
        return limit - position;
    }

    /**
     * Returns whether there are elements in the current buffer
	 * Return true if any
	 * Return false if not
     */
    public final boolean hasRemaining() {
        return position < limit;
    }

    /**
     * Whether the current buffer is read-only
	 * Return true if yes
	 * Return false if not
     */
    public abstract boolean isReadOnly();

    /**
     * Whether the current buffer can access the underlying array
     */
    public abstract boolean hasArray();

    /**
     * Returns the underlying implementation array of the current buffer
     */
    public abstract Object array();

    /**
     * Returns the optional offset of the first buffer element in the underlying implementation array of this buffer.
     */
    public abstract int arrayOffset();

    /**
     * Is this buffer a direct buffer
     */
    public abstract boolean isDirect();


    // -- Package-private methods for bounds checking, etc. --

    /**
     * Get the next location of the current location
     */
    final int nextGetIndex() {   
		//If the current position is greater than or equal to limit, a buffer down overflow exception is thrown.
        if (position >= limit)
            throw new BufferUnderflowException();
		//Return to the next location in the current location
        return position++;
    }

	/**
     * Current position increases the length of the specified parameter
	 * Return to the position before adding
     */
    final int nextGetIndex(int nb) {  
		//If the limit value minus the current position value is less than nb, a buffer down overflow exception is thrown.
        if (limit - position < nb)
            throw new BufferUnderflowException();
        int p = position;
        position += nb;
        return p;
    }

    /**
     * Auto increment current position
     */
    final int nextPutIndex() {                          // package-private
        if (position >= limit)
            throw new BufferOverflowException();
        return position++;
    }

	/**
     * Current position increases the length of the specified parameter
	 * Return to the position before increase
     */
    final int nextPutIndex(int nb) {                    // package-private
        if (limit - position < nb)
            throw new BufferOverflowException();
        int p = position;
        position += nb;
        return p;
    }

    /**
     * Check if parameter i is less than limit
     */
    final int checkIndex(int i) {                       // package-private
        if ((i < 0) || (i >= limit))
            throw new IndexOutOfBoundsException();
        return i;
    }
	
	/**
     * Check if parameter i is less than the limit - specified parameter
     */
    final int checkIndex(int i, int nb) {               // package-private
        if ((i < 0) || (nb > limit - i))
            throw new IndexOutOfBoundsException();
        return i;
    }

	//Returns the value of the temporary note variable
    final int markValue() {                             // package-private
        return mark;
    }

	//Empty buffer capacity
    final void truncate() {                             // package-private
        mark = -1;
        position = 0;
        limit = 0;
        capacity = 0;
    }

	//Discard temporary note variables
    final void discardMark() {                          // package-private
        mark = -1;
    }

5. Reading summary

① When writing to read, use the flip method, which is characterized by setting the read capacity limit to the write position, setting the start position of the read to 0, and setting the mark to - 1 (for why, please refer to the previous schematic diagram for thinking).

② When reading and writing, use the clear method, which is characterized by setting the position to 0, the write limit value to the capacity of the current buffer, and the mark value to - 1.

③ As for mark and reset methods, their function is to restore the position to its original position.



Posted by Rony on Fri, 01 May 2020 03:09:35 -0700