Redid some core IO stuff and fixed tests.
This commit is contained in:
parent
5ec90ec1ba
commit
eae6e12ac0
6 changed files with 344 additions and 330 deletions
294
src/IO/File.php
294
src/IO/File.php
|
@ -1,167 +1,26 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Misuzu\IO;
|
namespace Misuzu\IO;
|
||||||
|
|
||||||
use ErrorException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for f* (file stream) functions and other cool stuff.
|
* Static file meta functions.
|
||||||
* @package Misuzu\IO
|
* @package Misuzu\IO
|
||||||
* @author flashwave <me@flash.moe>
|
* @author flashwave <me@flash.moe>
|
||||||
*/
|
*/
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
/**
|
public static function open(string $filename): FileStream
|
||||||
* Open + Read flag.
|
|
||||||
*/
|
|
||||||
public const OPEN_READ = 'rb';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open + Write flag.
|
|
||||||
*/
|
|
||||||
public const OPEN_WRITE = 'cb';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open + Read + Write flag.
|
|
||||||
*/
|
|
||||||
public const OPEN_READ_WRITE = 'rb+';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create (truncates!) + Write flag.
|
|
||||||
*/
|
|
||||||
public const CREATE_WRITE = 'wb';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create (truncates!) + Read + Write flag.
|
|
||||||
*/
|
|
||||||
public const CREATE_READ_WRITE = 'wb+';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open + Write flag.
|
|
||||||
*/
|
|
||||||
public const OPEN_CREATE_WRITE = 'xb';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open or Create + Read + Write flag.
|
|
||||||
*/
|
|
||||||
public const OPEN_CREATE_READ_WRITE = 'xb+';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resource/stream container.
|
|
||||||
* @var resource
|
|
||||||
*/
|
|
||||||
private $resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filename.
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Real, fixed path.
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $path = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filesize in bytes.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $size = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ID of file owner.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $owner = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ID of file's owning group.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $group = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last time this file has been accessed.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $accessTime = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last time this file has been modified.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $modifiedTime = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current stream position.
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public $position = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes path and opens resource.
|
|
||||||
* @param string $path
|
|
||||||
* @param string $mode
|
|
||||||
* @throws FileDoesNotExistException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public function __construct(string $path, string $mode)
|
|
||||||
{
|
{
|
||||||
$path = Directory::fixSlashes($path);
|
return new FileStream($filename, FileStream::MODE_READ_WRITE, true);
|
||||||
$this->path = realpath($path);
|
|
||||||
$this->name = basename($this->path);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->resource = fopen($path, $mode, false);
|
|
||||||
} catch (ErrorException $e) {
|
|
||||||
throw new FileDoesNotExistException($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_resource($this->resource)) {
|
|
||||||
throw new IOException('Failed to create resource.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->updateMetaData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the meta data of the resource.
|
|
||||||
*/
|
|
||||||
private function updateMetaData(): void
|
|
||||||
{
|
|
||||||
$meta = fstat($this->resource);
|
|
||||||
$this->size = intval($meta['size']);
|
|
||||||
$this->owner = intval($meta['uid']);
|
|
||||||
$this->group = intval($meta['gid']);
|
|
||||||
$this->accessTime = intval($meta['atime']);
|
|
||||||
$this->modifiedTime = intval($meta['mtime']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the position variable.
|
|
||||||
*/
|
|
||||||
private function updatePosition(): void
|
|
||||||
{
|
|
||||||
$this->position = ftell($this->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the close method.
|
|
||||||
*/
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of a temporary file.
|
* Creates an instance of a temporary file.
|
||||||
* @param string $prefix
|
* @param string $prefix
|
||||||
* @return File
|
* @return FileStream
|
||||||
*/
|
*/
|
||||||
public static function temp(string $prefix = 'Misuzu'): File
|
public static function temp(string $prefix = 'Misuzu'): FileStream
|
||||||
{
|
{
|
||||||
return new static(tempnam(sys_get_temp_dir(), $prefix));
|
return static::open(tempnam(sys_get_temp_dir(), $prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,145 +49,4 @@ class File
|
||||||
|
|
||||||
unlink($path);
|
unlink($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the resource context.
|
|
||||||
*/
|
|
||||||
public function close(): void
|
|
||||||
{
|
|
||||||
if (is_resource($this->resource)) {
|
|
||||||
fclose($this->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the position to 0.
|
|
||||||
*/
|
|
||||||
public function start(): void
|
|
||||||
{
|
|
||||||
rewind($this->resource);
|
|
||||||
$this->updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the position to the end of the file.
|
|
||||||
*/
|
|
||||||
public function end(): void
|
|
||||||
{
|
|
||||||
fseek($this->resource, 0, SEEK_END);
|
|
||||||
$this->updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the position.
|
|
||||||
* @param int $offset
|
|
||||||
* @param bool $relative
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function position(int $offset, bool $relative = false): int
|
|
||||||
{
|
|
||||||
fseek($this->resource, $offset, $relative ? SEEK_CUR : SEEK_SET);
|
|
||||||
$this->updatePosition();
|
|
||||||
return $this->position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the current position is the end of the file.
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function atEOF(): bool
|
|
||||||
{
|
|
||||||
return feof($this->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to find the position of a string in the context.
|
|
||||||
* @param string $string
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function find(string $string): int
|
|
||||||
{
|
|
||||||
while ($this->position < $this->size) {
|
|
||||||
$find = strpos($this->read(8192), $string);
|
|
||||||
|
|
||||||
if ($find !== false) {
|
|
||||||
return $find + $this->position;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->position($this->position + 8192);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locks the file and reads from it.
|
|
||||||
* @param int $length
|
|
||||||
* @throws IOException
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function read(int $length = null): string
|
|
||||||
{
|
|
||||||
if ($length === null) {
|
|
||||||
$length = $this->size;
|
|
||||||
$this->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
flock($this->resource, LOCK_SH);
|
|
||||||
$data = fread($this->resource, $length);
|
|
||||||
flock($this->resource, LOCK_UN);
|
|
||||||
|
|
||||||
if ($data === false) {
|
|
||||||
throw new IOException('Read failed.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->updateMetaData();
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the character at the current position.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function char(): string
|
|
||||||
{
|
|
||||||
return fgetc($this->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locks the file, writes to the stream and flushes to file.
|
|
||||||
* @param string $data
|
|
||||||
* @param int $length
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public function write(string $data, int $length = 0): void
|
|
||||||
{
|
|
||||||
if ($length > 0) {
|
|
||||||
$length = strlen($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
flock($this->resource, LOCK_EX);
|
|
||||||
$write = fwrite($this->resource, $data, $length);
|
|
||||||
$flush = fflush($this->resource);
|
|
||||||
flock($this->resource, LOCK_UN);
|
|
||||||
|
|
||||||
if ($write === false || $flush === false) {
|
|
||||||
throw new IOException('Write failed.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->updateMetaData();
|
|
||||||
$this->updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The same as write except it moves to the end of the file first.
|
|
||||||
* @param string $data
|
|
||||||
* @param int $length
|
|
||||||
*/
|
|
||||||
public function append(string $data, int $length = 0): void
|
|
||||||
{
|
|
||||||
$this->end();
|
|
||||||
$this->write($data, $length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
252
src/IO/FileStream.php
Normal file
252
src/IO/FileStream.php
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\IO;
|
||||||
|
|
||||||
|
use ErrorException;
|
||||||
|
|
||||||
|
class FileStream extends Stream
|
||||||
|
{
|
||||||
|
public const MODE_READ = 0x1;
|
||||||
|
public const MODE_WRITE = 0x2;
|
||||||
|
public const MODE_READ_WRITE = self::MODE_READ | self::MODE_WRITE;
|
||||||
|
private const MODE_TRUNCATE_RAW = 0x4;
|
||||||
|
public const MODE_TRUNCATE = self::MODE_TRUNCATE_RAW | self::MODE_WRITE;
|
||||||
|
private const MODE_APPEND_RAW = 0x8;
|
||||||
|
public const MODE_APPEND = self::MODE_APPEND_RAW | self::MODE_WRITE;
|
||||||
|
|
||||||
|
protected $fileHandle;
|
||||||
|
protected $filePath;
|
||||||
|
protected $fileMode;
|
||||||
|
protected $isLocked;
|
||||||
|
|
||||||
|
public function __construct(string $path, int $mode, bool $lock = true)
|
||||||
|
{
|
||||||
|
$this->isLocked = $lock;
|
||||||
|
$this->filePath = $path;
|
||||||
|
$this->fileMode = $mode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->fileHandle = fopen($this->filePath, static::constructFileMode($this->fileMode));
|
||||||
|
} catch (ErrorException $ex) {
|
||||||
|
throw new FileDoesNotExistException($ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
|
||||||
|
if ($this->isLocked) {
|
||||||
|
flock($this->fileHandle, LOCK_EX | LOCK_NB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if (!is_resource($this->fileHandle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function constructFileMode(int $mode): string
|
||||||
|
{
|
||||||
|
$mode_read = ($mode & static::MODE_READ) > 0;
|
||||||
|
$mode_write = ($mode & static::MODE_WRITE) > 0;
|
||||||
|
$mode_truncate = ($mode & static::MODE_TRUNCATE_RAW) > 0;
|
||||||
|
$mode_append = ($mode & static::MODE_APPEND_RAW) > 0;
|
||||||
|
|
||||||
|
// why would you ever
|
||||||
|
if ($mode_append && $mode_truncate) {
|
||||||
|
throw new IOException("Can't append and truncate at the same time.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($mode_append || $mode_truncate) && !$mode_write) {
|
||||||
|
throw new IOException("Can't append or truncate without write privileges.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$mode_string = '';
|
||||||
|
|
||||||
|
if ($mode_append) {
|
||||||
|
$mode_string = 'a';
|
||||||
|
} elseif ($mode_truncate) {
|
||||||
|
$mode_string = 'w';
|
||||||
|
} elseif ($mode_write) {
|
||||||
|
$mode_string = 'c';
|
||||||
|
}
|
||||||
|
|
||||||
|
$mode_string .= 'b';
|
||||||
|
|
||||||
|
if ($mode_read) {
|
||||||
|
if (strlen($mode_string) < 2) {
|
||||||
|
$mode_string = 'r' . $mode_string;
|
||||||
|
} else {
|
||||||
|
$mode_string .= '+';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be at least two characters because of the b flag
|
||||||
|
if (strlen($mode_string) < 2) {
|
||||||
|
throw IOException('Failed to construct mode???');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $mode_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getResource(): resource
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
return $this->fileHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function ensureHandleActive(): void
|
||||||
|
{
|
||||||
|
if (!is_resource($this->fileHandle)) {
|
||||||
|
throw new IOException("No active file handle.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function ensureCanRead(): void
|
||||||
|
{
|
||||||
|
if (!$this->getCanRead()) {
|
||||||
|
throw new IOException('This stream cannot perform read operations.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function ensureCanWrite(): void
|
||||||
|
{
|
||||||
|
if (!$this->getCanWrite()) {
|
||||||
|
throw new IOException('This stream cannot perform write operations.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function ensureCanSeek(): void
|
||||||
|
{
|
||||||
|
if (!$this->getCanSeek()) {
|
||||||
|
throw new IOException('This stream cannot perform seek operations.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCanRead(): bool
|
||||||
|
{
|
||||||
|
return ($this->fileMode & static::MODE_READ) > 0 && is_readable($this->filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCanSeek(): bool
|
||||||
|
{
|
||||||
|
return ($this->fileMode & static::MODE_APPEND_RAW) == 0 && $this->getCanRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCanTimeout(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCanWrite(): bool
|
||||||
|
{
|
||||||
|
return ($this->fileMode & static::MODE_WRITE) > 0 && is_writable($this->filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLength(): int
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
return fstat($this->fileHandle)['size'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPosition(): int
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
return ftell($this->fileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getReadTimeout(): int
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getWriteTimeout(): int
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function flush(): void
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
fflush($this->fileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close(): void
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
|
||||||
|
if ($this->isLocked) {
|
||||||
|
flock($this->fileHandle, LOCK_UN | LOCK_NB);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($this->fileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read(int $length): string
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
$this->ensureCanRead();
|
||||||
|
|
||||||
|
$read = fread($this->fileHandle, $length);
|
||||||
|
|
||||||
|
if ($read === false) {
|
||||||
|
throw new IOException('Read failed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $read;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readChar(): int
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
return ord(fgetc($this->fileHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write(string $data): int
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
$this->ensureCanWrite();
|
||||||
|
|
||||||
|
$write = fwrite($this->fileHandle, $data);
|
||||||
|
|
||||||
|
if ($write === false) {
|
||||||
|
throw new IOException('Write failed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $write;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeChar(int $char): void
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
$this->write(chr($char), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function seek(int $offset, int $origin): void
|
||||||
|
{
|
||||||
|
$this->ensureHandleActive();
|
||||||
|
$this->ensureCanSeek();
|
||||||
|
|
||||||
|
switch ($origin) {
|
||||||
|
case Stream::ORIGIN_BEGIN:
|
||||||
|
$origin = SEEK_SET;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Stream::ORIGIN_END:
|
||||||
|
$origin = SEEK_END;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Stream::ORIGIN_CURRENT:
|
||||||
|
$origin = SEEK_CUR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IOException('Invalid seek origin.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek($this->fileHandle, $offset, $origin) !== 0) {
|
||||||
|
throw new IOException('Seek operation failed.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/IO/Stream.php
Normal file
40
src/IO/Stream.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\IO;
|
||||||
|
|
||||||
|
abstract class Stream
|
||||||
|
{
|
||||||
|
public const ORIGIN_CURRENT = 0;
|
||||||
|
public const ORIGIN_BEGIN = 1;
|
||||||
|
public const ORIGIN_END = 2;
|
||||||
|
|
||||||
|
public function __get(string $name)
|
||||||
|
{
|
||||||
|
$name = 'get' . ucfirst($name);
|
||||||
|
|
||||||
|
if (method_exists(static::class, $name)) {
|
||||||
|
return $this->{$name}();
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: specialised exception type
|
||||||
|
throw new IOException('Invalid property.');
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function getCanRead(): bool;
|
||||||
|
abstract protected function getCanSeek(): bool;
|
||||||
|
abstract protected function getCanTimeout(): bool;
|
||||||
|
abstract protected function getCanWrite(): bool;
|
||||||
|
abstract protected function getLength(): int;
|
||||||
|
abstract protected function getPosition(): int;
|
||||||
|
abstract protected function getReadTimeout(): int;
|
||||||
|
abstract protected function getWriteTimeout(): int;
|
||||||
|
|
||||||
|
abstract public function flush(): void;
|
||||||
|
abstract public function close(): void;
|
||||||
|
abstract public function seek(int $offset, int $origin): void;
|
||||||
|
|
||||||
|
abstract public function read(int $length): string;
|
||||||
|
abstract public function readChar(): int;
|
||||||
|
|
||||||
|
abstract public function write(string $data): int;
|
||||||
|
abstract public function writeChar(int $char): void;
|
||||||
|
}
|
|
@ -40,9 +40,9 @@ class Zalgo
|
||||||
public const ZALGO_MODE_MAX = 3;
|
public const ZALGO_MODE_MAX = 3;
|
||||||
|
|
||||||
private const ZALGO_MODES = [
|
private const ZALGO_MODES = [
|
||||||
ZALGO_MODE_MINI,
|
self::ZALGO_MODE_MINI,
|
||||||
ZALGO_MODE_NORMAL,
|
self::ZALGO_MODE_NORMAL,
|
||||||
ZALGO_MODE_MAX,
|
self::ZALGO_MODE_MAX,
|
||||||
];
|
];
|
||||||
|
|
||||||
public const ZALGO_DIR_UP = 0x1;
|
public const ZALGO_DIR_UP = 0x1;
|
||||||
|
@ -105,7 +105,7 @@ class Zalgo
|
||||||
}
|
}
|
||||||
|
|
||||||
$str .= $char;
|
$str .= $char;
|
||||||
|
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case self::ZALGO_MODE_MINI:
|
case self::ZALGO_MODE_MINI:
|
||||||
$num_up = mt_rand(0, 8);
|
$num_up = mt_rand(0, 8);
|
||||||
|
@ -129,9 +129,11 @@ class Zalgo
|
||||||
if ($going_up) {
|
if ($going_up) {
|
||||||
$str .= self::getZalgo(self::ZALGO_CHARS_UP, $num_up);
|
$str .= self::getZalgo(self::ZALGO_CHARS_UP, $num_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($going_mid) {
|
if ($going_mid) {
|
||||||
$str .= self::getZalgo(self::ZALGO_CHARS_MIDDLE, $num_mid);
|
$str .= self::getZalgo(self::ZALGO_CHARS_MIDDLE, $num_mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($going_down) {
|
if ($going_down) {
|
||||||
$str .= self::getZalgo(self::ZALGO_CHARS_DOWN, $num_down);
|
$str .= self::getZalgo(self::ZALGO_CHARS_DOWN, $num_down);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace MisuzuTests;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Misuzu\IO\Directory;
|
use Misuzu\IO\Directory;
|
||||||
use Misuzu\IO\File;
|
use Misuzu\IO\File;
|
||||||
|
use Misuzu\IO\FileStream;
|
||||||
|
|
||||||
define('WORKING_DIR', sys_get_temp_dir() . '/MisuzuFileSystemTest' . time());
|
define('WORKING_DIR', sys_get_temp_dir() . '/MisuzuFileSystemTest' . time());
|
||||||
|
|
||||||
|
@ -34,48 +35,48 @@ class FileSystemTest extends TestCase
|
||||||
|
|
||||||
public function testCreateFile()
|
public function testCreateFile()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::CREATE_READ_WRITE);
|
$file = File::open(WORKING_DIR . '/file');
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
$file->close();
|
$file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWriteFile()
|
public function testWriteFile()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_WRITE);
|
$file = new FileStream(WORKING_DIR . '/file', FileStream::MODE_TRUNCATE, false);
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
|
|
||||||
$file->write('misuzu');
|
$file->write('misuzu');
|
||||||
$this->assertEquals(6, $file->size);
|
$this->assertEquals(6, $file->length);
|
||||||
|
|
||||||
$file->close();
|
$file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAppendFile()
|
public function testAppendFile()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_WRITE);
|
$file = new FileStream(WORKING_DIR . '/file', FileStream::MODE_APPEND);
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
|
|
||||||
$file->append(' test');
|
$file->write(' test');
|
||||||
$this->assertEquals(11, $file->size);
|
$this->assertEquals(11, $file->length);
|
||||||
|
|
||||||
$file->close();
|
$file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPosition()
|
public function testPosition()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_READ);
|
$file = new FileStream(WORKING_DIR . '/file', FileStream::MODE_READ);
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
|
|
||||||
$file->start();
|
$file->seek(0, FileStream::ORIGIN_BEGIN);
|
||||||
$this->assertEquals(0, $file->position);
|
$this->assertEquals(0, $file->position);
|
||||||
|
|
||||||
$file->end();
|
$file->seek(0, FileStream::ORIGIN_END);
|
||||||
$this->assertEquals($file->size, $file->position);
|
$this->assertEquals($file->length, $file->position);
|
||||||
|
|
||||||
$file->position(4);
|
$file->seek(4, FileStream::ORIGIN_BEGIN);
|
||||||
$this->assertEquals(4, $file->position);
|
$this->assertEquals(4, $file->position);
|
||||||
|
|
||||||
$file->position(4, true);
|
$file->seek(4, FileStream::ORIGIN_CURRENT);
|
||||||
$this->assertEquals(8, $file->position);
|
$this->assertEquals(8, $file->position);
|
||||||
|
|
||||||
$file->close();
|
$file->close();
|
||||||
|
@ -83,34 +84,24 @@ class FileSystemTest extends TestCase
|
||||||
|
|
||||||
public function testRead()
|
public function testRead()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_READ);
|
$file = new FileStream(WORKING_DIR . '/file', FileStream::MODE_READ);
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
|
|
||||||
$this->assertEquals('misuzu test', $file->read());
|
$this->assertEquals('misuzu test', $file->read($file->length));
|
||||||
|
|
||||||
$file->position(7);
|
$file->seek(7, FileStream::ORIGIN_BEGIN);
|
||||||
$this->assertEquals('test', $file->read());
|
$this->assertEquals('test', $file->read(4));
|
||||||
|
|
||||||
$file->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFind()
|
|
||||||
{
|
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_READ);
|
|
||||||
$this->assertInstanceOf(File::class, $file);
|
|
||||||
|
|
||||||
$this->assertEquals(7, $file->find('test'));
|
|
||||||
|
|
||||||
$file->close();
|
$file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testChar()
|
public function testChar()
|
||||||
{
|
{
|
||||||
$file = new File(WORKING_DIR . '/file', File::OPEN_READ);
|
$file = new FileStream(WORKING_DIR . '/file', FileStream::MODE_READ);
|
||||||
$this->assertInstanceOf(File::class, $file);
|
$this->assertInstanceOf(FileStream::class, $file);
|
||||||
|
|
||||||
$file->position(3);
|
$file->seek(3, FileStream::ORIGIN_BEGIN);
|
||||||
$this->assertEquals('s', $file->char());
|
$this->assertEquals(ord('u'), $file->readChar());
|
||||||
|
|
||||||
$file->close();
|
$file->close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,19 @@ class ZalgoTest extends TestCase
|
||||||
|
|
||||||
public function testStrip()
|
public function testStrip()
|
||||||
{
|
{
|
||||||
$this->assertEquals(TEST_STRING, Zalgo::strip(Zalgo::run(TEST_STRING, Zalgo::ZALGO_MODE_MINI)));
|
$this->assertEquals(
|
||||||
$this->assertEquals(TEST_STRING, Zalgo::strip(Zalgo::run(TEST_STRING, Zalgo::ZALGO_MODE_NORMAL)));
|
static::TEST_STRING,
|
||||||
$this->assertEquals(TEST_STRING, Zalgo::strip(Zalgo::run(TEST_STRING, Zalgo::ZALGO_MODE_MAX)));
|
Zalgo::strip(Zalgo::run(static::TEST_STRING, Zalgo::ZALGO_MODE_MINI))
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
static::TEST_STRING,
|
||||||
|
Zalgo::strip(Zalgo::run(static::TEST_STRING, Zalgo::ZALGO_MODE_NORMAL))
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
static::TEST_STRING,
|
||||||
|
Zalgo::strip(Zalgo::run(static::TEST_STRING, Zalgo::ZALGO_MODE_MAX))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue