Passed
Push — master ( bdfaf8...931c46 )
by smiley
01:33
created

LTEXReader::readData()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 2
nop 0
dl 0
loc 26
rs 9.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class LTEXReader
4
 *
5
 * @link https://arctium.io/wiki/index.php?title=Locale_Lookup_Index_(.bin)
6
 *
7
 * @filesource   LTEXReader.php
8
 * @created      05.01.2019
9
 * @package      codemasher\WildstarDB
10
 * @author       smiley <[email protected]>
11
 * @copyright    2019 smiley
12
 * @license      MIT
13
 */
14
15
namespace codemasher\WildstarDB;
16
17
/**
18
 * @property string $prettyname
19
 */
20
class LTEXReader extends ReaderAbstract{
21
22
	// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c
23
	protected const LCID = [
24
		0x0407 => 'de-DE', // 1031
25
		0x0409 => 'en-US', // 1033
26
		0x040C => 'fr-FR', // 1036
27
		0x0412 => 'ko-KR', // 1042
28
	];
29
30
	protected $FORMAT_HEADER = 'a4Signature/LVersion/LLanguage/LLCID/QTagNameStringLength/QTagNameStringPtr/QShortNameStringLength/QShortNameStringPtr/QLongNameStringLength/QLongNameStringPtr/QEntryCount/QEntryIndexPtr/QNameStoreLength/QNameStorePtr';
31
32
	/**
33
	 * @var string
34
	 */
35
	protected $prettyname;
36
37
	/**
38
	 * @param string $filename
39
	 *
40
	 * @return \codemasher\WildstarDB\ReaderInterface
41
	 * @throws \codemasher\WildstarDB\WSDBException
42
	 */
43
	public function read(string $filename):ReaderInterface{
44
		$this->loadFile($filename);
45
46
		if($this->header['Signature'] !== "\x58\x45\x54\x4c"){ // XETL
47
			throw new WSDBException('invalid LTEX');
48
		}
49
50
		\fseek($this->fh, $this->headerSize + $this->header['LongNameStringPtr']);
51
52
		$this->prettyname = $this->decodeString(\fread($this->fh, $this->header['LongNameStringLength'] * 2));
53
		$this->name       = 'LocalizedText_'.$this::LCID[$this->header['LCID']];
54
		$this->cols       = [
55
			['name' => 'ID',            'header' => ['DataType' =>   3]],
56
			['name' => 'LocalizedText', 'header' => ['DataType' => 130]],
57
		];
58
59
		$this->readData();
60
61
		$this->logger->info($this->prettyname.' ('.$this->header['LCID'].', '.$this::LCID[$this->header['LCID']].'), rows: '.$this->header['EntryCount']);
62
63
		return $this;
64
	}
65
66
	/**
67
	 * @return void
68
	 */
69
	protected function readData():void{
70
		\fseek($this->fh, $this->headerSize + $this->header['EntryIndexPtr']);
71
72
		$this->data = array_fill(0, $this->header['EntryCount'], null);
73
74
		foreach($this->data as $i => $_){
75
			// get the id and offset for the data block
76
			$c = \unpack('Lid/Loffset', \fread($this->fh, 8));
77
			// save the current position
78
			$p = \ftell($this->fh);
79
80
			// seek forward to the data block
81
			\fseek($this->fh, $this->headerSize + $this->header['NameStorePtr'] + $c['offset'] * 2);
82
83
			$v = '';
84
			// read until we hit a double nul or the void
85
			do{
86
				$s = \fread($this->fh, 2);
87
				$v .= $s;
88
			}
89
			while($s !== "\x00\x00" && $s !== '');
90
91
			$this->data[$i] = ['ID' => $c['id'], 'LocalizedText' => $this->decodeString($v)];
92
93
			// restore the previous position
94
			\fseek($this->fh, $p);
95
		}
96
97
	}
98
99
}
100