Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replaceable encoder for converters #109

Merged
merged 1 commit into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/DataConverter/Encoder/EncoderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php declare(strict_types=1);

namespace XBase\DataConverter\Encoder;

interface EncoderInterface
{
public function encode(string $string, string $fromEncoding, string $toEncoding): string;
}
11 changes: 11 additions & 0 deletions src/DataConverter/Encoder/IconvEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types=1);

namespace XBase\DataConverter\Encoder;

class IconvEncoder implements EncoderInterface
{
public function encode(string $string, string $fromEncoding, string $toEncoding): string
{
return iconv($fromEncoding, $toEncoding, $string);
}
}
7 changes: 6 additions & 1 deletion src/DataConverter/Field/AbstractFieldDataConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace XBase\DataConverter\Field;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\Header\Column;
use XBase\Table\Table;

Expand All @@ -13,9 +14,13 @@ abstract class AbstractFieldDataConverter implements FieldDataConverterInterface
/** @var Column */
protected $column;

public function __construct(Table $table, Column $column)
/** @var EncoderInterface */
protected $encoder;

public function __construct(Table $table, Column $column, EncoderInterface $encoder)
{
$this->table = $table;
$this->column = $column;
$this->encoder = $encoder;
}
}
4 changes: 2 additions & 2 deletions src/DataConverter/Field/DBase/CharConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static function getType(): string
public function fromBinaryString(string $value)
{
if ($inCharset = $this->table->options['encoding']) {
$value = iconv($inCharset, 'utf-8', $value);
$value = $this->encoder->encode($value, $inCharset, 'utf-8');
}

return trim($value);
Expand All @@ -24,7 +24,7 @@ public function fromBinaryString(string $value)
public function toBinaryString($value): string
{
if ($value && $outCharset = $this->table->options['encoding']) {
$value = iconv('utf-8', $outCharset, $value);
$value = $this->encoder->encode($value, 'utf-8', $outCharset);
}

return str_pad($value ?? '', $this->column->length);
Expand Down
4 changes: 2 additions & 2 deletions src/DataConverter/Field/VisualFoxpro/VarFieldConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function fromBinaryString(string $value): string
}

if ($inCharset = $this->table->options['encoding']) {
$value = iconv($inCharset, 'utf-8', $value);
$value = $this->encoder->encode($value, $inCharset, 'utf-8');
}

return $value;
Expand All @@ -32,7 +32,7 @@ public function toBinaryString($value): string
{
$value = $value ?? '';
if ($outCharset = $this->table->options['encoding']) {
$value = iconv('utf-8', $outCharset, $value);
$value = $this->encoder->encode($value, 'utf-8', $outCharset);
}

return str_pad($value, $this->column->length - 1, chr(0x00)).chr(0x03);
Expand Down
9 changes: 7 additions & 2 deletions src/DataConverter/Record/DBaseDataConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace XBase\DataConverter\Record;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\DataConverter\Field\DBase\CharConverter;
use XBase\DataConverter\Field\DBase\DateConverter;
use XBase\DataConverter\Field\DBase\IgnoreConverter;
Expand All @@ -20,9 +21,13 @@ class DBaseDataConverter implements RecordDataConverterInterface
/** @var Table */
protected $table;

public function __construct(Table $table)
/** @var EncoderInterface */
protected $encoder;

public function __construct(Table $table, EncoderInterface $encoder)
{
$this->table = $table;
$this->encoder = $encoder;
}

/**
Expand Down Expand Up @@ -80,7 +85,7 @@ private function findFieldConverter(Column $column): FieldDataConverterInterface
{
foreach (static::getFieldConverters() as $class) {
if ($column->type === $class::getType()) {
return new $class($this->table, $column);
return new $class($this->table, $column, $this->encoder);
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/Memo/AbstractMemo.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace XBase\Memo;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\Stream\Stream;
use XBase\Table\Table;

Expand All @@ -16,12 +17,16 @@ abstract class AbstractMemo implements MemoInterface
/** @var string */
protected $filepath;

/** @var EncoderInterface */
protected $encoder;

/**
* @param string $filepath Path to memo file
*/
public function __construct(Table $table, string $filepath)
public function __construct(Table $table, string $filepath, EncoderInterface $encoder)
{
$this->table = $table;
$this->encoder = $encoder;

$this->filepath = $filepath;
$this->open();
Expand Down
2 changes: 1 addition & 1 deletion src/Memo/DBase3Memo.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function get(int $pointer): ?MemoObject
$result = substr($result, 0, -1); // remove endline symbol (0x00)
}
if ($this->table->options['encoding']) {
$result = iconv($this->table->options['encoding'], 'utf-8', $result);
$result = $this->encoder->encode($result, $this->table->options['encoding'], 'utf-8');
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Memo/DBase4Memo.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function get(int $pointer): ?MemoObject
$info = $this->guessDataType($result);
assert(isset($info['type']));
if (MemoObject::TYPE_TEXT === $info['type'] && $this->table->options['encoding']) {
$result = iconv($this->table->options['encoding'], 'utf-8', $result);
$result = $this->encoder->encode($result, $this->table->options['encoding'], 'utf-8');
}

return new MemoObject($result, $info['type'], $pointer, $memoLength[1]);
Expand Down
2 changes: 1 addition & 1 deletion src/Memo/FoxproMemo.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function get(int $pointer): ?MemoObject
$info = $this->guessDataType($result);
assert(isset($info['type']));
if ($this->table->options['encoding']) {
$result = iconv($this->table->options['encoding'], 'utf-8', $result);
$result = $this->encoder->encode($result, $this->table->options['encoding'], 'utf-8');
}

return new MemoObject($result, $info['type'], $pointer, $memoLength[1], $info);
Expand Down
5 changes: 3 additions & 2 deletions src/Memo/MemoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

namespace XBase\Memo;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\Enum\TableType;
use XBase\Table\Table;

class MemoFactory
{
public static function create(Table $table): ?MemoInterface
public static function create(Table $table, EncoderInterface $encoder): ?MemoInterface
{
$class = self::getClass($table->getVersion());
$refClass = new \ReflectionClass($class);
Expand All @@ -26,7 +27,7 @@ public static function create(Table $table): ?MemoInterface
return null; //todo create file?
}

return $refClass->newInstance($table, $memoFilepath);
return $refClass->newInstance($table, $memoFilepath, $encoder);
}

private static function getClass(int $version): string
Expand Down
23 changes: 14 additions & 9 deletions src/Record/RecordFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace XBase\Record;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\DataConverter\Record\DBase4DataConverter;
use XBase\DataConverter\Record\DBase7DataConverter;
use XBase\DataConverter\Record\DBaseDataConverter;
Expand All @@ -13,8 +14,12 @@

class RecordFactory
{
public static function create(Table $table, int $recordIndex, ?string $rawData = null): ?RecordInterface
{
public static function create(
Table $table,
EncoderInterface $encoder,
int $recordIndex,
?string $rawData = null
): ?RecordInterface {
$class = self::getClass($table->getVersion());
$refClass = new \ReflectionClass($class);
if (!$refClass->implementsInterface(RecordInterface::class)) {
Expand All @@ -24,7 +29,7 @@ public static function create(Table $table, int $recordIndex, ?string $rawData =
return $refClass->newInstance(
$table,
$recordIndex,
self::createDataConverter($table)->fromBinaryString($rawData ?? '')
self::createDataConverter($table, $encoder)->fromBinaryString($rawData ?? '')
);
}

Expand Down Expand Up @@ -56,28 +61,28 @@ public static function getClass(int $version): string
/**
* @return RecordDataConverterInterface
*/
public static function createDataConverter(Table $table): RecordDataConverterInterface
public static function createDataConverter(Table $table, EncoderInterface $encoder): RecordDataConverterInterface
{
switch ($table->getVersion()) {
case TableType::DBASE_IV_MEMO:
return new DBase4DataConverter($table);
return new DBase4DataConverter($table, $encoder);

case TableType::DBASE_7_NOMEMO:
case TableType::DBASE_7_MEMO:
return new DBase7DataConverter($table);
return new DBase7DataConverter($table, $encoder);

case TableType::FOXPRO_MEMO:
return new FoxproDataConverter($table);
return new FoxproDataConverter($table, $encoder);

case TableType::VISUAL_FOXPRO:
case TableType::VISUAL_FOXPRO_AI:
case TableType::VISUAL_FOXPRO_VAR:
return new VisualFoxproDataConverter($table);
return new VisualFoxproDataConverter($table, $encoder);

case TableType::DBASE_III_PLUS_MEMO:
case TableType::DBASE_III_PLUS_NOMEMO:
default:
return new DBaseDataConverter($table);
return new DBaseDataConverter($table, $encoder);
}
}
}
10 changes: 8 additions & 2 deletions src/TableCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace XBase;

use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\DataConverter\Encoder\IconvEncoder;
use XBase\Enum\TableType;
use XBase\Exception\ColumnException;
use XBase\Exception\XBaseException;
Expand All @@ -20,7 +22,10 @@ class TableCreator
{
use TableAwareTrait;

public function __construct(string $filepath, Header $header)
/** @var EncoderInterface */
protected $encoder;

public function __construct(string $filepath, Header $header, EncoderInterface $encoder = null)
{
$this->checkFilepath($filepath);
$this->checkHeader($header);
Expand All @@ -29,6 +34,7 @@ public function __construct(string $filepath, Header $header)
$this->table->filepath = $filepath;
$this->table->header = $header;
$this->table->options['create'] = true;
$this->encoder = $encoder ?? new IconvEncoder();
}

private function checkFilepath(string $filepath): void
Expand Down Expand Up @@ -70,7 +76,7 @@ public function save(): self

if (TableType::hasMemo($version = $this->getHeader()->version)) {
MemoCreatorFactory::create($this->table)->createFile();
$this->table->memo = MemoFactory::create($this->table);
$this->table->memo = MemoFactory::create($this->table, $this->encoder);
}

$this->table->stream->close();
Expand Down
5 changes: 3 additions & 2 deletions src/TableEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function close(): void
public function appendRecord(): RecordInterface
{
$this->recordPos = $this->getHeader()->recordCount;
$this->record = RecordFactory::create($this->table, $this->recordPos);
$this->record = RecordFactory::create($this->table, $this->encoder, $this->recordPos);
$this->insertion = true;

return $this->record;
Expand All @@ -107,7 +107,8 @@ public function writeRecord(RecordInterface $record = null): self

$offset = $this->getHeader()->length + ($record->getRecordIndex() * $this->getHeader()->recordByteLength);
$this->getStream()->seek($offset);
$this->getStream()->write(RecordFactory::createDataConverter($this->table)->toBinaryString($record));
$this->getStream()->write(RecordFactory::createDataConverter($this->table, $this->encoder)
->toBinaryString($record));

if ($this->insertion) {
$this->table->header->recordCount++;
Expand Down
24 changes: 19 additions & 5 deletions src/TableReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use XBase\Column\ColumnInterface;
use XBase\Column\XBaseColumn;
use XBase\DataConverter\Encoder\EncoderInterface;
use XBase\DataConverter\Encoder\IconvEncoder;
use XBase\Enum\Codepage;
use XBase\Enum\TableType;
use XBase\Exception\TableException;
Expand Down Expand Up @@ -36,6 +38,9 @@ class TableReader
/** @var RecordInterface|null */
protected $record;

/** @var EncoderInterface */
protected $encoder;

/**
* @var Table
*/
Expand All @@ -47,6 +52,7 @@ class TableReader
* @param array $options Array of options:<br>
* encoding - convert text data from<br>
* columns - available columns<br>
* encoder - encoder class name, default: IconvEncoder::class<br>
*
* @throws \Exception
*/
Expand All @@ -55,6 +61,9 @@ public function __construct(string $filepath, array $options = [])
$this->table = new Table();
$this->table->filepath = $filepath;

$this->encoder = isset($options['encoder']) && $options['encoder'] instanceof EncoderInterface ?
$options['encoder'] :
new IconvEncoder();
$this->table->options = $this->resolveOptions($options);

$this->open();
Expand Down Expand Up @@ -96,7 +105,7 @@ protected function readHeader(): void
protected function openMemo(): void
{
if (TableType::hasMemo($this->getVersion())) {
$this->table->memo = MemoFactory::create($this->table);
$this->table->memo = MemoFactory::create($this->table, $this->encoder);
}
}

Expand Down Expand Up @@ -137,7 +146,7 @@ public function nextRecord(): ?RecordInterface
}

$this->recordPos++;
$this->record = RecordFactory::create($this->table, $this->recordPos, $this->getStream()
$this->record = RecordFactory::create($this->table, $this->encoder, $this->recordPos, $this->getStream()
->read($this->getHeader()->recordByteLength));

if ($this->record->isDeleted()) {
Expand Down Expand Up @@ -167,7 +176,7 @@ public function pickRecord(int $position): ?RecordInterface
throw new TableException("Failed to pick row at position {$position}");
}

$record = RecordFactory::create($this->table, $position, $this->getStream()
$record = RecordFactory::create($this->table, $this->encoder, $position, $this->getStream()
->read($this->getHeader()->recordByteLength));
// revert pointer
$this->getStream()->seek($curPos);
Expand Down Expand Up @@ -197,7 +206,12 @@ public function previousRecord(): ?RecordInterface

$this->getStream()->seek($this->getHeader()->length + ($this->recordPos * $this->getHeader()->recordByteLength));

$this->record = RecordFactory::create($this->table, $this->recordPos, $this->getStream()->read($this->getRecordByteLength()));
$this->record = RecordFactory::create(
$this->table,
$this->encoder,
$this->recordPos,
$this->getStream()->read($this->getRecordByteLength())
);

if ($this->record->isDeleted()) {
$this->deleteCount++;
Expand All @@ -219,7 +233,7 @@ public function moveTo(int $index): ?RecordInterface

$this->getStream()->seek($this->getHeader()->length + ($index * $this->getHeader()->recordByteLength));

$this->record = RecordFactory::create($this->table, $this->recordPos, $this->getStream()
$this->record = RecordFactory::create($this->table, $this->encoder, $this->recordPos, $this->getStream()
->read($this->getHeader()->recordByteLength));

return $this->record;
Expand Down
Loading