1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.util; 18 19 import libcore.util.EmptyArray; 20 21 import java.util.NoSuchElementException; 22 23 /** 24 * Copied from frameworks/base/core/java/android/util/LongArrayQueue.java 25 * 26 * @hide 27 */ 28 public class LongArrayQueue { 29 30 private long[] mValues; 31 private int mSize; 32 private int mHead; 33 private int mTail; 34 newUnpaddedLongArray(int num)35 private long[] newUnpaddedLongArray(int num) { 36 return new long[num]; 37 } 38 /** 39 * Initializes a queue with the given starting capacity. 40 * 41 * @param initialCapacity the capacity. 42 */ LongArrayQueue(int initialCapacity)43 public LongArrayQueue(int initialCapacity) { 44 if (initialCapacity == 0) { 45 mValues = EmptyArray.LONG; 46 } else { 47 mValues = newUnpaddedLongArray(initialCapacity); 48 } 49 mSize = 0; 50 mHead = mTail = 0; 51 } 52 53 /** 54 * Initializes a queue with default starting capacity. 55 */ LongArrayQueue()56 public LongArrayQueue() { 57 this(16); 58 } 59 60 /** @hide */ growSize(int currentSize)61 public static int growSize(int currentSize) { 62 return currentSize <= 4 ? 8 : currentSize * 2; 63 } 64 grow()65 private void grow() { 66 if (mSize < mValues.length) { 67 throw new IllegalStateException("Queue not full yet!"); 68 } 69 final int newSize = growSize(mSize); 70 final long[] newArray = newUnpaddedLongArray(newSize); 71 final int r = mValues.length - mHead; // Number of elements on and to the right of head. 72 System.arraycopy(mValues, mHead, newArray, 0, r); 73 System.arraycopy(mValues, 0, newArray, r, mHead); 74 mValues = newArray; 75 mHead = 0; 76 mTail = mSize; 77 } 78 79 /** 80 * Returns the number of elements in the queue. 81 */ size()82 public int size() { 83 return mSize; 84 } 85 86 /** 87 * Removes all elements from this queue. 88 */ clear()89 public void clear() { 90 mSize = 0; 91 mHead = mTail = 0; 92 } 93 94 /** 95 * Adds a value to the tail of the queue. 96 * 97 * @param value the value to be added. 98 */ addLast(long value)99 public void addLast(long value) { 100 if (mSize == mValues.length) { 101 grow(); 102 } 103 mValues[mTail] = value; 104 mTail = (mTail + 1) % mValues.length; 105 mSize++; 106 } 107 108 /** 109 * Removes an element from the head of the queue. 110 * 111 * @return the element at the head of the queue. 112 * @throws NoSuchElementException if the queue is empty. 113 */ removeFirst()114 public long removeFirst() { 115 if (mSize == 0) { 116 throw new NoSuchElementException("Queue is empty!"); 117 } 118 final long ret = mValues[mHead]; 119 mHead = (mHead + 1) % mValues.length; 120 mSize--; 121 return ret; 122 } 123 124 /** 125 * Returns the element at the given position from the head of the queue, where 0 represents the 126 * head of the queue. 127 * 128 * @param position the position from the head of the queue. 129 * @return the element found at the given position. 130 * @throws IndexOutOfBoundsException if {@code position} < {@code 0} or 131 * {@code position} >= {@link #size()} 132 */ get(int position)133 public long get(int position) { 134 if (position < 0 || position >= mSize) { 135 throw new IndexOutOfBoundsException("Index " + position 136 + " not valid for a queue of size " + mSize); 137 } 138 final int index = (mHead + position) % mValues.length; 139 return mValues[index]; 140 } 141 142 /** 143 * Returns the element at the head of the queue, without removing it. 144 * 145 * @return the element at the head of the queue. 146 * @throws NoSuchElementException if the queue is empty 147 */ peekFirst()148 public long peekFirst() { 149 if (mSize == 0) { 150 throw new NoSuchElementException("Queue is empty!"); 151 } 152 return mValues[mHead]; 153 } 154 155 /** 156 * Returns the element at the tail of the queue. 157 * 158 * @return the element at the tail of the queue. 159 * @throws NoSuchElementException if the queue is empty. 160 */ peekLast()161 public long peekLast() { 162 if (mSize == 0) { 163 throw new NoSuchElementException("Queue is empty!"); 164 } 165 final int index = (mTail == 0) ? mValues.length - 1 : mTail - 1; 166 return mValues[index]; 167 } 168 169 /** 170 * {@inheritDoc} 171 */ 172 @Override toString()173 public String toString() { 174 if (mSize <= 0) { 175 return "{}"; 176 } 177 178 final StringBuilder buffer = new StringBuilder(mSize * 64); 179 buffer.append('{'); 180 buffer.append(get(0)); 181 for (int i = 1; i < mSize; i++) { 182 buffer.append(", "); 183 buffer.append(get(i)); 184 } 185 buffer.append('}'); 186 return buffer.toString(); 187 } 188 } 189