DoubleEndedQueue.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. /**
  3. * This file is part of the ramsey/collection library
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. *
  8. * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
  9. * @license http://opensource.org/licenses/MIT MIT
  10. */
  11. declare(strict_types=1);
  12. namespace Ramsey\Collection;
  13. use Ramsey\Collection\Exception\InvalidArgumentException;
  14. use Ramsey\Collection\Exception\NoSuchElementException;
  15. use function array_key_last;
  16. use function array_pop;
  17. use function array_unshift;
  18. /**
  19. * This class provides a basic implementation of `DoubleEndedQueueInterface`, to
  20. * minimize the effort required to implement this interface.
  21. *
  22. * @template T
  23. * @extends Queue<T>
  24. * @implements DoubleEndedQueueInterface<T>
  25. */
  26. class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
  27. {
  28. /**
  29. * Constructs a double-ended queue (dequeue) object of the specified type,
  30. * optionally with the specified data.
  31. *
  32. * @param string $queueType The type or class name associated with this dequeue.
  33. * @param array<array-key, T> $data The initial items to store in the dequeue.
  34. */
  35. public function __construct(private readonly string $queueType, array $data = [])
  36. {
  37. parent::__construct($this->queueType, $data);
  38. }
  39. /**
  40. * @throws InvalidArgumentException if $element is of the wrong type
  41. */
  42. public function addFirst(mixed $element): bool
  43. {
  44. if ($this->checkType($this->getType(), $element) === false) {
  45. throw new InvalidArgumentException(
  46. 'Value must be of type ' . $this->getType() . '; value is '
  47. . $this->toolValueToString($element),
  48. );
  49. }
  50. array_unshift($this->data, $element);
  51. return true;
  52. }
  53. /**
  54. * @throws InvalidArgumentException if $element is of the wrong type
  55. */
  56. public function addLast(mixed $element): bool
  57. {
  58. return $this->add($element);
  59. }
  60. public function offerFirst(mixed $element): bool
  61. {
  62. try {
  63. return $this->addFirst($element);
  64. } catch (InvalidArgumentException) {
  65. return false;
  66. }
  67. }
  68. public function offerLast(mixed $element): bool
  69. {
  70. return $this->offer($element);
  71. }
  72. /**
  73. * @return T the first element in this queue.
  74. *
  75. * @throws NoSuchElementException if the queue is empty
  76. */
  77. public function removeFirst(): mixed
  78. {
  79. return $this->remove();
  80. }
  81. /**
  82. * @return T the last element in this queue.
  83. *
  84. * @throws NoSuchElementException if this queue is empty.
  85. */
  86. public function removeLast(): mixed
  87. {
  88. return $this->pollLast() ?? throw new NoSuchElementException(
  89. 'Can\'t return element from Queue. Queue is empty.',
  90. );
  91. }
  92. /**
  93. * @return T | null the head of this queue, or `null` if this queue is empty.
  94. */
  95. public function pollFirst(): mixed
  96. {
  97. return $this->poll();
  98. }
  99. /**
  100. * @return T | null the tail of this queue, or `null` if this queue is empty.
  101. */
  102. public function pollLast(): mixed
  103. {
  104. return array_pop($this->data);
  105. }
  106. /**
  107. * @return T the head of this queue.
  108. *
  109. * @throws NoSuchElementException if this queue is empty.
  110. */
  111. public function firstElement(): mixed
  112. {
  113. return $this->element();
  114. }
  115. /**
  116. * @return T the tail of this queue.
  117. *
  118. * @throws NoSuchElementException if this queue is empty.
  119. */
  120. public function lastElement(): mixed
  121. {
  122. return $this->peekLast() ?? throw new NoSuchElementException(
  123. 'Can\'t return element from Queue. Queue is empty.',
  124. );
  125. }
  126. /**
  127. * @return T | null the head of this queue, or `null` if this queue is empty.
  128. */
  129. public function peekFirst(): mixed
  130. {
  131. return $this->peek();
  132. }
  133. /**
  134. * @return T | null the tail of this queue, or `null` if this queue is empty.
  135. */
  136. public function peekLast(): mixed
  137. {
  138. $lastIndex = array_key_last($this->data);
  139. if ($lastIndex === null) {
  140. return null;
  141. }
  142. return $this->data[$lastIndex];
  143. }
  144. }