Skip to content

Commit 06e8722

Browse files
committed
feature: add getData for mobi
#2
1 parent 856bcf9 commit 06e8722

File tree

8 files changed

+608
-243
lines changed

8 files changed

+608
-243
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"require-dev": {
2020
"phpunit/phpunit": "^11.5.15",
21-
"friendsofphp/php-cs-fixer": "^3.73.1",
21+
"friendsofphp/php-cs-fixer": "^3.75",
2222
"phpstan/phpstan": "^2.1"
2323
},
2424
"autoload": {

src/Data/MobiData.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EbookReader\Data;
6+
7+
use EbookReader\EbookDataInterface;
8+
use EbookReader\Resource\Style;
9+
10+
final readonly class MobiData implements EbookDataInterface
11+
{
12+
/**
13+
* @param Style[] $styles
14+
*/
15+
public function __construct(
16+
private string $text,
17+
private ?string $title,
18+
private array $styles = [],
19+
) {
20+
}
21+
22+
public function getText(): string
23+
{
24+
return $this->text;
25+
}
26+
27+
public function getTitle(): ?string
28+
{
29+
return $this->title;
30+
}
31+
32+
/**
33+
* @return Style[]
34+
*/
35+
public function getStyles(): array
36+
{
37+
return $this->styles;
38+
}
39+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EbookReader\Decompressor;
6+
7+
interface DecompressorInterface
8+
{
9+
public function decompress(string $data): string;
10+
}

src/Decompressor/PalmDocLz77.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EbookReader\Decompressor;
6+
7+
final class PalmDocLz77 implements DecompressorInterface
8+
{
9+
/**
10+
* @var int[]
11+
*/
12+
private array $data;
13+
private int $offset = 0;
14+
/**
15+
* @var int[]
16+
*/
17+
private array $buffer;
18+
19+
public function decompress(string $data): string
20+
{
21+
$this->data = \array_values(\unpack('C*', $data));
22+
$this->offset = 0;
23+
$this->buffer = [];
24+
25+
$length = \count($this->data);
26+
while ($this->offset < $length) {
27+
$char = $this->readByte();
28+
29+
if (0 === $char) {
30+
$this->buffer[] = $char;
31+
} elseif ($char <= 8) {
32+
$this->writeLiteral($char);
33+
} elseif ($char <= 0x7F) {
34+
$this->buffer[] = $char;
35+
} elseif ($char <= 0xBF) {
36+
$this->writeBackReference($char);
37+
} else {
38+
$this->writeSpecial($char);
39+
}
40+
}
41+
42+
return \pack('C*', ...$this->buffer);
43+
}
44+
45+
private function readByte(): int
46+
{
47+
return $this->data[$this->offset++];
48+
}
49+
50+
private function writeLiteral(int $count): void
51+
{
52+
for ($i = 0; $i < $count; ++$i) {
53+
$this->buffer[] = $this->readByte();
54+
}
55+
}
56+
57+
private function writeBackReference(int $char): void
58+
{
59+
$next = $this->readByte();
60+
$distance = (($char << 8 | $next) >> 3) & 0x7FF;
61+
$lzLength = ($next & 0x7) + 3;
62+
63+
$bufferSize = \count($this->buffer);
64+
for ($i = 0; $i < $lzLength; ++$i) {
65+
$this->buffer[] = $this->buffer[$bufferSize - $distance + $i];
66+
}
67+
}
68+
69+
private function writeSpecial(int $char): void
70+
{
71+
$this->buffer[] = 32;
72+
$this->buffer[] = $char ^ 0x80;
73+
}
74+
}

0 commit comments

Comments
 (0)