Reimplement data structures based on SPL
This commit is contained in:
parent
dc4209e40f
commit
a84046755e
|
@ -1,111 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Useful PHP Basics
|
|
||||||
* Copyright (C) 2023 Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
|
||||||
|
|
||||||
use InvalidArgumentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A type-sensitive, ordered Set.
|
|
||||||
*
|
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
|
||||||
* @package opencultureconsulting/basics
|
|
||||||
* @implements \Countable
|
|
||||||
* @implements \Iterator
|
|
||||||
* @implements \Serializable
|
|
||||||
*/
|
|
||||||
class Set extends AbstractList
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Add a single item.
|
|
||||||
*
|
|
||||||
* @param mixed $item The item to add
|
|
||||||
* @param ?int $offset Optional offset to add, defaults to append
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function add(mixed $item, ?int $offset = null): void
|
|
||||||
{
|
|
||||||
if (is_null($offset)) {
|
|
||||||
$this->append($item);
|
|
||||||
} elseif (isset($item)) {
|
|
||||||
if (!$this->isAllowedType($item)) {
|
|
||||||
throw new InvalidArgumentException('Parameter 1 must be an allowed type, ' . get_debug_type($item) . ' given.');
|
|
||||||
}
|
|
||||||
array_splice($this->items, $offset, 0, [$item]);
|
|
||||||
if ($offset >= 0) {
|
|
||||||
if ($offset <= $this->position) {
|
|
||||||
++$this->position;
|
|
||||||
}
|
|
||||||
} elseif ($offset < 0) {
|
|
||||||
if (($offset + $this->count()) <= $this->position) {
|
|
||||||
++$this->position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a single item.
|
|
||||||
*
|
|
||||||
* @param ?int $offset Optional offset to peek, defaults to current
|
|
||||||
*
|
|
||||||
* @return mixed The item or NULL if empty
|
|
||||||
*/
|
|
||||||
public function peek(?int $offset = null): mixed
|
|
||||||
{
|
|
||||||
if (is_null($offset)) {
|
|
||||||
return $this->current();
|
|
||||||
}
|
|
||||||
$item = array_slice($this->items, $offset, 1);
|
|
||||||
return $item[0] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a single item.
|
|
||||||
*
|
|
||||||
* @param ?int $offset Optional offset to remove, defauls to current
|
|
||||||
*
|
|
||||||
* @return mixed The removed item or NULL if empty
|
|
||||||
*/
|
|
||||||
public function remove(?int $offset = null): mixed
|
|
||||||
{
|
|
||||||
if (is_null($offset)) {
|
|
||||||
$offset = $this->position;
|
|
||||||
}
|
|
||||||
$item = array_splice($this->items, $offset, 1);
|
|
||||||
if (isset($item[0])) {
|
|
||||||
if ($offset >= 0) {
|
|
||||||
if ($offset <= $this->position) {
|
|
||||||
--$this->position;
|
|
||||||
}
|
|
||||||
} elseif ($offset < 0) {
|
|
||||||
if (($offset + $this->count()) <= $this->position) {
|
|
||||||
--$this->position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $item[0] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,35 +22,25 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
use Countable;
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Iterator;
|
use SplDoublyLinkedList;
|
||||||
use OCC\Basics\Traits\Getter;
|
use OCC\Basics\Traits\Getter;
|
||||||
use Serializable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prototype for a type-sensitive, ordered list of items.
|
* A type-sensitive, taversable List.
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package opencultureconsulting/basics
|
* @package opencultureconsulting/basics
|
||||||
|
*
|
||||||
|
* @implements \ArrayAccess
|
||||||
* @implements \Countable
|
* @implements \Countable
|
||||||
* @implements \Iterator
|
* @implements \Iterator
|
||||||
* @implements \Serializable
|
* @implements \Serializable
|
||||||
*/
|
*/
|
||||||
abstract class AbstractList implements Countable, Iterator, Serializable
|
class StrictList extends SplDoublyLinkedList
|
||||||
{
|
{
|
||||||
use Getter;
|
use Getter;
|
||||||
|
|
||||||
/**
|
|
||||||
* The items.
|
|
||||||
*/
|
|
||||||
protected array $items = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current position of iterator.
|
|
||||||
*/
|
|
||||||
protected int $position = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the allowed types for items.
|
* Defines the allowed types for items.
|
||||||
* If empty, all types are allowed.
|
* If empty, all types are allowed.
|
||||||
|
@ -74,9 +64,28 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
protected array $allowedTypes = [];
|
protected array $allowedTypes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append items.
|
* Add/insert a new item at the specified index.
|
||||||
|
* @see SplDoublyLinkedList::add
|
||||||
*
|
*
|
||||||
* @param mixed ...$items One or more items to add
|
* @param int $index The index where the new item is to be inserted
|
||||||
|
* @param mixed $item The new item for the index
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function add(int $index, mixed $item): void
|
||||||
|
{
|
||||||
|
if (!$this->isAllowedType($item)) {
|
||||||
|
throw new InvalidArgumentException('Parameter 2 must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
|
}
|
||||||
|
parent::add($index, $item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append items at the end of the list.
|
||||||
|
*
|
||||||
|
* @param mixed ...$items One or more items to append
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
@ -84,57 +93,34 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
*/
|
*/
|
||||||
public function append(mixed ...$items): void
|
public function append(mixed ...$items): void
|
||||||
{
|
{
|
||||||
if (!empty($this->allowedTypes)) {
|
|
||||||
foreach ($items as $count => $item) {
|
foreach ($items as $count => $item) {
|
||||||
if (!$this->isAllowedType($item)) {
|
if (!$this->isAllowedType($item)) {
|
||||||
throw new InvalidArgumentException('Parameter ' . $count + 1 . ' must be an allowed type, ' . get_debug_type($item) . ' given.');
|
throw new InvalidArgumentException('Parameter ' . $count + 1 . ' must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach ($items as $item) {
|
||||||
|
parent::push($item);
|
||||||
}
|
}
|
||||||
$this->items = array_merge($this->items, $items);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of items.
|
* Get the allowed item types.
|
||||||
* @see Countable::count
|
|
||||||
*
|
*
|
||||||
* @return int The number of items
|
* @return array The list of allowed item types
|
||||||
*/
|
*/
|
||||||
public function count(): int
|
public function getAllowedTypes(): array
|
||||||
{
|
{
|
||||||
return count($this->items);
|
return $this->allowedTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all items.
|
* Check if item is an allowed type.
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function clear(): void
|
|
||||||
{
|
|
||||||
$this->items = [];
|
|
||||||
$this->rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current item.
|
|
||||||
* @see Iterator::current
|
|
||||||
*
|
|
||||||
* @return mixed The current item or NULL if empty
|
|
||||||
*/
|
|
||||||
public function current(): mixed
|
|
||||||
{
|
|
||||||
return $this->items[$this->position] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if an item is an allowed type.
|
|
||||||
*
|
*
|
||||||
* @param mixed $item The item to check
|
* @param mixed $item The item to check
|
||||||
*
|
*
|
||||||
* @return bool Whether the item is an allowed type
|
* @return bool Whether the item is an allowed type
|
||||||
*/
|
*/
|
||||||
protected function isAllowedType(mixed $item): bool
|
public function isAllowedType(mixed $item): bool
|
||||||
{
|
{
|
||||||
if (empty($this->allowedTypes)) {
|
if (empty($this->allowedTypes)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -152,17 +138,6 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current iterator position.
|
|
||||||
* @see Iterator::key
|
|
||||||
*
|
|
||||||
* @return int The current iterator position
|
|
||||||
*/
|
|
||||||
public function key(): int
|
|
||||||
{
|
|
||||||
return $this->position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic getter method for $this->allowedTypes.
|
* Magic getter method for $this->allowedTypes.
|
||||||
* @see OCC\Basics\Traits\Getter
|
* @see OCC\Basics\Traits\Getter
|
||||||
|
@ -175,34 +150,70 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move iterator to next position.
|
* Set the item at the specified index.
|
||||||
* @see Iterator::next
|
* @see ArrayAccess::offsetSet
|
||||||
|
*
|
||||||
|
* @param ?int $index The index being set or NULL to append
|
||||||
|
* @param mixed $item The new item for the index
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function next(): void
|
public function offsetSet(mixed $index, mixed $item): void
|
||||||
{
|
{
|
||||||
++$this->position;
|
if (!$this->isAllowedType($item)) {
|
||||||
|
throw new InvalidArgumentException('Parameter 2 must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
|
}
|
||||||
|
parent::offsetSet($index, $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the iterator position.
|
* Prepend items at the start of the list.
|
||||||
* @see Iterator::rewind
|
*
|
||||||
|
* @param mixed ...$items One or more items to prepend
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function rewind(): void
|
public function prepend(mixed ...$items): void
|
||||||
{
|
{
|
||||||
$this->position = 0;
|
foreach ($items as $count => $item) {
|
||||||
|
if (!$this->isAllowedType($item)) {
|
||||||
|
throw new InvalidArgumentException('Parameter ' . $count + 1 . ' must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($items as $item) {
|
||||||
|
parent::unshift($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push an item at the end of the list.
|
||||||
|
* @see SplDoublyLinkedList::push
|
||||||
|
*
|
||||||
|
* @param mixed $item The item to push
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function push(mixed $item): void
|
||||||
|
{
|
||||||
|
if (!$this->isAllowedType($item)) {
|
||||||
|
throw new InvalidArgumentException('Parameter 1 must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
|
}
|
||||||
|
parent::push($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get string representation of $this.
|
* Get string representation of $this.
|
||||||
* @see Serializable::serialize
|
* @see Serializable::serialize
|
||||||
*
|
*
|
||||||
* @return ?string String representation
|
* @return string String representation
|
||||||
*/
|
*/
|
||||||
public function serialize(): ?string
|
public function serialize(): string
|
||||||
{
|
{
|
||||||
return serialize($this->__serialize());
|
return serialize($this->__serialize());
|
||||||
}
|
}
|
||||||
|
@ -221,30 +232,27 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if there is an item at the current position.
|
* Prepend the list with an item.
|
||||||
* @see Iterator::valid
|
* @see SplDoublyLinkedList::unshift
|
||||||
*
|
*
|
||||||
* @return bool Is there an item at the current position?
|
* @param mixed $item The item to unshift
|
||||||
*/
|
|
||||||
public function valid(): bool
|
|
||||||
{
|
|
||||||
return isset($this->items[$this->position]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset iterator position after cloning.
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function __clone(): void
|
public function unshift(mixed $item): void
|
||||||
{
|
{
|
||||||
$this->rewind();
|
if (!$this->isAllowedType($item)) {
|
||||||
|
throw new InvalidArgumentException('Parameter 1 must be an allowed type, ' . get_debug_type($item) . ' given.');
|
||||||
|
}
|
||||||
|
parent::unshift($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a type-sensitive traversable list of items.
|
* Create a type-sensitive, traversable list of items.
|
||||||
*
|
*
|
||||||
* @param iterable $items Initial list of items
|
* @param iterable $items Initial set of items
|
||||||
* @param string[] $allowedTypes Allowed types of items (optional)
|
* @param string[] $allowedTypes Allowed types of items (optional)
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
@ -256,7 +264,6 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
}
|
}
|
||||||
$this->allowedTypes = $allowedTypes;
|
$this->allowedTypes = $allowedTypes;
|
||||||
$this->append(...$items);
|
$this->append(...$items);
|
||||||
$this->rewind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,7 +285,8 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'allowedTypes' => $this->allowedTypes,
|
'allowedTypes' => $this->allowedTypes,
|
||||||
'items' => $this->items
|
'splDoublyLinkedList::flags' => $this->getIteratorMode(),
|
||||||
|
'splDoublyLinkedList::dllist' => iterator_to_array($this)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +299,7 @@ abstract class AbstractList implements Countable, Iterator, Serializable
|
||||||
*/
|
*/
|
||||||
public function __unserialize(array $data): void
|
public function __unserialize(array $data): void
|
||||||
{
|
{
|
||||||
$this->__construct($data['items'], $data['allowedTypes']);
|
$this->__construct($data['splDoublyLinkedList::dllist'], $data['allowedTypes']);
|
||||||
|
$this->setIteratorMode($data['splDoublyLinkedList::flags']);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,52 +22,48 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type-sensitive, destructive Last In, First Out Stack.
|
* A type-sensitive, taversable First In, First Out Queue (FIFO).
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package opencultureconsulting/basics
|
* @package opencultureconsulting/basics
|
||||||
|
*
|
||||||
|
* @implements \ArrayAccess
|
||||||
* @implements \Countable
|
* @implements \Countable
|
||||||
* @implements \Iterator
|
* @implements \Iterator
|
||||||
* @implements \Serializable
|
* @implements \Serializable
|
||||||
*/
|
*/
|
||||||
class Stack extends AbstractList
|
class StrictQueue extends StrictList
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the last item and remove it.
|
* Set the mode of iteration.
|
||||||
* @see Iterator::current
|
* @see SplDoublyLinkedList::setIteratorMode
|
||||||
*
|
*
|
||||||
* @return mixed The last item or NULL if empty
|
* @param int $mode The new iterator mode (0 or 1)
|
||||||
|
*
|
||||||
|
* @return int The set of flags and modes of iteration
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public function current(): mixed
|
public function setIteratorMode(int $mode): int
|
||||||
{
|
{
|
||||||
return array_pop($this->items);
|
if ($mode > 1) {
|
||||||
|
throw new RuntimeException('Changing the iterator direction of ' . static::class . ' is prohibited.');
|
||||||
|
}
|
||||||
|
return parent::setIteratorMode($mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single item without removing it.
|
* Create a type-sensitive, traversable queue of items.
|
||||||
*
|
*
|
||||||
* @param ?int $offset Optional offset to peek, defaults to last
|
* @param iterable $items Initial set of items
|
||||||
*
|
* @param string[] $allowedTypes Allowed types of items (optional)
|
||||||
* @return mixed The item or NULL if empty
|
|
||||||
*/
|
*/
|
||||||
public function peek(?int $offset = null): mixed
|
public function __construct(iterable $items = [], array $allowedTypes = [])
|
||||||
{
|
{
|
||||||
if (is_null($offset)) {
|
parent::__construct($items, $allowedTypes);
|
||||||
return end($this->items) ?? null;
|
$this->setIteratorMode(0);
|
||||||
}
|
|
||||||
$item = array_slice($this->items, $offset, 1);
|
|
||||||
return $item[0] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an item left on the stack.
|
|
||||||
* @see Iterator::valid
|
|
||||||
*
|
|
||||||
* @return bool Is there an item on the stack?
|
|
||||||
*/
|
|
||||||
public function valid(): bool
|
|
||||||
{
|
|
||||||
return (bool) $this->count();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,52 +22,48 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCC\Basics\DataStructures;
|
namespace OCC\Basics\DataStructures;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type-sensitive, destructive First In, First Out Queue.
|
* A type-sensitive, taversable Last In, First Out Stack (LIFO).
|
||||||
*
|
*
|
||||||
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
* @author Sebastian Meyer <sebastian.meyer@opencultureconsulting.com>
|
||||||
* @package opencultureconsulting/basics
|
* @package opencultureconsulting/basics
|
||||||
|
*
|
||||||
|
* @implements \ArrayAccess
|
||||||
* @implements \Countable
|
* @implements \Countable
|
||||||
* @implements \Iterator
|
* @implements \Iterator
|
||||||
* @implements \Serializable
|
* @implements \Serializable
|
||||||
*/
|
*/
|
||||||
class Queue extends AbstractList
|
class StrictStack extends StrictList
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the first item and remove it.
|
* Set the mode of iteration.
|
||||||
* @see Iterator::current
|
* @see SplDoublyLinkedList::setIteratorMode
|
||||||
*
|
*
|
||||||
* @return mixed The first item or NULL if empty
|
* @param int $mode The new iterator mode (2 or 3)
|
||||||
|
*
|
||||||
|
* @return int The set of flags and modes of iteration
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException
|
||||||
*/
|
*/
|
||||||
public function current(): mixed
|
public function setIteratorMode(int $mode): int
|
||||||
{
|
{
|
||||||
return array_shift($this->items);
|
if ($mode < 2) {
|
||||||
|
throw new RuntimeException('Changing the iterator direction of ' . static::class . ' is prohibited.');
|
||||||
|
}
|
||||||
|
return parent::setIteratorMode($mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single item without removing it.
|
* Create a type-sensitive, traversable stack of items.
|
||||||
*
|
*
|
||||||
* @param ?int $offset Optional offset to peek, defaults to first
|
* @param iterable $items Initial set of items
|
||||||
*
|
* @param string[] $allowedTypes Allowed types of items (optional)
|
||||||
* @return mixed The item or NULL if empty
|
|
||||||
*/
|
*/
|
||||||
public function peek(?int $offset = null): mixed
|
public function __construct(iterable $items = [], array $allowedTypes = [])
|
||||||
{
|
{
|
||||||
if (is_null($offset)) {
|
parent::__construct($items, $allowedTypes);
|
||||||
return reset($this->items) ?? null;
|
$this->setIteratorMode(2);
|
||||||
}
|
|
||||||
$item = array_slice($this->items, $offset, 1);
|
|
||||||
return $item[0] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an item left on the queue.
|
|
||||||
* @see Iterator::valid
|
|
||||||
*
|
|
||||||
* @return bool Is there an item on the queue?
|
|
||||||
*/
|
|
||||||
public function valid(): bool
|
|
||||||
{
|
|
||||||
return (bool) $this->count();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue