Skip to content

Commit 63bf958

Browse files
committed
Add support for DBase 7 Double type
1 parent 3062e8f commit 63bf958

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace XBase\DataConverter\Field\DBase7;
4+
5+
use XBase\DataConverter\Field\AbstractFieldDataConverter;
6+
use XBase\Enum\FieldType;
7+
8+
class DoubleConverter extends AbstractFieldDataConverter
9+
{
10+
public static function getType(): string
11+
{
12+
return FieldType::DBASE7_DOUBLE;
13+
}
14+
15+
public function fromBinaryString(string $value): float
16+
{
17+
$buf = unpack('C*', $value);
18+
$buf = array_map(function ($v) {
19+
return str_pad(decbin($v), 8, '0', STR_PAD_LEFT);
20+
}, $buf);
21+
22+
$negative = '0' === $buf[1][0];
23+
if ($negative) {
24+
$buf = array_map(function ($v) {
25+
return $this->inverseBits($v);
26+
}, $buf);
27+
}
28+
29+
$result = unpack('E', pack('C*', ...array_map('bindec', $buf)));
30+
if ($result) {
31+
$result = (float) abs($result[1]);
32+
if ($negative) {
33+
$result = -($result);
34+
}
35+
36+
return $result;
37+
}
38+
39+
return 0.0;
40+
}
41+
42+
/**
43+
* @param float|null $value
44+
*/
45+
public function toBinaryString($value): string
46+
{
47+
if (null === $value) {
48+
return str_pad('', $this->column->getLength(), chr(0x00));
49+
}
50+
51+
return pack('E', $value);
52+
}
53+
54+
private function inverseBits(string $bin): string
55+
{
56+
$len = strlen($bin);
57+
$result = '';
58+
for ($i = 0; $i < $len; $i++) {
59+
$result .= '0' === $bin[$i] ? '1' : '0';
60+
}
61+
62+
return $result;
63+
}
64+
}

src/XBase/DataConverter/Record/DBase7DataConverter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace XBase\DataConverter\Record;
44

55
use XBase\DataConverter\Field\DBase7\AiConverter;
6+
use XBase\DataConverter\Field\DBase7\DoubleConverter;
67
use XBase\DataConverter\Field\DBase7\IntegerConverter;
78
use XBase\DataConverter\Field\DBase7\MemoConverter;
89
use XBase\DataConverter\Field\DBase7\TimestampConverter;
@@ -13,6 +14,7 @@ protected static function getFiledConverters(): array
1314
{
1415
return array_merge([
1516
AiConverter::class,
17+
DoubleConverter::class,
1618
IntegerConverter::class,
1719
TimestampConverter::class,
1820
MemoConverter::class,

src/XBase/Enum/FieldType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ final class FieldType
3636
const AUTO_INCREMENT = '+';
3737

3838
const DBASE4_BLOB = 'B';
39+
const DBASE7_DOUBLE = 'O';
3940

4041
public static function has($type): bool
4142
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace XBase\Tests\Record\DataConverter\Field\DBase7;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use XBase\Column\ColumnInterface;
7+
use XBase\DataConverter\Field\DBase7\DoubleConverter;
8+
use XBase\Table;
9+
10+
class DoubleConverterTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider dataProvider
14+
*/
15+
public function test(string $binaryString, float $float): void
16+
{
17+
$table = $this->createMock(Table::class);
18+
$column = $this->createMock(ColumnInterface::class);
19+
$converter = new DoubleConverter($table, $column);
20+
self::assertSame($float, $converter->fromBinaryString($binaryString));
21+
self::assertEquals($float, unpack('E', $converter->toBinaryString($float))[1]);
22+
}
23+
24+
public function dataProvider()
25+
{
26+
yield [
27+
base64_decode('P5cDMzMzMzI='),
28+
-199.9,
29+
];
30+
31+
yield [
32+
base64_decode('P61f//////8='),
33+
-74.5,
34+
];
35+
36+
yield [
37+
base64_decode('gAAAAAAAAAA='),
38+
0.0,
39+
];
40+
41+
yield [
42+
base64_decode('wCIAAAAAAAA='),
43+
9.0
44+
];
45+
46+
yield [
47+
base64_decode('wFOMzMzMzM0='),
48+
78.2,
49+
];
50+
}
51+
}

0 commit comments

Comments
 (0)