Skip to content

Commit

Permalink
Merge pull request #109 from atmtk/feature/implicit-encoders
Browse files Browse the repository at this point in the history
replaceable encoder for converters
  • Loading branch information
gam6itko authored Oct 20, 2021
2 parents 9d080ea + ba22d84 commit 9247c04
Show file tree
Hide file tree
Showing 25 changed files with 113 additions and 42 deletions.
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

0 comments on commit 9247c04

Please sign in to comment.