Home | History | Annotate | Download | only in zip
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements.  See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership.  The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the
      7  * "License"); you may not use this file except in compliance
      8  * with the License.  You may obtain a copy of the License at
      9  *
     10  * http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing,
     13  * software distributed under the License is distributed on an
     14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15  * KIND, either express or implied.  See the License for the
     16  * specific language governing permissions and limitations
     17  * under the License.
     18  */
     19 
     20 package org.apache.commons.compress.archivers.zip;
     21 
     22 /**
     23  * Circular byte buffer.
     24  *
     25  * @author Emmanuel Bourg
     26  * @since 1.7
     27  */
     28 class CircularBuffer {
     29 
     30     /** Size of the buffer */
     31     private final int size;
     32 
     33     /** The buffer */
     34     private final byte[] buffer;
     35 
     36     /** Index of the next data to be read from the buffer */
     37     private int readIndex;
     38 
     39     /** Index of the next data written in the buffer */
     40     private int writeIndex;
     41 
     42     CircularBuffer(final int size) {
     43         this.size = size;
     44         buffer = new byte[size];
     45     }
     46 
     47     /**
     48      * Tells if a new byte can be read from the buffer.
     49      */
     50     public boolean available() {
     51         return readIndex != writeIndex;
     52     }
     53 
     54     /**
     55      * Writes a byte to the buffer.
     56      */
     57     public void put(final int value) {
     58         buffer[writeIndex] = (byte) value;
     59         writeIndex = (writeIndex + 1) % size;
     60     }
     61 
     62     /**
     63      * Reads a byte from the buffer.
     64      */
     65     public int get() {
     66         if (available()) {
     67             final int value = buffer[readIndex];
     68             readIndex = (readIndex + 1) % size;
     69             return value & 0xFF;
     70         }
     71         return -1;
     72     }
     73 
     74     /**
     75      * Copy a previous interval in the buffer to the current position.
     76      *
     77      * @param distance the distance from the current write position
     78      * @param length   the number of bytes to copy
     79      */
     80     public void copy(final int distance, final int length) {
     81         final int pos1 = writeIndex - distance;
     82         final int pos2 = pos1 + length;
     83         for (int i = pos1; i < pos2; i++) {
     84             buffer[writeIndex] = buffer[(i + size) % size];
     85             writeIndex = (writeIndex + 1) % size;
     86         }
     87     }
     88 }
     89