ignorer BOM

This commit is contained in:
Jephté Clain 2024-04-23 04:54:18 +04:00
parent 31d67148c3
commit 6a837fbcb3
3 changed files with 40 additions and 7 deletions

View File

@ -7,9 +7,17 @@ use nur\sery\os\IOException;
* Class FileReader: un fichier accédé en lecture * Class FileReader: un fichier accédé en lecture
*/ */
class FileReader extends _File { class FileReader extends _File {
/** @var bool *à l'ouverture du fichier*, faut-il ignorer le BOM? */
const IGNORE_BOM = true;
const DEFAULT_MODE = "rb"; const DEFAULT_MODE = "rb";
function __construct($input, ?string $mode=null, bool $throwOnError=true, ?bool $allowLocking=null) { /** @var bool */
protected $ignoreBom;
function __construct($input, ?string $mode=null, bool $throwOnError=true, ?bool $allowLocking=null, ?bool $ignoreBom=null) {
if ($ignoreBom === null) $ignoreBom = static::IGNORE_BOM;
$this->ignoreBom = $ignoreBom;
if ($input === null) { if ($input === null) {
$fd = STDIN; $fd = STDIN;
$close = false; $close = false;
@ -26,4 +34,20 @@ class FileReader extends _File {
} }
parent::__construct($fd, $close, $throwOnError, $allowLocking); parent::__construct($fd, $close, $throwOnError, $allowLocking);
} }
/** @return resource */
protected function open() {
$fd = parent::open();
$this->haveBom = false;
if ($this->ignoreBom) {
$bom = fread($fd, 3);
if ($bom === "\xEF\xBB\xBF") $this->seekOffset = 3;
else rewind($fd);
}
return $fd;
}
function haveBom(): bool {
return $this->seekOffset !== 0;
}
} }

View File

@ -29,6 +29,9 @@ class Stream extends AbstractIterator implements IReader, IWriter {
/** @var bool */ /** @var bool */
protected $useLocking; protected $useLocking;
/** @var int nombre d'octets à ignorer au début du fichier lors d'un seek */
protected $seekOffset = 0;
/** @var int|null */ /** @var int|null */
protected $serial; protected $serial;
@ -84,24 +87,28 @@ class Stream extends AbstractIterator implements IReader, IWriter {
return $this->stat; return $this->stat;
} }
function getSize(): int { function getSize(?int $seekOffset=null): int {
return $this->fstat()["size"]; if ($seekOffset === null) $seekOffset = $this->seekOffset;
return $this->fstat()["size"] - $seekOffset;
} }
/** @throws IOException */ /** @throws IOException */
function ftell(): int { function ftell(?int $seekOffset=null): int {
$fd = $this->getResource(); $fd = $this->getResource();
return IOException::ensure_valid(ftell($fd), $this->throwOnError); if ($seekOffset === null) $seekOffset = $this->seekOffset;
return IOException::ensure_valid(ftell($fd), $this->throwOnError) - $seekOffset;
} }
/** /**
* @return int la position après avoir déplacé le pointeur * @return int la position après avoir déplacé le pointeur
* @throws IOException * @throws IOException
*/ */
function fseek(int $offset, int $whence=SEEK_SET): int { function fseek(int $offset, int $whence=SEEK_SET, ?int $seekOffset=null): int {
$fd = $this->getResource(); $fd = $this->getResource();
if ($seekOffset === null) $seekOffset = $this->seekOffset;
if ($whence === SEEK_SET) $offset += $seekOffset;
IOException::ensure_valid(fseek($fd, $offset, $whence), $this->throwOnError, -1); IOException::ensure_valid(fseek($fd, $offset, $whence), $this->throwOnError, -1);
return $this->ftell(); return $this->ftell($seekOffset);
} }
function seek(int $offset, int $whence=SEEK_SET): self { function seek(int $offset, int $whence=SEEK_SET): self {

View File

@ -15,10 +15,12 @@ abstract class _File extends Stream {
/** @var string */ /** @var string */
protected $mode; protected $mode;
/** @return resource */
protected function open() { protected function open() {
return IOException::ensure_valid(@fopen($this->file, $this->mode)); return IOException::ensure_valid(@fopen($this->file, $this->mode));
} }
/** @return resource */
function getResource() { function getResource() {
if ($this->fd === null && $this->file !== null) $this->fd = $this->open(); if ($this->fd === null && $this->file !== null) $this->fd = $this->open();
return parent::getResource(); return parent::getResource();