/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package stdx.net.http
open class DefaultQueue<T> {
protected var buffer: Array<Option<T>>
protected var rear: Int64 = -1
protected var front: Int64 = -1
protected var size_: Int64 = 0
protected var capacity_: Int64
protected var evictEnable: Bool = false
protected var evictCount: Int64 = 0
init() {
this(0)
}
init(capacity: Int64) {
if (capacity < 0) {
throw IllegalArgumentException("Failed to init queue, invalid capacity: ${capacity}.")
}
buffer = Array<Option<T>>(capacity, repeat: Option<T>.None)
capacity_ = capacity
}
prop size: Int64 {
get() {
return size_
}
}
prop capacity: Int64 {
get() {
return capacity_
}
}
/**
* insert element to the rear
*/
func enqueue(element: T): Bool {
if (!prepareForEnqueue()) {
return false
}
rear = adjustment(rear + 1)
buffer[rear] = element
size_++
return true
}
/**
* remove element from the front
*/
func dequeue(): Option<T> {
if (isEmpty()) {
return None
}
let v = buffer[front]
match {
case size == 1 => reset()
case _ =>
front = adjustment(front + 1)
size_--
}
return v
}
// get from front
func get(index: Int64): Option<T> {
if (isEmpty() || index >= size || index < 0) { // empty or out of bound
return None
}
let pos = adjustment(front + index)
return buffer[pos]
}
// get from rear
func latest(index: Int64): Option<T> {
if (isEmpty() || index >= size || index < 0) { // empty or out of bound
return None
}
let pos = adjustment(rear - index)
return buffer[pos]
}
func isEmpty(): Bool {
return size == 0
}
func isFull(): Bool {
return size == capacity
}
/**
* Suppose 0<= newPosition < capacity * 2
*/
protected func adjustment(newPosition: Int64): Int64 {
return (newPosition + buffer.size) % buffer.size
}
protected func grow(newCapacity: Int64): Unit {
evictCount = 0
return match {
case newCapacity < capacity => throw IllegalArgumentException("Reduce size is not supported.")
case newCapacity > capacity => growCapacity(newCapacity)
case _ => ()
}
}
private func prepareForEnqueue(): Bool {
if (isFull()) { // need grow or evict or reject
match {
case evictEnable => match {
case capacity == 0 => return false // no capacity to evict
case _ =>
front = adjustment(front + 1) // evict from front
size_--
evictCount++
}
case _ => grow(nextCapacity()) // grow queue to add element
}
}
if (isEmpty()) { // it's the first
front = 0
rear = -1
}
return true
}
private func growCapacity(newCapacity: Int64): Unit {
let newBuffer = Array<Option<T>>(newCapacity, {
i => if (i < size) {
get(i).getOrThrow()
} else {
None
}
})
buffer = newBuffer
capacity_ = newCapacity
if (size > 0) {
front = 0
rear = size - 1
}
}
private func reset(): Unit {
rear = -1
front = -1
size_ = 0
}
private func nextCapacity(): Int64 {
var v: Int64 = capacity
var n: Int64 = 0
while (v != 0) {
v >>= 1
n++
}
return 1 << n
}
}