All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.wjybxx.dson.text.CharBuffer Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*
 * Copyright 2023-2024 wjybxx([email protected])
 *
 * 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 cn.wjybxx.dson.text;

import cn.wjybxx.base.io.ByteBufferUtils;

import javax.annotation.Nonnull;
import java.nio.BufferOverflowException;
import java.util.Arrays;
import java.util.Objects;

/**
 * @author wjybxx
 * date - 2023/7/8
 */
class CharBuffer implements CharSequence {

    public char[] array;
    public int ridx;
    public int widx;

    CharBuffer(int length) {
        this.array = new char[length];
    }

    CharBuffer(char[] array) {
        this.array = Objects.requireNonNull(array);
    }

    public int capacity() {
        return array.length;
    }

    public boolean isReadable() {
        return ridx < widx;
    }

    public boolean isWritable() {
        return widx < array.length;
    }

    public int writableChars() {
        return array.length - widx;
    }

    public int readableChars() {
        return Math.max(0, widx - ridx);
    }

    // region CharSequence

    /** Length为可读字节数 */
    @Override
    public int length() {
        return Math.max(0, widx - ridx);
    }

    @Override
    public char charAt(int index) {
        return array[ridx + index];
    }

    @Nonnull
    @Override
    public CharSequence subSequence(int start, int end) {
        return new String(array, ridx + start, end - start);
    }

    // endregion

    // region 读写

    public char read() {
        if (ridx == widx) throw new BufferOverflowException();
        return array[ridx++];
    }

    public void unread() {
        if (ridx == 0) throw new BufferOverflowException();
        ridx--;
    }

    public void write(char c) {
        if (widx == array.length) {
            throw new BufferOverflowException();
        }
        array[widx++] = c;
    }

    public void write(char[] chars) {
        if (chars.length == 0) {
            return;
        }
        if (widx + chars.length > array.length) {
            throw new BufferOverflowException();
        }
        System.arraycopy(chars, 0, array, widx, chars.length);
        widx += chars.length;
    }

    public void write(char[] chars, int offset, int len) {
        if (len == 0) {
            return;
        }
        ByteBufferUtils.checkBuffer(chars.length, offset, len);
        if (widx + len > array.length) {
            throw new BufferOverflowException();
        }
        System.arraycopy(chars, offset, array, widx, len);
        widx += len;
    }

    /**
     * 将给定buffer中的可读字符写入到当前buffer中
     * 给定的buffer的读索引将更新,当前buffer的写索引将更新
     *
     * @return 写入的字符数;返回0时可能是因为当前buffer已满,或给定的buffer无可读字符
     */
    public int write(CharBuffer charBuffer) {
        int n = Math.min(writableChars(), charBuffer.readableChars());
        if (n == 0) {
            return 0;
        }
        write(charBuffer.array, charBuffer.ridx, n);
        charBuffer.addRidx(n);
        return n;
    }
    // endregion

    //region 索引调整

    public void addRidx(int count) {
        setRidx(ridx + count);
    }

    public void addWidx(int count) {
        setWidx(widx + count);
    }

    public void setRidx(int ridx) {
        if (ridx < 0 || ridx > widx) {
            throw new IllegalArgumentException("ridx overflow");
        }
        this.ridx = ridx;
    }

    public void setWidx(int widx) {
        if (widx < ridx || widx > array.length) {
            throw new IllegalArgumentException("widx overflow");
        }
        this.widx = widx;
    }

    public void setIndexes(int ridx, int widx) {
        if (ridx < 0 || ridx > widx) {
            throw new IllegalArgumentException("ridx overflow");
        }
        if (widx > array.length) {
            throw new IllegalArgumentException("widx overflow");
        }
        this.ridx = ridx;
        this.widx = widx;
    }
    // endregion

    //region 容量调整

    public void shift(int shiftCount) {
        if (shiftCount <= 0) {
            return;
        }
        if (shiftCount >= array.length) {
//                Arrays.fill(buffer, (char) 0);
            ridx = 0;
            widx = 0;
        } else {
            System.arraycopy(array, shiftCount, array, 0, array.length - shiftCount);
            ridx = Math.max(0, ridx - shiftCount);
            widx = Math.max(0, widx - shiftCount);
//            Arrays.fill(buffer, widx, buffer.length, (char) 0);
        }
    }

    public char[] grow(char[] newArray) {
        char[] oldArray = this.array;
        System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
        this.array = newArray;
        return oldArray;
    }

    public void grow(int capacity) {
        char[] buffer = this.array;
        if (capacity <= buffer.length) {
            return;
        }
        this.array = Arrays.copyOf(this.array, capacity);
    }
    // endregion

    public void clear() {
        ridx = widx = 0;
    }

    @Nonnull
    @Override
    public String toString() {
        return "CharBuffer{" +
                "buffer='" + encodeBuffer() + "'" +
                ", ridx=" + ridx +
                ", widx=" + widx +
                '}';
    }

    private String encodeBuffer() {
        if (ridx >= widx) {
            return "";
        }
        return new String(array, ridx, Math.max(0, widx - ridx));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy