Renamed SharpConfig to FileConfig.

This commit is contained in:
flash 2024-06-03 22:04:36 +00:00
parent a04cc1b63d
commit e40e393b0c
4 changed files with 160 additions and 142 deletions

136
src/FileConfig.php Normal file
View file

@ -0,0 +1,136 @@
<?php
// FileConfig.php
// Created: 2023-10-20
// Updated: 2024-06-03
namespace Syokuhou;
use InvalidArgumentException;
use Index\IO\FileStream;
use Index\IO\Stream;
/**
* Provides a configuration in Sharp Chat format.
*/
class FileConfig implements IConfig {
use ImmutableConfigTrait, GetValueInfoTrait, GetValuesTrait;
/**
* @param array<string, FileConfigValueInfo> $values
*/
public function __construct(private array $values) {}
public function getSeparator(): string {
return ':';
}
public function scopeTo(string ...$prefix): IConfig {
return new ScopedConfig($this, $prefix);
}
public function hasValues(string|array $names): bool {
if(is_string($names))
return array_key_exists($names, $this->values);
foreach($names as $name)
if(!array_key_exists($name, $this->values))
return false;
return true;
}
public function getAllValueInfos(int $range = 0, int $offset = 0): array {
if($range === 0)
return array_values($this->values);
if($range < 0)
throw new InvalidArgumentException('$range must be a positive integer.');
if($offset < 0)
throw new InvalidArgumentException('$offset must be greater than zero if a range is specified.');
return array_slice($this->values, $offset, $range);
}
public function getValueInfos(string|array $names): array {
if(is_string($names))
return array_key_exists($names, $this->values) ? [$this->values[$names]] : [];
$infos = [];
foreach($names as $name)
if(array_key_exists($name, $this->values))
$infos[] = $this->values[$name];
return $infos;
}
/**
* Creates an instance of FileConfig from an array of lines.
*
* @param string[] $lines Config lines.
* @return FileConfig
*/
public static function fromLines(array $lines): self {
$values = [];
foreach($lines as $line) {
$line = trim($line);
if($line === '' || $line[0] === '#' || $line[0] === ';')
continue;
$info = new FileConfigValueInfo(...explode(' ', $line, 2));
$values[$info->getName()] = $info;
}
return new FileConfig($values);
}
/**
* Creates an instance of FileConfig from a string.
*
* @param string $lines Config lines.
* @param non-empty-string $newLine Line separator character.
* @return FileConfig
*/
public static function fromString(string $lines, string $newLine = "\n"): self {
return self::fromLines(explode($newLine, $lines));
}
/**
* Creates an instance of FileConfig from a file.
*
* @param string $path Config file path.
* @throws InvalidArgumentException If $path does not exist.
* @return FileConfig
*/
public static function fromFile(string $path): self {
if(!is_file($path))
throw new InvalidArgumentException('$path does not exist.');
return self::fromStream(FileStream::openRead($path));
}
/**
* Creates an instance of FileConfig from a readable stream.
*
* @param Stream $stream Config file stream.
* @throws InvalidArgumentException If $stream is not readable.
* @return FileConfig
*/
public static function fromStream(Stream $stream): self {
if(!$stream->canRead())
throw new InvalidArgumentException('$stream must be readable.');
$values = [];
while(($line = $stream->readLine()) !== null) {
$line = trim($line);
if($line === '' || $line[0] === '#' || $line[0] === ';')
continue;
$info = new FileConfigValueInfo(...explode(' ', $line, 2));
$values[$info->getName()] = $info;
}
return new FileConfig($values);
}
}

View file

@ -1,11 +1,11 @@
<?php <?php
// SharpConfigValueInfo.php // FileConfigValueInfo.php
// Created: 2023-10-20 // Created: 2023-10-20
// Updated: 2023-10-20 // Updated: 2024-06-03
namespace Syokuhou; namespace Syokuhou;
class SharpConfigValueInfo implements IConfigValueInfo { class FileConfigValueInfo implements IConfigValueInfo {
private string $name; private string $name;
private string $value; private string $value;

View file

@ -1,136 +1,11 @@
<?php <?php
// SharpConfig.php // SharpConfig.php
// Created: 2023-10-20 // Created: 2024-06-03
// Updated: 2023-10-20 // Updated: 2024-06-03
namespace Syokuhou; namespace Syokuhou;
use InvalidArgumentException;
use Index\IO\FileStream;
use Index\IO\Stream;
/** /**
* Provides a configuration in SharpChat format. * Provides an alias for FileConfig.
*/ */
class SharpConfig implements IConfig { class SharpConfig extends FileConfig {}
use ImmutableConfigTrait, GetValueInfoTrait, GetValuesTrait;
/**
* @param array<string, SharpConfigValueInfo> $values
*/
public function __construct(private array $values) {}
public function getSeparator(): string {
return ':';
}
public function scopeTo(string ...$prefix): IConfig {
return new ScopedConfig($this, $prefix);
}
public function hasValues(string|array $names): bool {
if(is_string($names))
return array_key_exists($names, $this->values);
foreach($names as $name)
if(!array_key_exists($name, $this->values))
return false;
return true;
}
public function getAllValueInfos(int $range = 0, int $offset = 0): array {
if($range === 0)
return array_values($this->values);
if($range < 0)
throw new InvalidArgumentException('$range must be a positive integer.');
if($offset < 0)
throw new InvalidArgumentException('$offset must be greater than zero if a range is specified.');
return array_slice($this->values, $offset, $range);
}
public function getValueInfos(string|array $names): array {
if(is_string($names))
return array_key_exists($names, $this->values) ? [$this->values[$names]] : [];
$infos = [];
foreach($names as $name)
if(array_key_exists($name, $this->values))
$infos[] = $this->values[$name];
return $infos;
}
/**
* Creates an instance of SharpConfig from an array of lines.
*
* @param string[] $lines Config lines.
* @return SharpConfig
*/
public static function fromLines(array $lines): self {
$values = [];
foreach($lines as $line) {
$line = trim($line);
if($line === '' || $line[0] === '#' || $line[0] === ';')
continue;
$info = new SharpConfigValueInfo(...explode(' ', $line, 2));
$values[$info->getName()] = $info;
}
return new SharpConfig($values);
}
/**
* Creates an instance of SharpConfig from a string.
*
* @param string $lines Config lines.
* @param non-empty-string $newLine Line separator character.
* @return SharpConfig
*/
public static function fromString(string $lines, string $newLine = "\n"): self {
return self::fromLines(explode($newLine, $lines));
}
/**
* Creates an instance of SharpConfig from a file.
*
* @param string $path Config file path.
* @throws InvalidArgumentException If $path does not exist.
* @return SharpConfig
*/
public static function fromFile(string $path): self {
if(!is_file($path))
throw new InvalidArgumentException('$path does not exist.');
return self::fromStream(FileStream::openRead($path));
}
/**
* Creates an instance of SharpConfig from a readable stream.
*
* @param Stream $stream Config file stream.
* @throws InvalidArgumentException If $stream is not readable.
* @return SharpConfig
*/
public static function fromStream(Stream $stream): self {
if(!$stream->canRead())
throw new InvalidArgumentException('$stream must be readable.');
$values = [];
while(($line = $stream->readLine()) !== null) {
$line = trim($line);
if($line === '' || $line[0] === '#' || $line[0] === ';')
continue;
$info = new SharpConfigValueInfo(...explode(' ', $line, 2));
$values[$info->getName()] = $info;
}
return new SharpConfig($values);
}
}

View file

@ -1,53 +1,60 @@
<?php <?php
// SharpConfigTest.php // FileConfigTest.php
// Created: 2023-10-20 // Created: 2023-10-20
// Updated: 2023-10-20 // Updated: 2024-06-03
declare(strict_types=1); declare(strict_types=1);
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
/** /**
* @covers \Syokuhou\SharpConfig * @covers \Syokuhou\FileConfig
* @covers \Syokuhou\SharpConfigValueInfo * @covers \Syokuhou\FileConfigValueInfo
* @covers \Syokuhou\ImmutableConfigTrait * @covers \Syokuhou\ImmutableConfigTrait
* @covers \Syokuhou\GetValueInfoTrait * @covers \Syokuhou\GetValueInfoTrait
* @covers \Syokuhou\GetValuesTrait * @covers \Syokuhou\GetValuesTrait
* @covers \Syokuhou\SharpConfig
*/ */
final class SharpConfigTest extends TestCase { final class FileConfigTest extends TestCase {
public function testImmutableRemove(): void { public function testImmutableRemove(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test value')->removeValues('test');
\Syokuhou\SharpConfig::fromString('test value')->removeValues('test'); \Syokuhou\SharpConfig::fromString('test value')->removeValues('test');
} }
public function testImmutableSetString(): void { public function testImmutableSetString(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test value')->setString('test', 'the');
\Syokuhou\SharpConfig::fromString('test value')->setString('test', 'the'); \Syokuhou\SharpConfig::fromString('test value')->setString('test', 'the');
} }
public function testImmutableSetInteger(): void { public function testImmutableSetInteger(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test 1234')->setInteger('test', 5678);
\Syokuhou\SharpConfig::fromString('test 1234')->setInteger('test', 5678); \Syokuhou\SharpConfig::fromString('test 1234')->setInteger('test', 5678);
} }
public function testImmutableSetFloat(): void { public function testImmutableSetFloat(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test 56.78')->setFloat('test', 12.34);
\Syokuhou\SharpConfig::fromString('test 56.78')->setFloat('test', 12.34); \Syokuhou\SharpConfig::fromString('test 56.78')->setFloat('test', 12.34);
} }
public function testImmutableSetBoolean(): void { public function testImmutableSetBoolean(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test true')->setBoolean('test', false);
\Syokuhou\SharpConfig::fromString('test true')->setBoolean('test', false); \Syokuhou\SharpConfig::fromString('test true')->setBoolean('test', false);
} }
public function testImmutableSetArray(): void { public function testImmutableSetArray(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\FileConfig::fromString('test words words words')->setArray('test', ['meow', 'meow', 'meow']);
\Syokuhou\SharpConfig::fromString('test words words words')->setArray('test', ['meow', 'meow', 'meow']); \Syokuhou\SharpConfig::fromString('test words words words')->setArray('test', ['meow', 'meow', 'meow']);
} }
public function testImmutableSetValues(): void { public function testImmutableSetValues(): void {
$this->expectException(\RuntimeException::class); $this->expectException(\RuntimeException::class);
\Syokuhou\SharpConfig::fromString('')->setValues([ \Syokuhou\FileConfig::fromString('')->setValues([
'stringval' => 'the', 'stringval' => 'the',
'intval' => 1234, 'intval' => 1234,
'floatval' => 56.78, 'floatval' => 56.78,
@ -57,7 +64,7 @@ final class SharpConfigTest extends TestCase {
} }
public function testScoping(): void { public function testScoping(): void {
$config = \Syokuhou\SharpConfig::fromLines([ $config = \Syokuhou\FileConfig::fromLines([
'test Inaccessible', 'test Inaccessible',
'scoped:test Accessible', 'scoped:test Accessible',
]); ]);
@ -70,7 +77,7 @@ final class SharpConfigTest extends TestCase {
} }
public function testHasValues(): void { public function testHasValues(): void {
$config = \Syokuhou\SharpConfig::fromLines([ $config = \Syokuhou\FileConfig::fromLines([
'test 123', 'test 123',
'scoped:test true', 'scoped:test true',
'scoped:meow meow', 'scoped:meow meow',
@ -85,7 +92,7 @@ final class SharpConfigTest extends TestCase {
} }
public function testGetAllValueInfos(): void { public function testGetAllValueInfos(): void {
$config = \Syokuhou\SharpConfig::fromFile(__DIR__ . '/sharpchat.cfg'); $config = \Syokuhou\FileConfig::fromFile(__DIR__ . '/sharpchat.cfg');
$all = $config->getAllValueInfos(); $all = $config->getAllValueInfos();
$expected = [ $expected = [
@ -131,7 +138,7 @@ final class SharpConfigTest extends TestCase {
} }
public function testGetValues(): void { public function testGetValues(): void {
$config = \Syokuhou\SharpConfig::fromFile(__DIR__ . '/sharpchat.cfg'); $config = \Syokuhou\FileConfig::fromFile(__DIR__ . '/sharpchat.cfg');
$this->assertNull($config->getValueInfo('doesnotexist')); $this->assertNull($config->getValueInfo('doesnotexist'));