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

com.amazon.ion.impl.UnifiedInputBufferX Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazon.ion.impl;


abstract class UnifiedInputBufferX
{
    public enum BufferType { BYTES, CHARS }

    protected int               _page_size;
    protected UnifiedDataPageX[] _buffers;
    protected int               _buffer_current;
    protected int               _buffer_count;
    protected int               _locks;

    public static UnifiedInputBufferX makePageBuffer(byte[] bytes, int offset, int length) {
        UnifiedInputBufferX buf = new UnifiedInputBufferX.Bytes(bytes, offset, length);
        return buf;
    }
    public static UnifiedInputBufferX makePageBuffer(char[] chars, int offset, int length) {
        UnifiedInputBufferX buf = new UnifiedInputBufferX.Chars(chars, offset, length);
        return buf;
    }
    public static UnifiedInputBufferX makePageBuffer(CharSequence chars, int offset, int length) {
        char [] char_array = chars_make_char_array(chars, offset, length);
        UnifiedInputBufferX buf = makePageBuffer(char_array, 0, length);
        return buf;
    }
    public static UnifiedInputBufferX makePageBuffer(BufferType bufferType, int initialPageSize)
    {
        UnifiedInputBufferX buf;
        switch(bufferType) {
        case CHARS:
            buf = new UnifiedInputBufferX.Chars(initialPageSize);
            break;
        case BYTES:
            buf = new UnifiedInputBufferX.Bytes(initialPageSize);
            break;
        default:
            throw new IllegalArgumentException("invalid buffer type");
        }
        return buf;
    }
    protected static final char[] chars_make_char_array(CharSequence chars,
                                                         int offset,
                                                         int length)
    {
        char[] char_array = new char[length];
        for (int ii=offset; ii 0");
        } else if (initialPageSize > _Private_IonConstants.ARRAY_MAXIMUM_SIZE) {
            throw new IllegalArgumentException("page size must be < " + _Private_IonConstants.ARRAY_MAXIMUM_SIZE);
        }
        _page_size = initialPageSize;
        _buffers = new UnifiedDataPageX[10];
    }

    public abstract BufferType getType();
    public abstract int maxValue();

    public final void putCharAt(long fileOffset, int c) {
        if (c < 0 || c > maxValue()) throw new IllegalArgumentException("value ("+c+")is out of range (0 to "+maxValue()+")");

        // since we start at _curr the common case find the buffer immediately
        UnifiedDataPageX page = null;
        for (int ii=_buffer_current; ii>=0; ii--) {
            if (_buffers[ii].containsOffset(fileOffset)) {
                page = _buffers[ii];
                break;
            }
        }
        if (page == null) throw new IllegalArgumentException();
        int offset = (int)(fileOffset - page.getStartingFileOffset());
        page.putValue(offset, c);
    }

    public final UnifiedDataPageX getCurrentPage() {
        return _buffers[_buffer_current];
    }

    public final int getCurrentPageIdx()   {
        return _buffer_current;
    }

    public final int getPageCount() {
        return _buffer_count;
    }

    public final void incLock() {
        _locks++;
    }
    public final boolean decLock() {
        _locks--;
        return (_locks == 0);
    }

    public final UnifiedDataPageX getPage(int pageIdx) {
        if (pageIdx < 0 || pageIdx >= _buffer_count) {
            throw new IndexOutOfBoundsException();
        }
        return _buffers[pageIdx];
    }

    protected final int getNextFilledPageIdx() {
        int idx = _buffer_current + 1;

        if (idx < _buffer_count) {
            UnifiedDataPageX p = _buffers[idx];
            if (p != null) {
                _buffer_current = idx;
                return idx;
            }
        }
        return -1;
    }

    protected final UnifiedDataPageX getEmptyPageIdx() {
        UnifiedDataPageX next = null;

        if (_buffer_count < _buffers.length) {
            next = _buffers[_buffer_count];
        }
        if (next == null) {
            next = make_page(_page_size);
        }
        else {
            assert(_buffer_count == (_buffer_current + 1));
        }
        return next;
    }

    abstract protected UnifiedDataPageX make_page(int page_size);

    protected final UnifiedDataPageX setCurrentPage(int idx, UnifiedDataPageX curr) {
        setPage(idx, curr, true);
        if (idx != _buffer_current) {
            _buffer_current = idx;
            if (idx >= _buffer_count) {
                _buffer_count = idx + 1;
            }
        }
        UnifiedDataPageX p = _buffers[idx];
        return p;
    }

    protected final void setPage(int idx, UnifiedDataPageX curr, boolean recycleOldPage)
    {
        int oldlen = _buffers.length;
        if (idx >= oldlen) {
            int newlen = oldlen * 2;
            UnifiedDataPageX[] newbuf = new UnifiedDataPageX[newlen];
            System.arraycopy(_buffers, 0, newbuf, 0, oldlen);
            _buffers = newbuf;
        }
        UnifiedDataPageX prev = _buffers[idx];
        _buffers[idx] = curr;
        if (idx >= _buffer_count) {
            _buffer_count = idx + 1;
        }
        // if the caller wants us to we'll hold onto this
        // page for a bit, since it's now available
        if (recycleOldPage
         && prev != null
         && prev != curr
         && (idx + 1) < _buffers.length // it's not worth reallocating the _buffers array for this
         ) {
            _buffers[idx+1] = prev;
        }
    }

    /**
     * resets the buffer list to start at the current page
     * this releases any "extra" pages.  This does hold
     * on to 1 extra page, if there is one, since two pages
     * if a common occurrence for values that cross the
     * page boundary.
     *
     * when this exits there will be either just the current
     * page in the buffer list or the current page and 1
     * preallocated page just after it (in idx 1).
     */
    protected final void resetToCurrentPage()
    {
        int p0_idx = getCurrentPageIdx();
        if (p0_idx > 0) {
            // this is a common "do nothing" case, it happens
            // when we reset to the page and there are no saved
            // pages - i.e. the mark is contained in curr
            release_pages_to(p0_idx);
        }
    }

    private final void release_pages_to(int p0_idx) {
        assert(p0_idx > 0);

        // we'll try to save the now unneeded 0th empty page
        UnifiedDataPageX empty_page = _buffers[0];

        // now bump all the page ptrs down to release the
        // pages that precede the current page
        int dst = 0;
        int src = p0_idx;
        while (src<_buffer_count) {
            _buffers[dst++] = _buffers[src++];
        }

        // clear any trailing page ptrs
        int end = _buffer_count + 1; // we may have an extra page ptr saved at buffer[count]
        if (end >= _buffers.length) {
            end = _buffers.length;
        }
        while (dst < end) {
            _buffers[dst++] = null;
        }

        _buffer_current -= p0_idx;
        _buffer_count -= p0_idx;
        _buffers[_buffer_count] = empty_page;
    }

    /**
     * this clears all the pages out, except to save
     * one page (unallocated)
     *
     */
    protected final void clear() {
        UnifiedDataPageX curr = getCurrentPage();

        for (int ii=0; ii<_buffers.length; ii++) {
            _buffers[ii] = null;
        }

        // curr is null when underlying stream is empty.
        if (curr != null)
        {
            _buffers[0] = curr;
            curr.reset(0);
        }

        _buffer_count = 0;
        _buffer_current = 0;
    }

    static class Bytes extends UnifiedInputBufferX {
        protected Bytes(int initialPageSize) {
            super(initialPageSize);
        }
        protected Bytes(byte[] bytes, int offset, int length) {
            super(length);
            _buffers[0] = new UnifiedDataPageX.Bytes(bytes, offset, length);
            _buffer_current = 0;
            _buffer_count = 1;
        }
        @Override
        public final BufferType getType() { return BufferType.BYTES; }

        @Override
        protected final UnifiedDataPageX make_page(int page_size) {
            UnifiedDataPageX p = new UnifiedDataPageX.Bytes(page_size);
            return p;
        }

        @Override
        public final int maxValue() { return 0xff; }

    }
    static class Chars extends UnifiedInputBufferX {
        protected Chars(int initialPageSize) {
            super(initialPageSize);
        }
        /** Retains a reference to the chars array! */
        protected Chars(char[] chars, int offset, int length) {
            super(offset + length);
            _buffers[0] = new UnifiedDataPageX.Chars(chars, offset, length);
            _buffer_current = 0;
            _buffer_count = 1;

        }
        /**
         * Makes a copy of the {@link CharSequence}.
         */
        protected Chars(CharSequence chars, int offset, int length) {
            this(chars_make_char_array(chars, offset, length), 0, length);
        }
        @Override
        public final BufferType getType() { return BufferType.CHARS; }

        @Override
        protected final UnifiedDataPageX make_page(int page_size) {
            UnifiedDataPageX p = new UnifiedDataPageX.Chars(page_size);
            return p;
        }

        @Override
        public final int maxValue() { return 0xffff; }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy