149 lines
3.4 KiB
PHP
149 lines
3.4 KiB
PHP
|
<?php
|
||
|
namespace nulib\php\iter;
|
||
|
|
||
|
use Exception;
|
||
|
use Iterator;
|
||
|
use nulib\os\EOFException;
|
||
|
use nulib\php\ICloseable;
|
||
|
|
||
|
/**
|
||
|
* Class AbstractIterator: implémentation de base d'un itérateur
|
||
|
*/
|
||
|
abstract class AbstractIterator implements Iterator, ICloseable {
|
||
|
/**
|
||
|
* initialiser les ressources nécessaires à l'itération.
|
||
|
*
|
||
|
* les exceptions lancées par cette méthode sont ignorées.
|
||
|
*/
|
||
|
protected function _setup(): void {}
|
||
|
|
||
|
/**
|
||
|
* lancer un traitement avant de commencer l'itération.
|
||
|
*
|
||
|
* cette méthode est appelée après {@link _setup()} et l'objet est garanti
|
||
|
* d'être dans un état valide.
|
||
|
*
|
||
|
* cette méthode est prévue pour être surchargée par l'utilisateur, mais il
|
||
|
* doit gérer lui-même les exceptions éventuelles.
|
||
|
*/
|
||
|
protected function beforeIter() {}
|
||
|
|
||
|
/**
|
||
|
* retourner le prochain élément. lancer l'exception {@link EOFException} pour
|
||
|
* indiquer que plus aucun élément n'est disponible
|
||
|
*
|
||
|
* le cas échéant, initialiser $key
|
||
|
*
|
||
|
* @throws EOFException
|
||
|
*/
|
||
|
abstract protected function _next(&$key);
|
||
|
|
||
|
/**
|
||
|
* modifier l'élement retourné par {@link _next()} avant de le retourner.
|
||
|
*
|
||
|
*
|
||
|
* cette méthode est prévue pour être surchargée par l'utilisateur, mais il
|
||
|
* doit gérer lui-même les exceptions éventuelles.
|
||
|
*/
|
||
|
protected function cook(&$item) {}
|
||
|
|
||
|
/**
|
||
|
* lancer un traitement avant de terminer l'itération et de libérer les
|
||
|
* resources
|
||
|
*
|
||
|
* cette méthode est appelée avant {@link _teardown()} et l'objet est garanti
|
||
|
* d'être dans un état valide.
|
||
|
*
|
||
|
* cette méthode est prévue pour être surchargée par l'utilisateur, mais il
|
||
|
* doit gérer lui-même les exceptions éventuelles.
|
||
|
*/
|
||
|
protected function beforeClose(): void {}
|
||
|
|
||
|
/**
|
||
|
* libérer les ressources allouées.
|
||
|
*
|
||
|
* les exceptions lancées par cette méthode sont ignorées.
|
||
|
*/
|
||
|
protected function _teardown(): void {}
|
||
|
|
||
|
function close(): void {
|
||
|
$this->rewind();
|
||
|
}
|
||
|
|
||
|
#############################################################################
|
||
|
# Implémentation par défaut
|
||
|
|
||
|
private $setup = false;
|
||
|
private $valid = false;
|
||
|
private $toredown = true;
|
||
|
|
||
|
private $index = 0;
|
||
|
protected $key;
|
||
|
protected $item = null;
|
||
|
|
||
|
function key() {
|
||
|
return $this->key;
|
||
|
}
|
||
|
|
||
|
function current() {
|
||
|
return $this->item;
|
||
|
}
|
||
|
|
||
|
function next(): void {
|
||
|
if ($this->toredown) return;
|
||
|
$this->valid = false;
|
||
|
try {
|
||
|
$item = $this->_next($key);
|
||
|
} catch (EOFException $e) {
|
||
|
$this->beforeClose();
|
||
|
try {
|
||
|
$this->_teardown();
|
||
|
} catch (Exception $e) {
|
||
|
}
|
||
|
$this->toredown = true;
|
||
|
return;
|
||
|
}
|
||
|
$this->cook($item);
|
||
|
$this->item = $item;
|
||
|
if ($key !== null) {
|
||
|
$this->key = $key;
|
||
|
} else {
|
||
|
$this->index++;
|
||
|
$this->key = $this->index;
|
||
|
}
|
||
|
$this->valid = true;
|
||
|
}
|
||
|
|
||
|
function rewind(): void {
|
||
|
if ($this->setup) {
|
||
|
if (!$this->toredown) {
|
||
|
$this->beforeClose();
|
||
|
try {
|
||
|
$this->_teardown();
|
||
|
} catch (Exception $e) {
|
||
|
}
|
||
|
}
|
||
|
$this->setup = false;
|
||
|
$this->valid = false;
|
||
|
$this->toredown = true;
|
||
|
$this->index = 0;
|
||
|
$this->key = null;
|
||
|
$this->item = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function valid(): bool {
|
||
|
if (!$this->setup) {
|
||
|
try {
|
||
|
$this->_setup();
|
||
|
} catch (Exception $e) {
|
||
|
}
|
||
|
$this->setup = true;
|
||
|
$this->toredown = false;
|
||
|
$this->beforeIter();
|
||
|
$this->next();
|
||
|
}
|
||
|
return $this->valid;
|
||
|
}
|
||
|
}
|