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

com.epam.deltix.util.collections.ByteQueue Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021 EPAM Systems, Inc
 *
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. 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 com.epam.deltix.util.collections;

import java.io.IOException;
import java.io.OutputStream;

/**
 * Fixed size circular buffer of byte values
 */
public final class ByteQueue implements ByteContainer {
    private int                 capacity;
    private byte []             buffer;
    private int                 size = 0;
    private int                 head = 0;
    private int                 tail = 0;
    
    public ByteQueue (int capacity) {
        this.capacity = capacity;
        buffer = new byte [capacity];
    }
    
    public void                 offer (int value) {
        offer ((byte) value);
    }

    public void                 offer (long value) {
        offer ((byte) value);
    }

    public void                 offer (byte value) {
        assert size < capacity :
            "size: " + size + "; capacity: " + capacity;
        
        buffer [tail] = value;
        
        size++;
        tail++;
        
        if (tail == capacity)
            tail = 0;                
    }

//    public void                 insert (byte [] src, int offset, int length) {
//        if (capacity - size < length) {
//            // increase buffer
//            if (tail > head) {
//                byte[] temp = new byte[capacity + length];
//                System.arraycopy (buffer, head, temp, length + head, size);
//                buffer = temp;
//            } else {
//                byte[] temp = new byte[capacity + length];
//                System.arraycopy (buffer, 0, temp, 0, tail);
//                System.arraycopy (buffer, head, temp, capacity - head + length, capacity - head);
//                buffer = temp;
//            }
//            capacity += length;
//        }
//
//        if (head > length) {
//            System.arraycopy (src, offset, buffer, head - length, length);
//            head -= length;
//        } else {
//            int remains = length - head;
//            System.arraycopy (src, offset, buffer, capacity - remains, remains);
//            System.arraycopy (src, offset + remains, buffer, 0, head);
//
//            head = capacity - remains;
//        }
//        size += length;
//
//    }
    
    public void                 offer (byte [] src, int offset, int length) {
        assert size + length <= capacity :
            "size: " + size + "; length: " + length + "; capacity: " + capacity;
        
        int                 end = tail + length;
        int                 excess = end - capacity;
        
        if (excess > 0) {
            int             n = capacity - tail;
            
            System.arraycopy (src, offset, buffer, tail, n);
            
            tail = length - n;
            
            System.arraycopy (src, offset + n, buffer, 0, tail);
        }
        else {
            System.arraycopy (src, offset, buffer, tail, length);        
            tail = excess == 0 ? 0 : end;
        }  
        
        size += length;
    }

    public void                 poll(OutputStream out) throws IOException {
        int end = head + size;

        if (end - capacity > 0) {
            out.write(buffer, head, capacity - head);
            out.write(buffer, 0, tail);
        } else {
            out.write(buffer, head, tail - head);
        }

        clear();
    }
    
    public byte                 poll () {
        assert size > 0 : "size: " + size;
        
        byte                value = buffer [head];
        
        size--;
        head++;
        
        if (head == capacity)
            head = 0;

        return (value);
    }   

    /**
     *  Equivalent to (head + offset) % capacity for 0 <= offset < capacity
     *  but a bit faster.
     */
    private int                 logicalToInternal (int srcOffset) {
        int     ret = head + srcOffset;

        if (ret >= capacity)
            ret -= capacity;

        return (ret);
    }

    @Override
    public byte                 get (int srcOffset) {
        assert srcOffset < size : "srcOffset: " + srcOffset + "; size: " + size;

        return (buffer [logicalToInternal (srcOffset)]);
    }

    public void                 poll (byte [] dest, int offset, int length) {
        assert size >= length : "size: " + size + "; length: " + length;
        
        int                 end = head + length;
        int                 excess = end - capacity;
        
        if (excess > 0) {
            int             n = capacity - head;

            if (dest != null) {
                System.arraycopy (buffer, head, dest, offset, n);
                System.arraycopy (buffer, 0, dest, offset + n, excess);
            }

            head = excess;            
        }
        else {
            if (dest != null)
                System.arraycopy (buffer, head, dest, offset, length);
            
            head = excess == 0 ? 0 : end;
        }
        
        size -= length;
    }
    
    public void                 get (int srcOffset, byte [] dest, int destOffset, int length) {
        assert srcOffset + length <= size :
            "size: " + size + "; srcOffset: " + srcOffset + "; length: " + length;

        int                 start = logicalToInternal (srcOffset);
        int                 end = start + length;
        int                 excess = end - capacity;

        if (excess > 0) {
            int             n = capacity - start;

            System.arraycopy (buffer, start, dest, destOffset, n);
            System.arraycopy (buffer, 0, dest, destOffset + n, excess);
        }
        else
            System.arraycopy (buffer, start, dest, destOffset, length);
    }

    public void                 skip (int length) {
        assert size >= length && length >= 0 : "skip length " + length + " > size: " + size;
        
        size -= length;
        head += length;
        
        if (head >= capacity)
            head -= capacity;
    }
    
    public void                 clear () {
        size = 0;
        head = 0;
        tail = 0;
    }
    
    public boolean        isEmpty () {
        return (size == 0);
    }
    
    public boolean        isFull () {
        return (size == capacity);
    }
    
    public int            size () {
        return (size);
    }  
    
    public int            free () {
        return (capacity - size);
    }
    
    public byte []              getBuffer () {
        return buffer;
    }

    public int                  getHead () {
        return head;
    }

    public int                  getTail () {
        return tail;
    }    

    public int                  capacity() {
        return capacity;
    }

    public void                 addCapacity(int increment) {
        setCapacity(capacity + increment);
    }

    public void                 truncate(int length) {
        assert length < size;
        int newTail = tail - length;
        if (newTail < 0)
            newTail =+ capacity;
        
        size -= length;
        tail = newTail;
    }

    public boolean              setCapacity (int value) {
        if (capacity == value)
            return false; 

        assert(value > capacity);
        capacity = value;
        
        byte[] previous = buffer;
        buffer = new byte[capacity];
        if (tail > head) {
            System.arraycopy (previous, head, buffer, 0, size);
        } else {
            System.arraycopy (previous, head, buffer, 0, previous.length - head);
            System.arraycopy (previous, 0, buffer, previous.length - head, tail);
        }
        
        head = 0;
        tail = size;

        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy